From 694f9bfbf7f1af19108461c7e00d133e55082bce Mon Sep 17 00:00:00 2001 From: Manuel Nickschas Date: Fri, 25 May 2012 16:05:34 +0200 Subject: [PATCH] Reformat ALL the source! MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Yes, yes. After stubborningly refusing to switch to a more readable coding style for years, I finally give in. Our old, quite compact, 2-indent style was born from my time with homecomputers, where every whitespace was a waste. Later (and mostly thanks to EgS), I did see the light, e.g. changed from one-letter variable names to useful ones, but still shied away from reformatting the whole source, touching every line, destroying the historical context as shown by svn and git blame. However, since I'm now doing Qt-related programming as my day job, and use a proper (Qt-like) coding style there, it has become increasingly annoying for myself to switch to another style in those long hacking nights working on Quassel, and so I decided to Just Do It™. Helps that Git nowadays can ignore whitespace changes when blaming, or diffing, or patching, so this shouldn't be too much of an annoyance for existing patches. Feedback from the community was also positive... So now we use a style that should be pretty close to the Qt Coding Style [1], which not only covers the indentation, but also things like newline-after-function-head. Reformatting was done automagically using uncrustify [2], a script and config file is in scripts/manage/. Please don't run it over the whole codebase again, as there are some false positives and weird formattings that will have to be manually fixed over time. You can use it for reformatting existing patches or MRs, though. [1] http://qt-project.org/wiki/Qt_Coding_Style [2] http://uncrustify.sourceforge.net/ --- scripts/manage/format_source.cfg | 176 + scripts/manage/format_source.sh | 32 + src/client/abstractmessageprocessor.cpp | 2 +- src/client/abstractmessageprocessor.h | 22 +- src/client/abstractui.h | 24 +- src/client/backlogrequester.cpp | 131 +- src/client/backlogrequester.h | 94 +- src/client/backlogsettings.h | 34 +- src/client/buffermodel.cpp | 197 +- src/client/buffermodel.h | 55 +- src/client/buffersettings.cpp | 39 +- src/client/buffersettings.h | 54 +- src/client/bufferviewoverlay.cpp | 430 ++- src/client/bufferviewoverlay.h | 74 +- src/client/client.cpp | 782 ++-- src/client/client.h | 320 +- src/client/clientaliasmanager.cpp | 9 +- src/client/clientaliasmanager.h | 15 +- src/client/clientbacklogmanager.cpp | 229 +- src/client/clientbacklogmanager.h | 54 +- src/client/clientbufferviewconfig.cpp | 16 +- src/client/clientbufferviewconfig.h | 22 +- src/client/clientbufferviewmanager.cpp | 46 +- src/client/clientbufferviewmanager.h | 18 +- src/client/clientcoreinfo.h | 20 +- src/client/clientidentity.cpp | 96 +- src/client/clientidentity.h | 61 +- src/client/clientignorelistmanager.cpp | 43 +- src/client/clientignorelistmanager.h | 29 +- src/client/clientirclisthelper.cpp | 44 +- src/client/clientirclisthelper.h | 28 +- src/client/clientsettings.cpp | 433 ++- src/client/clientsettings.h | 167 +- src/client/clientuserinputhandler.cpp | 150 +- src/client/clientuserinputhandler.h | 34 +- src/client/coreaccount.cpp | 205 +- src/client/coreaccount.h | 122 +- src/client/coreaccountmodel.cpp | 342 +- src/client/coreaccountmodel.h | 74 +- src/client/coreconnection.cpp | 1117 +++--- src/client/coreconnection.h | 212 +- src/client/execwrapper.cpp | 172 +- src/client/execwrapper.h | 36 +- src/client/irclistmodel.cpp | 104 +- src/client/irclistmodel.h | 26 +- src/client/messagefilter.cpp | 324 +- src/client/messagefilter.h | 52 +- src/client/messagemodel.cpp | 767 ++-- src/client/messagemodel.h | 202 +- src/client/networkmodel.cpp | 1962 +++++----- src/client/networkmodel.h | 442 +-- src/client/selectionmodelsynchronizer.cpp | 377 +- src/client/selectionmodelsynchronizer.h | 58 +- src/client/treemodel.cpp | 855 +++-- src/client/treemodel.h | 219 +- src/common/abstractcliparser.h | 74 +- src/common/aliasmanager.cpp | 275 +- src/common/aliasmanager.h | 63 +- src/common/backlogmanager.cpp | 15 +- src/common/backlogmanager.h | 24 +- src/common/basichandler.cpp | 98 +- src/common/basichandler.h | 33 +- src/common/bufferinfo.cpp | 62 +- src/common/bufferinfo.h | 86 +- src/common/buffersyncer.cpp | 161 +- src/common/buffersyncer.h | 74 +- src/common/bufferviewconfig.cpp | 315 +- src/common/bufferviewconfig.h | 151 +- src/common/bufferviewmanager.cpp | 104 +- src/common/bufferviewmanager.h | 50 +- src/common/cliparser.cpp | 350 +- src/common/cliparser.h | 30 +- src/common/coreinfo.h | 16 +- src/common/ctcpevent.cpp | 40 +- src/common/ctcpevent.h | 100 +- src/common/event.cpp | 158 +- src/common/event.h | 65 +- src/common/eventmanager.cpp | 438 ++- src/common/eventmanager.h | 283 +- src/common/genversion.cpp | 163 +- src/common/identity.cpp | 400 +- src/common/identity.h | 230 +- src/common/ignorelistmanager.cpp | 292 +- src/common/ignorelistmanager.h | 216 +- src/common/ircchannel.cpp | 836 ++-- src/common/ircchannel.h | 148 +- src/common/ircevent.cpp | 66 +- src/common/ircevent.h | 151 +- src/common/irclisthelper.h | 29 +- src/common/ircuser.cpp | 431 ++- src/common/ircuser.h | 274 +- src/common/logbacktrace_unix.cpp | 99 +- src/common/logbacktrace_win.cpp | 294 +- src/common/logger.cpp | 130 +- src/common/logger.h | 44 +- src/common/mac_utils.cpp | 21 +- src/common/main.cpp | 118 +- src/common/message.cpp | 61 +- src/common/message.h | 133 +- src/common/messageevent.cpp | 90 +- src/common/messageevent.h | 81 +- src/common/network.cpp | 1611 ++++---- src/common/network.h | 612 +-- src/common/networkconfig.cpp | 111 +- src/common/networkconfig.h | 96 +- src/common/networkevent.cpp | 91 +- src/common/networkevent.h | 159 +- src/common/quassel.cpp | 666 ++-- src/common/quassel.h | 266 +- src/common/settings.cpp | 155 +- src/common/settings.h | 140 +- src/common/signalproxy.cpp | 1938 +++++----- src/common/signalproxy.h | 431 +-- src/common/syncableobject.cpp | 266 +- src/common/syncableobject.h | 106 +- src/common/types.h | 38 +- src/common/util.cpp | 221 +- src/common/util.h | 29 +- src/core/abstractsqlstorage.cpp | 792 ++-- src/core/abstractsqlstorage.h | 488 +-- src/core/cipher.cpp | 669 ++-- src/core/cipher.h | 12 +- src/core/core.cpp | 1658 ++++---- src/core/core.h | 902 +++-- src/core/corealiasmanager.cpp | 56 +- src/core/corealiasmanager.h | 19 +- src/core/coreapplication.cpp | 86 +- src/core/coreapplication.h | 19 +- src/core/corebacklogmanager.cpp | 134 +- src/core/corebacklogmanager.h | 18 +- src/core/corebasichandler.cpp | 154 +- src/core/corebasichandler.h | 55 +- src/core/corebuffersyncer.cpp | 222 +- src/core/corebuffersyncer.h | 44 +- src/core/corebufferviewconfig.cpp | 9 +- src/core/corebufferviewconfig.h | 26 +- src/core/corebufferviewmanager.cpp | 110 +- src/core/corebufferviewmanager.h | 27 +- src/core/corecoreinfo.cpp | 18 +- src/core/corecoreinfo.h | 18 +- src/core/coreeventmanager.h | 15 +- src/core/coreidentity.cpp | 94 +- src/core/coreidentity.h | 73 +- src/core/coreignorelistmanager.cpp | 47 +- src/core/coreignorelistmanager.h | 31 +- src/core/coreircchannel.cpp | 51 +- src/core/coreircchannel.h | 26 +- src/core/coreirclisthelper.cpp | 111 +- src/core/coreirclisthelper.h | 36 +- src/core/coreircuser.cpp | 30 +- src/core/coreircuser.h | 20 +- src/core/corenetwork.cpp | 1359 ++++--- src/core/corenetwork.h | 262 +- src/core/corenetworkconfig.cpp | 32 +- src/core/corenetworkconfig.h | 28 +- src/core/coresession.cpp | 944 ++--- src/core/coresession.h | 236 +- src/core/coresessioneventprocessor.cpp | 1341 ++++--- src/core/coresessioneventprocessor.h | 204 +- src/core/coresettings.cpp | 38 +- src/core/coresettings.h | 8 +- src/core/coreuserinputhandler.cpp | 1115 +++--- src/core/coreuserinputhandler.h | 116 +- src/core/coreusersettings.cpp | 82 +- src/core/coreusersettings.h | 9 +- src/core/ctcpparser.cpp | 382 +- src/core/ctcpparser.h | 78 +- src/core/eventstringifier.cpp | 878 +++-- src/core/eventstringifier.h | 155 +- src/core/ircparser.cpp | 473 +-- src/core/ircparser.h | 24 +- src/core/netsplit.cpp | 231 +- src/core/netsplit.h | 201 +- src/core/oidentdconfiggenerator.cpp | 158 +- src/core/oidentdconfiggenerator.h | 49 +- src/core/postgresqlstorage.cpp | 3218 ++++++++-------- src/core/postgresqlstorage.h | 257 +- src/core/sessionthread.cpp | 124 +- src/core/sessionthread.h | 48 +- src/core/sqlitestorage.cpp | 3371 +++++++++-------- src/core/sqlitestorage.h | 218 +- src/core/sslserver.cpp | 174 +- src/core/sslserver.h | 32 +- src/core/storage.cpp | 8 +- src/core/storage.h | 754 ++-- src/qtui/aboutdlg.cpp | 279 +- src/qtui/aboutdlg.h | 10 +- src/qtui/awaylogfilter.cpp | 46 +- src/qtui/awaylogfilter.h | 14 +- src/qtui/awaylogview.cpp | 40 +- src/qtui/awaylogview.h | 10 +- src/qtui/bufferwidget.cpp | 400 +- src/qtui/bufferwidget.h | 48 +- src/qtui/channellistdlg.cpp | 206 +- src/qtui/channellistdlg.h | 44 +- src/qtui/chatitem.cpp | 1262 +++--- src/qtui/chatitem.h | 341 +- src/qtui/chatline.cpp | 350 +- src/qtui/chatline.h | 131 +- src/qtui/chatlinemodel.cpp | 78 +- src/qtui/chatlinemodel.h | 53 +- src/qtui/chatlinemodelitem.cpp | 353 +- src/qtui/chatlinemodelitem.h | 62 +- src/qtui/chatmonitorfilter.cpp | 238 +- src/qtui/chatmonitorfilter.h | 58 +- src/qtui/chatmonitorview.cpp | 112 +- src/qtui/chatmonitorview.h | 22 +- src/qtui/chatscene.cpp | 1764 +++++---- src/qtui/chatscene.h | 350 +- src/qtui/chatview.cpp | 498 +-- src/qtui/chatview.h | 139 +- src/qtui/chatviewsearchbar.cpp | 68 +- src/qtui/chatviewsearchbar.h | 36 +- src/qtui/chatviewsearchcontroller.cpp | 633 ++-- src/qtui/chatviewsearchcontroller.h | 97 +- src/qtui/chatviewsettings.cpp | 9 +- src/qtui/chatviewsettings.h | 31 +- src/qtui/columnhandleitem.cpp | 182 +- src/qtui/columnhandleitem.h | 62 +- src/qtui/coreconfigwizard.cpp | 509 +-- src/qtui/coreconfigwizard.h | 163 +- src/qtui/coreconnectdlg.cpp | 98 +- src/qtui/coreconnectdlg.h | 30 +- src/qtui/coreconnectionstatuswidget.cpp | 106 +- src/qtui/coreconnectionstatuswidget.h | 22 +- src/qtui/coreinfodlg.cpp | 42 +- src/qtui/coreinfodlg.h | 20 +- src/qtui/debugbufferviewoverlay.cpp | 124 +- src/qtui/debugbufferviewoverlay.h | 34 +- src/qtui/debugconsole.cpp | 29 +- src/qtui/debugconsole.h | 20 +- src/qtui/debuglogwidget.cpp | 23 +- src/qtui/debuglogwidget.h | 12 +- src/qtui/debugmessagemodelfilter.cpp | 48 +- src/qtui/debugmessagemodelfilter.h | 12 +- src/qtui/indicatornotificationbackend.cpp | 257 +- src/qtui/indicatornotificationbackend.h | 54 +- src/qtui/inputwidget.cpp | 856 +++-- src/qtui/inputwidget.h | 131 +- src/qtui/ircconnectionwizard.cpp | 188 +- src/qtui/ircconnectionwizard.h | 52 +- src/qtui/knotificationbackend.cpp | 171 +- src/qtui/knotificationbackend.h | 44 +- src/qtui/legacysystemtray.cpp | 212 +- src/qtui/legacysystemtray.h | 55 +- src/qtui/mainpage.cpp | 24 +- src/qtui/mainpage.h | 12 +- src/qtui/mainwin.cpp | 2156 ++++++----- src/qtui/mainwin.h | 20 +- src/qtui/markerlineitem.cpp | 57 +- src/qtui/markerlineitem.h | 30 +- src/qtui/monoapplication.cpp | 56 +- src/qtui/monoapplication.h | 18 +- src/qtui/msgprocessorstatuswidget.cpp | 27 +- src/qtui/msgprocessorstatuswidget.h | 12 +- src/qtui/nicklistwidget.cpp | 255 +- src/qtui/nicklistwidget.h | 43 +- src/qtui/phononnotificationbackend.cpp | 193 +- src/qtui/phononnotificationbackend.h | 60 +- src/qtui/qtui.cpp | 273 +- src/qtui/qtui.h | 68 +- src/qtui/qtuiapplication.cpp | 176 +- src/qtui/qtuiapplication.h | 27 +- src/qtui/qtuimessageprocessor.cpp | 268 +- src/qtui/qtuimessageprocessor.h | 78 +- src/qtui/qtuisettings.cpp | 28 +- src/qtui/qtuisettings.h | 26 +- src/qtui/qtuistyle.cpp | 185 +- src/qtui/qtuistyle.h | 28 +- src/qtui/settingsdlg.cpp | 308 +- src/qtui/settingsdlg.h | 45 +- src/qtui/settingspagedlg.cpp | 147 +- src/qtui/settingspagedlg.h | 15 +- src/qtui/settingspages/aliasesmodel.cpp | 364 +- src/qtui/settingspages/aliasesmodel.h | 77 +- .../settingspages/aliasessettingspage.cpp | 82 +- src/qtui/settingspages/aliasessettingspage.h | 26 +- .../settingspages/appearancesettingspage.cpp | 375 +- .../settingspages/appearancesettingspage.h | 36 +- .../settingspages/backlogsettingspage.cpp | 60 +- src/qtui/settingspages/backlogsettingspage.h | 22 +- .../settingspages/bufferviewsettingspage.cpp | 872 +++-- .../settingspages/bufferviewsettingspage.h | 105 +- .../settingspages/chatmonitorsettingspage.cpp | 346 +- .../settingspages/chatmonitorsettingspage.h | 15 +- .../settingspages/chatviewsettingspage.cpp | 32 +- src/qtui/settingspages/chatviewsettingspage.h | 16 +- .../settingspages/connectionsettingspage.cpp | 137 +- .../settingspages/connectionsettingspage.h | 14 +- .../settingspages/coreaccountsettingspage.cpp | 417 +- .../settingspages/coreaccountsettingspage.h | 48 +- .../coreconnectionsettingspage.cpp | 101 +- .../coreconnectionsettingspage.h | 28 +- .../settingspages/highlightsettingspage.cpp | 402 +- .../settingspages/highlightsettingspage.h | 28 +- .../settingspages/identitiessettingspage.cpp | 653 ++-- .../settingspages/identitiessettingspage.h | 96 +- src/qtui/settingspages/identityeditwidget.cpp | 613 +-- src/qtui/settingspages/identityeditwidget.h | 85 +- src/qtui/settingspages/ignorelistmodel.cpp | 423 ++- src/qtui/settingspages/ignorelistmodel.h | 82 +- .../settingspages/ignorelistsettingspage.cpp | 508 +-- .../settingspages/ignorelistsettingspage.h | 83 +- .../settingspages/inputwidgetsettingspage.cpp | 8 +- .../settingspages/inputwidgetsettingspage.h | 14 +- .../settingspages/itemviewsettingspage.cpp | 79 +- src/qtui/settingspages/itemviewsettingspage.h | 24 +- src/qtui/settingspages/keysequencewidget.cpp | 558 +-- src/qtui/settingspages/keysequencewidget.h | 77 +- .../settingspages/networkssettingspage.cpp | 1457 +++---- src/qtui/settingspages/networkssettingspage.h | 148 +- .../notificationssettingspage.cpp | 77 +- .../settingspages/notificationssettingspage.h | 14 +- src/qtui/settingspages/previewbufferview.h | 12 +- src/qtui/settingspages/shortcutsmodel.cpp | 322 +- src/qtui/settingspages/shortcutsmodel.h | 94 +- .../settingspages/shortcutssettingspage.cpp | 190 +- .../settingspages/shortcutssettingspage.h | 44 +- .../settingspages/topicwidgetsettingspage.cpp | 6 +- .../settingspages/topicwidgetsettingspage.h | 14 +- src/qtui/simplenetworkeditor.cpp | 177 +- src/qtui/simplenetworkeditor.h | 38 +- src/qtui/sslinfodlg.cpp | 78 +- src/qtui/sslinfodlg.h | 16 +- src/qtui/statusnotifieritem.cpp | 423 ++- src/qtui/statusnotifieritem.h | 76 +- src/qtui/statusnotifieritemdbus.cpp | 64 +- src/qtui/systemtray.cpp | 207 +- src/qtui/systemtray.h | 160 +- src/qtui/systraynotificationbackend.cpp | 203 +- src/qtui/systraynotificationbackend.h | 58 +- src/qtui/taskbarnotificationbackend.cpp | 136 +- src/qtui/taskbarnotificationbackend.h | 50 +- src/qtui/titlesetter.cpp | 48 +- src/qtui/titlesetter.h | 12 +- src/qtui/topicwidget.cpp | 349 +- src/qtui/topicwidget.h | 48 +- src/qtui/verticaldock.cpp | 94 +- src/qtui/verticaldock.h | 41 +- src/qtui/webpreviewitem.cpp | 51 +- src/qtui/webpreviewitem.h | 13 +- src/uisupport/abstractbuffercontainer.cpp | 127 +- src/uisupport/abstractbuffercontainer.h | 71 +- src/uisupport/abstractitemview.cpp | 47 +- src/uisupport/abstractitemview.h | 38 +- src/uisupport/abstractnotificationbackend.h | 61 +- src/uisupport/action.cpp | 101 +- src/uisupport/action.h | 41 +- src/uisupport/actioncollection.cpp | 344 +- src/uisupport/actioncollection.h | 40 +- src/uisupport/bufferhotlistfilter.cpp | 57 +- src/uisupport/bufferhotlistfilter.h | 14 +- src/uisupport/bufferview.cpp | 908 +++-- src/uisupport/bufferview.h | 133 +- src/uisupport/bufferviewfilter.cpp | 809 ++-- src/uisupport/bufferviewfilter.h | 107 +- src/uisupport/bufferviewoverlayfilter.cpp | 114 +- src/uisupport/bufferviewoverlayfilter.h | 16 +- src/uisupport/clearablelineedit.cpp | 44 +- src/uisupport/clearablelineedit.h | 14 +- src/uisupport/clickable.cpp | 166 +- src/uisupport/clickable.h | 49 +- src/uisupport/clickablelabel.cpp | 13 +- src/uisupport/clickablelabel.h | 12 +- src/uisupport/colorbutton.cpp | 43 +- src/uisupport/colorbutton.h | 26 +- src/uisupport/contextmenuactionprovider.cpp | 814 ++-- src/uisupport/contextmenuactionprovider.h | 80 +- src/uisupport/flatproxymodel.cpp | 1071 +++--- src/uisupport/flatproxymodel.h | 123 +- src/uisupport/fontselector.cpp | 59 +- src/uisupport/fontselector.h | 26 +- src/uisupport/graphicalui.cpp | 343 +- src/uisupport/graphicalui.h | 125 +- src/uisupport/icon.cpp | 26 +- src/uisupport/icon.h | 20 +- src/uisupport/iconloader.cpp | 231 +- src/uisupport/iconloader.h | 94 +- src/uisupport/kcmdlinewrapper.cpp | 48 +- src/uisupport/kcmdlinewrapper.h | 18 +- src/uisupport/multilineedit.cpp | 1157 +++--- src/uisupport/multilineedit.h | 150 +- src/uisupport/networkmodelcontroller.cpp | 862 +++-- src/uisupport/networkmodelcontroller.h | 271 +- src/uisupport/nickview.cpp | 141 +- src/uisupport/nickview.h | 30 +- src/uisupport/nickviewfilter.cpp | 46 +- src/uisupport/nickviewfilter.h | 18 +- src/uisupport/qssparser.cpp | 1233 +++--- src/uisupport/qssparser.h | 16 +- src/uisupport/resizingstackedwidget.cpp | 22 +- src/uisupport/resizingstackedwidget.h | 12 +- src/uisupport/settingspage.cpp | 332 +- src/uisupport/settingspage.h | 166 +- src/uisupport/styledlabel.cpp | 333 +- src/uisupport/styledlabel.h | 92 +- src/uisupport/tabcompleter.cpp | 265 +- src/uisupport/tabcompleter.h | 59 +- src/uisupport/toolbaractionprovider.cpp | 291 +- src/uisupport/toolbaractionprovider.h | 54 +- src/uisupport/uisettings.cpp | 177 +- src/uisupport/uisettings.h | 71 +- src/uisupport/uistyle.cpp | 1245 +++--- src/uisupport/uistyle.h | 322 +- 404 files changed, 48380 insertions(+), 41690 deletions(-) create mode 100644 scripts/manage/format_source.cfg create mode 100755 scripts/manage/format_source.sh diff --git a/scripts/manage/format_source.cfg b/scripts/manage/format_source.cfg new file mode 100644 index 00000000..4af3870d --- /dev/null +++ b/scripts/manage/format_source.cfg @@ -0,0 +1,176 @@ +tok_split_gte=false +utf8_byte=false +utf8_force=false +indent_cmt_with_tabs=false +indent_align_string=true +indent_braces=false +indent_braces_no_func=false +indent_braces_no_class=false +indent_braces_no_struct=false +indent_brace_parent=false +indent_namespace=false +indent_extern=false +indent_class=true +indent_class_colon=false +indent_else_if=false +indent_var_def_cont=false +indent_func_call_param=true +indent_func_def_param=true +indent_func_proto_param=true +indent_func_class_param=true +indent_func_ctor_var_param=true +indent_template_param=true +indent_func_param_double=false +indent_relative_single_line_comments=false +indent_col1_comment=false +indent_access_spec_body=false +indent_paren_nl=false +indent_comma_paren=false +indent_bool_paren=false +indent_first_bool_expr=false +indent_square_nl=false +indent_preserve_sql=false +indent_align_assign=true +sp_balance_nested_parens=false +align_keep_tabs=false +align_with_tabs=false +align_on_tabstop=false +align_number_left=false +align_func_params=false +align_same_func_call_params=false +align_var_def_colon=false +align_var_def_attribute=false +align_var_def_inline=false +align_right_cmt_mix=true +align_on_operator=false +align_mix_var_proto=false +align_single_line_func=false +align_single_line_brace=false +align_nl_cont=false +align_left_shift=true +align_oc_decl_colon=false +nl_collapse_empty_body=false +nl_assign_leave_one_liners=true +nl_class_leave_one_liners=true +nl_enum_leave_one_liners=true +nl_getset_leave_one_liners=true +nl_func_leave_one_liners=true +nl_if_leave_one_liners=false +nl_multi_line_cond=true +nl_multi_line_define=false +nl_before_case=false +nl_after_case=true +nl_after_return=false +nl_after_semicolon=false +nl_after_brace_open=false +nl_after_brace_open_cmt=false +nl_after_vbrace_open=false +nl_after_vbrace_open_empty=false +nl_after_brace_close=true +nl_after_vbrace_close=true +nl_define_macro=false +nl_squeeze_ifdef=false +nl_ds_struct_enum_cmt=false +nl_ds_struct_enum_close_brace=false +nl_create_if_one_liner=false +nl_create_for_one_liner=false +nl_create_while_one_liner=false +ls_for_split_full=false +ls_func_split_full=false +nl_after_multiline_comment=false +eat_blanks_after_open_brace=true +eat_blanks_before_close_brace=true +mod_full_brace_if_chain=false +mod_pawn_semicolon=false +mod_full_paren_if_bool=false +mod_remove_extra_semicolon=false +mod_sort_import=false +mod_sort_using=false +mod_sort_include=false +mod_move_case_break=false +mod_remove_empty_return=false +cmt_indent_multi=false +cmt_c_group=false +cmt_c_nl_start=false +cmt_c_nl_end=false +cmt_cpp_group=false +cmt_cpp_nl_start=false +cmt_cpp_nl_end=false +cmt_cpp_to_c=false +cmt_star_cont=false +cmt_multi_check_last=true +cmt_insert_before_preproc=false +pp_indent_at_level=false +pp_region_indent_code=false +pp_if_indent_code=false +pp_define_at_level=false +indent_columns=4 +nl_end_of_file_min=1 +nl_max=2 +nl_after_func_body=3 +nl_after_class=3 +indent_with_tabs=0 +sp_assign=add +sp_assign_default=add +sp_before_assign=add +sp_after_assign=add +sp_enum_assign=add +sp_enum_before_assign=add +sp_enum_after_assign=add +sp_pp_concat=ignore +sp_pp_stringify=ignore +sp_bool=add +sp_compare=add +sp_inside_paren=remove +sp_paren_paren=remove +sp_paren_brace=add +sp_before_ptr_star=add +sp_before_unnamed_ptr_star=add +sp_between_ptr_star=remove +sp_after_ptr_star=remove +sp_before_byref=add +sp_after_byref=remove +sp_template_angle=remove +sp_before_angle=remove +sp_inside_angle=remove +sp_after_angle=add +sp_angle_paren=remove +sp_before_sparen=add +sp_inside_sparen=remove +sp_after_sparen=add +sp_sparen_brace=add +sp_after_semi_for_empty=remove +sp_before_square=remove +sp_before_squares=remove +sp_inside_square=remove +sp_after_comma=add +sp_before_comma=remove +sp_after_class_colon=add +sp_before_class_colon=add +sp_before_case_colon=remove +sp_after_operator=remove +sp_after_operator_sym=remove +sp_after_cast=remove +sp_inside_paren_cast=remove +sp_cpp_cast_paren=remove +sp_sizeof_paren=remove +sp_inside_braces_enum=add +sp_inside_braces_struct=add +sp_inside_braces=add +sp_inside_braces_empty=remove +sp_func_proto_paren=remove +sp_func_def_paren=remove +sp_inside_fparens=remove +sp_inside_fparen=remove +sp_square_fparen=remove +sp_fparen_brace=add +sp_func_call_paren=remove +sp_else_brace=add +sp_brace_else=add +sp_case_label=force +nl_start_of_file=remove +nl_end_of_file=add +nl_case_colon_brace=ignore +nl_class_brace=add +nl_fdef_brace=add +pos_class_comma=lead diff --git a/scripts/manage/format_source.sh b/scripts/manage/format_source.sh new file mode 100755 index 00000000..5d407522 --- /dev/null +++ b/scripts/manage/format_source.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +# format_source.sh dirname - indent the whole source tree +# format_source.sh filename - indent a single file + +if [ -d "$1" ]; then +#echo "Dir ${1} exists" + +file_list=`find ${1} -name "*.cpp" -or -name "*.h" -type f` +for file2indent in $file_list +do +echo "Indenting file $file2indent" +#!/bin/bash +uncrustify -f "$file2indent" -c "./format_source.cfg" -o indentoutput.tmp +mv indentoutput.tmp "$file2indent" + +done +else +if [ -f "$1" ]; then +echo "Indenting one file $1" +#!/bin/bash +uncrustify -f "$1" -c "./format_source.cfg" -o indentoutput.tmp +mv indentoutput.tmp "$1" + +else +echo "ERROR: As parameter given directory or file does not exist!" +echo "Syntax is: format_source.sh dirname filesuffix" +echo "Syntax is: format_source.sh filename" +echo "Example: format_source.sh temp cpp" +exit 1 +fi +fi diff --git a/src/client/abstractmessageprocessor.cpp b/src/client/abstractmessageprocessor.cpp index 2419c316..025789f3 100644 --- a/src/client/abstractmessageprocessor.cpp +++ b/src/client/abstractmessageprocessor.cpp @@ -23,6 +23,6 @@ #include "client.h" AbstractMessageProcessor::AbstractMessageProcessor(QObject *parent) - : QObject(parent) + : QObject(parent) { } diff --git a/src/client/abstractmessageprocessor.h b/src/client/abstractmessageprocessor.h index b38138e2..7725a4be 100644 --- a/src/client/abstractmessageprocessor.h +++ b/src/client/abstractmessageprocessor.h @@ -25,22 +25,24 @@ #include "message.h" #include "networkmodel.h" -class AbstractMessageProcessor : public QObject { - Q_OBJECT +class AbstractMessageProcessor : public QObject +{ + Q_OBJECT public: - AbstractMessageProcessor(QObject *parent); - virtual void reset() = 0; + AbstractMessageProcessor(QObject *parent); + virtual void reset() = 0; public slots: - virtual void process(Message &msg) = 0; - virtual void process(QList &msgs) = 0; + virtual void process(Message &msg) = 0; + virtual void process(QList &msgs) = 0; protected: - // updateBufferActivity also sets the Message::Redirected flag which is later used - // to determine where a message should be displayed. therefore it's crucial that it - // is called before inserting the message into the model - inline void preProcess(Message &msg) { Client::networkModel()->updateBufferActivity(msg); } + // updateBufferActivity also sets the Message::Redirected flag which is later used + // to determine where a message should be displayed. therefore it's crucial that it + // is called before inserting the message into the model + inline void preProcess(Message &msg) { Client::networkModel()->updateBufferActivity(msg); } }; + #endif diff --git a/src/client/abstractui.h b/src/client/abstractui.h index 54ae4308..4f63b690 100644 --- a/src/client/abstractui.h +++ b/src/client/abstractui.h @@ -33,23 +33,25 @@ class AbstractActionProvider; class QAction; class QMenu; -class AbstractUi : public QObject { - Q_OBJECT +class AbstractUi : public QObject +{ + Q_OBJECT public: - AbstractUi(QObject *parent = 0) : QObject(parent) {} - virtual ~AbstractUi() {} - virtual void init() = 0; // called after the client is initialized - virtual MessageModel *createMessageModel(QObject *parent) = 0; - virtual AbstractMessageProcessor *createMessageProcessor(QObject *parent) = 0; + AbstractUi(QObject *parent = 0) : QObject(parent) {} + virtual ~AbstractUi() {} + virtual void init() = 0; // called after the client is initialized + virtual MessageModel *createMessageModel(QObject *parent) = 0; + virtual AbstractMessageProcessor *createMessageProcessor(QObject *parent) = 0; protected slots: - virtual void connectedToCore() {} - virtual void disconnectedFromCore() {} + virtual void connectedToCore() {} + virtual void disconnectedFromCore() {} signals: - void connectToCore(const QVariantMap &connInfo); - void disconnectFromCore(); + void connectToCore(const QVariantMap &connInfo); + void disconnectFromCore(); }; + #endif diff --git a/src/client/backlogrequester.cpp b/src/client/backlogrequester.cpp index 4a6524cc..23ce6969 100644 --- a/src/client/backlogrequester.cpp +++ b/src/client/backlogrequester.cpp @@ -27,101 +27,120 @@ #include "clientbacklogmanager.h" BacklogRequester::BacklogRequester(bool buffering, RequesterType requesterType, ClientBacklogManager *backlogManager) - : backlogManager(backlogManager), + : backlogManager(backlogManager), _isBuffering(buffering), _requesterType(requesterType), _totalBuffers(0) { - Q_ASSERT(backlogManager); + Q_ASSERT(backlogManager); } -void BacklogRequester::setWaitingBuffers(const QSet &buffers) { - _buffersWaiting = buffers; - _totalBuffers = _buffersWaiting.count(); + +void BacklogRequester::setWaitingBuffers(const QSet &buffers) +{ + _buffersWaiting = buffers; + _totalBuffers = _buffersWaiting.count(); } -void BacklogRequester::addWaitingBuffer(BufferId buffer) { - _buffersWaiting << buffer; - _totalBuffers++; + +void BacklogRequester::addWaitingBuffer(BufferId buffer) +{ + _buffersWaiting << buffer; + _totalBuffers++; } -bool BacklogRequester::buffer(BufferId bufferId, const MessageList &messages) { - _bufferedMessages << messages; - _buffersWaiting.remove(bufferId); - return !_buffersWaiting.isEmpty(); + +bool BacklogRequester::buffer(BufferId bufferId, const MessageList &messages) +{ + _bufferedMessages << messages; + _buffersWaiting.remove(bufferId); + return !_buffersWaiting.isEmpty(); } -BufferIdList BacklogRequester::allBufferIds() const { - QSet bufferIds = Client::bufferViewOverlay()->bufferIds(); - bufferIds += Client::bufferViewOverlay()->tempRemovedBufferIds(); - return bufferIds.toList(); + +BufferIdList BacklogRequester::allBufferIds() const +{ + QSet bufferIds = Client::bufferViewOverlay()->bufferIds(); + bufferIds += Client::bufferViewOverlay()->tempRemovedBufferIds(); + return bufferIds.toList(); } -void BacklogRequester::flushBuffer() { - if(!_buffersWaiting.isEmpty()) { - qWarning() << Q_FUNC_INFO << "was called before all backlog was received:" - << _buffersWaiting.count() << "buffers are waiting."; - } - _bufferedMessages.clear(); - _totalBuffers = 0; - _buffersWaiting.clear(); + +void BacklogRequester::flushBuffer() +{ + if (!_buffersWaiting.isEmpty()) { + qWarning() << Q_FUNC_INFO << "was called before all backlog was received:" + << _buffersWaiting.count() << "buffers are waiting."; + } + _bufferedMessages.clear(); + _totalBuffers = 0; + _buffersWaiting.clear(); } + // ======================================== // FIXED BACKLOG REQUESTER // ======================================== FixedBacklogRequester::FixedBacklogRequester(ClientBacklogManager *backlogManager) - : BacklogRequester(true, BacklogRequester::PerBufferFixed, backlogManager) + : BacklogRequester(true, BacklogRequester::PerBufferFixed, backlogManager) { - BacklogSettings backlogSettings; - _backlogCount = backlogSettings.fixedBacklogAmount(); + BacklogSettings backlogSettings; + _backlogCount = backlogSettings.fixedBacklogAmount(); } -void FixedBacklogRequester::requestBacklog(const BufferIdList &bufferIds) { - setWaitingBuffers(bufferIds); - backlogManager->emitMessagesRequested(QObject::tr("Requesting a total of up to %1 backlog messages for %2 buffers").arg(_backlogCount * bufferIds.count()).arg(bufferIds.count())); - foreach(BufferId bufferId, bufferIds) { - backlogManager->requestBacklog(bufferId, -1, -1, _backlogCount); - } + +void FixedBacklogRequester::requestBacklog(const BufferIdList &bufferIds) +{ + setWaitingBuffers(bufferIds); + backlogManager->emitMessagesRequested(QObject::tr("Requesting a total of up to %1 backlog messages for %2 buffers").arg(_backlogCount * bufferIds.count()).arg(bufferIds.count())); + foreach(BufferId bufferId, bufferIds) { + backlogManager->requestBacklog(bufferId, -1, -1, _backlogCount); + } } + // ======================================== // GLOBAL UNREAD BACKLOG REQUESTER // ======================================== GlobalUnreadBacklogRequester::GlobalUnreadBacklogRequester(ClientBacklogManager *backlogManager) - : BacklogRequester(false, BacklogRequester::GlobalUnread, backlogManager) + : BacklogRequester(false, BacklogRequester::GlobalUnread, backlogManager) { - BacklogSettings backlogSettings; - _limit = backlogSettings.globalUnreadBacklogLimit(); - _additional = backlogSettings.globalUnreadBacklogAdditional(); + BacklogSettings backlogSettings; + _limit = backlogSettings.globalUnreadBacklogLimit(); + _additional = backlogSettings.globalUnreadBacklogAdditional(); } -void GlobalUnreadBacklogRequester::requestInitialBacklog() { - MsgId oldestUnreadMessage; - foreach(BufferId bufferId, allBufferIds()) { - MsgId msgId = Client::networkModel()->lastSeenMsgId(bufferId); - if(!oldestUnreadMessage.isValid() || oldestUnreadMessage > msgId) - oldestUnreadMessage = msgId; - } - backlogManager->emitMessagesRequested(QObject::tr("Requesting up to %1 of all unread backlog messages (plus additional %2)").arg(_limit).arg(_additional)); - backlogManager->requestBacklogAll(oldestUnreadMessage, -1, _limit, _additional); + +void GlobalUnreadBacklogRequester::requestInitialBacklog() +{ + MsgId oldestUnreadMessage; + foreach(BufferId bufferId, allBufferIds()) { + MsgId msgId = Client::networkModel()->lastSeenMsgId(bufferId); + if (!oldestUnreadMessage.isValid() || oldestUnreadMessage > msgId) + oldestUnreadMessage = msgId; + } + backlogManager->emitMessagesRequested(QObject::tr("Requesting up to %1 of all unread backlog messages (plus additional %2)").arg(_limit).arg(_additional)); + backlogManager->requestBacklogAll(oldestUnreadMessage, -1, _limit, _additional); } + // ======================================== // PER BUFFER UNREAD BACKLOG REQUESTER // ======================================== PerBufferUnreadBacklogRequester::PerBufferUnreadBacklogRequester(ClientBacklogManager *backlogManager) - : BacklogRequester(true, BacklogRequester::PerBufferUnread, backlogManager) + : BacklogRequester(true, BacklogRequester::PerBufferUnread, backlogManager) { - BacklogSettings backlogSettings; - _limit = backlogSettings.perBufferUnreadBacklogLimit(); - _additional = backlogSettings.perBufferUnreadBacklogAdditional(); + BacklogSettings backlogSettings; + _limit = backlogSettings.perBufferUnreadBacklogLimit(); + _additional = backlogSettings.perBufferUnreadBacklogAdditional(); } -void PerBufferUnreadBacklogRequester::requestBacklog(const BufferIdList &bufferIds) { - setWaitingBuffers(bufferIds); - backlogManager->emitMessagesRequested(QObject::tr("Requesting a total of up to %1 unread backlog messages for %2 buffers").arg((_limit + _additional) * bufferIds.count()).arg(bufferIds.count())); - foreach(BufferId bufferId, bufferIds) { - backlogManager->requestBacklog(bufferId, Client::networkModel()->lastSeenMsgId(bufferId), -1, _limit, _additional); - } + +void PerBufferUnreadBacklogRequester::requestBacklog(const BufferIdList &bufferIds) +{ + setWaitingBuffers(bufferIds); + backlogManager->emitMessagesRequested(QObject::tr("Requesting a total of up to %1 unread backlog messages for %2 buffers").arg((_limit + _additional) * bufferIds.count()).arg(bufferIds.count())); + foreach(BufferId bufferId, bufferIds) { + backlogManager->requestBacklog(bufferId, Client::networkModel()->lastSeenMsgId(bufferId), -1, _limit, _additional); + } } diff --git a/src/client/backlogrequester.h b/src/client/backlogrequester.h index e813c6c7..06d0c2b8 100644 --- a/src/client/backlogrequester.h +++ b/src/client/backlogrequester.h @@ -30,85 +30,93 @@ class ClientBacklogManager; -class BacklogRequester { +class BacklogRequester +{ public: - enum RequesterType { - InvalidRequester = 0, - PerBufferFixed, - PerBufferUnread, - GlobalUnread - }; + enum RequesterType { + InvalidRequester = 0, + PerBufferFixed, + PerBufferUnread, + GlobalUnread + }; - BacklogRequester(bool buffering, RequesterType requesterType, ClientBacklogManager *backlogManger); - virtual inline ~BacklogRequester() {} + BacklogRequester(bool buffering, RequesterType requesterType, ClientBacklogManager *backlogManger); + virtual inline ~BacklogRequester() {} - inline bool isBuffering() { return _isBuffering; } - inline RequesterType type() { return _requesterType; } - inline const QList &bufferedMessages() { return _bufferedMessages; } + inline bool isBuffering() { return _isBuffering; } + inline RequesterType type() { return _requesterType; } + inline const QList &bufferedMessages() { return _bufferedMessages; } - inline int buffersWaiting() const { return _buffersWaiting.count(); } - inline int totalBuffers() const { return _totalBuffers; } + inline int buffersWaiting() const { return _buffersWaiting.count(); } + inline int totalBuffers() const { return _totalBuffers; } - bool buffer(BufferId bufferId, const MessageList &messages); //! returns false if it was the last missing backlogpart + bool buffer(BufferId bufferId, const MessageList &messages); //! returns false if it was the last missing backlogpart - virtual void requestBacklog(const BufferIdList &bufferIds) = 0; - virtual inline void requestInitialBacklog() { requestBacklog(allBufferIds()); } + virtual void requestBacklog(const BufferIdList &bufferIds) = 0; + virtual inline void requestInitialBacklog() { requestBacklog(allBufferIds()); } - virtual void flushBuffer(); + virtual void flushBuffer(); protected: - BufferIdList allBufferIds() const; - inline void setWaitingBuffers(const QList &buffers) { setWaitingBuffers(buffers.toSet()); } - void setWaitingBuffers(const QSet &buffers); - void addWaitingBuffer(BufferId buffer); + BufferIdList allBufferIds() const; + inline void setWaitingBuffers(const QList &buffers) { setWaitingBuffers(buffers.toSet()); } + void setWaitingBuffers(const QSet &buffers); + void addWaitingBuffer(BufferId buffer); - ClientBacklogManager *backlogManager; + ClientBacklogManager *backlogManager; private: - bool _isBuffering; - RequesterType _requesterType; - MessageList _bufferedMessages; - int _totalBuffers; - QSet _buffersWaiting; + bool _isBuffering; + RequesterType _requesterType; + MessageList _bufferedMessages; + int _totalBuffers; + QSet _buffersWaiting; }; + // ======================================== // FIXED BACKLOG REQUESTER // ======================================== -class FixedBacklogRequester : public BacklogRequester { +class FixedBacklogRequester : public BacklogRequester +{ public: - FixedBacklogRequester(ClientBacklogManager *backlogManager); - virtual void requestBacklog(const BufferIdList &bufferIds); + FixedBacklogRequester(ClientBacklogManager *backlogManager); + virtual void requestBacklog(const BufferIdList &bufferIds); private: - int _backlogCount; + int _backlogCount; }; + // ======================================== // GLOBAL UNREAD BACKLOG REQUESTER // ======================================== -class GlobalUnreadBacklogRequester : public BacklogRequester { +class GlobalUnreadBacklogRequester : public BacklogRequester +{ public: - GlobalUnreadBacklogRequester(ClientBacklogManager *backlogManager); - virtual void requestInitialBacklog(); - virtual void requestBacklog(const BufferIdList &) {} + GlobalUnreadBacklogRequester(ClientBacklogManager *backlogManager); + virtual void requestInitialBacklog(); + virtual void requestBacklog(const BufferIdList &) {} private: - int _limit; - int _additional; + int _limit; + int _additional; }; + // ======================================== // PER BUFFER UNREAD BACKLOG REQUESTER // ======================================== -class PerBufferUnreadBacklogRequester : public BacklogRequester { +class PerBufferUnreadBacklogRequester : public BacklogRequester +{ public: - PerBufferUnreadBacklogRequester(ClientBacklogManager *backlogManager); - virtual void requestBacklog(const BufferIdList &bufferIds); + PerBufferUnreadBacklogRequester(ClientBacklogManager *backlogManager); + virtual void requestBacklog(const BufferIdList &bufferIds); private: - int _limit; - int _additional; + int _limit; + int _additional; }; + #endif //BACKLOGREQUESTER_H diff --git a/src/client/backlogsettings.h b/src/client/backlogsettings.h index 21f946f7..7de0eef6 100644 --- a/src/client/backlogsettings.h +++ b/src/client/backlogsettings.h @@ -23,27 +23,29 @@ #include "clientsettings.h" -class BacklogSettings : public ClientSettings { +class BacklogSettings : public ClientSettings +{ public: - BacklogSettings() : ClientSettings("Backlog") {} - inline int requesterType() { return localValue("RequesterType", 1).toInt(); } - inline void setRequesterType(int requesterType) { setLocalValue("RequesterType", requesterType); } + BacklogSettings() : ClientSettings("Backlog") {} + inline int requesterType() { return localValue("RequesterType", 1).toInt(); } + inline void setRequesterType(int requesterType) { setLocalValue("RequesterType", requesterType); } - inline int dynamicBacklogAmount() { return localValue("DynamicBacklogAmount", 200).toInt(); } - inline void setDynamicBacklogAmount(int amount) { return setLocalValue("DynamicBacklogAmount", amount); } + inline int dynamicBacklogAmount() { return localValue("DynamicBacklogAmount", 200).toInt(); } + inline void setDynamicBacklogAmount(int amount) { return setLocalValue("DynamicBacklogAmount", amount); } - inline int fixedBacklogAmount() { return localValue("FixedBacklogAmount", 500).toInt(); } - inline void setFixedBacklogAmount(int amount) { return setLocalValue("FixedBacklogAmount", amount); } + inline int fixedBacklogAmount() { return localValue("FixedBacklogAmount", 500).toInt(); } + inline void setFixedBacklogAmount(int amount) { return setLocalValue("FixedBacklogAmount", amount); } - inline int globalUnreadBacklogLimit() { return localValue("GlobalUnreadBacklogLimit", 5000).toInt(); } - inline void setGlobalUnreadBacklogLimit(int limit) { return setLocalValue("GlobalUnreadBacklogLimit", limit); } - inline int globalUnreadBacklogAdditional() { return localValue("GlobalUnreadBacklogAdditional", 100).toInt(); } - inline void setGlobalUnreadBacklogAdditional(int Additional) { return setLocalValue("GlobalUnreadBacklogAdditional", Additional); } + inline int globalUnreadBacklogLimit() { return localValue("GlobalUnreadBacklogLimit", 5000).toInt(); } + inline void setGlobalUnreadBacklogLimit(int limit) { return setLocalValue("GlobalUnreadBacklogLimit", limit); } + inline int globalUnreadBacklogAdditional() { return localValue("GlobalUnreadBacklogAdditional", 100).toInt(); } + inline void setGlobalUnreadBacklogAdditional(int Additional) { return setLocalValue("GlobalUnreadBacklogAdditional", Additional); } - inline int perBufferUnreadBacklogLimit() { return localValue("PerBufferUnreadBacklogLimit", 200).toInt(); } - inline void setPerBufferUnreadBacklogLimit(int limit) { return setLocalValue("PerBufferUnreadBacklogLimit", limit); } - inline int perBufferUnreadBacklogAdditional() { return localValue("PerBufferUnreadBacklogAdditional", 50).toInt(); } - inline void setPerBufferUnreadBacklogAdditional(int Additional) { return setLocalValue("PerBufferUnreadBacklogAdditional", Additional); } + inline int perBufferUnreadBacklogLimit() { return localValue("PerBufferUnreadBacklogLimit", 200).toInt(); } + inline void setPerBufferUnreadBacklogLimit(int limit) { return setLocalValue("PerBufferUnreadBacklogLimit", limit); } + inline int perBufferUnreadBacklogAdditional() { return localValue("PerBufferUnreadBacklogAdditional", 50).toInt(); } + inline void setPerBufferUnreadBacklogAdditional(int Additional) { return setLocalValue("PerBufferUnreadBacklogAdditional", Additional); } }; + #endif //BACKLOGSETTINGS_H diff --git a/src/client/buffermodel.cpp b/src/client/buffermodel.cpp index 57441a91..959df8ac 100644 --- a/src/client/buffermodel.cpp +++ b/src/client/buffermodel.cpp @@ -27,122 +27,147 @@ #include "quassel.h" BufferModel::BufferModel(NetworkModel *parent) - : QSortFilterProxyModel(parent), + : QSortFilterProxyModel(parent), _selectionModelSynchronizer(this) { - setSourceModel(parent); - if(Quassel::isOptionSet("debugbufferswitches")) { - connect(_selectionModelSynchronizer.selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), - this, SLOT(debug_currentChanged(const QModelIndex &, const QModelIndex &))); - } - connect(Client::instance(), SIGNAL(networkCreated(NetworkId)), this, SLOT(newNetwork(NetworkId))); - connect(this, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(newBuffers(const QModelIndex &, int, int))); + setSourceModel(parent); + if (Quassel::isOptionSet("debugbufferswitches")) { + connect(_selectionModelSynchronizer.selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), + this, SLOT(debug_currentChanged(const QModelIndex &, const QModelIndex &))); + } + connect(Client::instance(), SIGNAL(networkCreated(NetworkId)), this, SLOT(newNetwork(NetworkId))); + connect(this, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(newBuffers(const QModelIndex &, int, int))); } -bool BufferModel::filterAcceptsRow(int sourceRow, const QModelIndex &parent) const { - Q_UNUSED(sourceRow); - // only networks and buffers are allowed - if(!parent.isValid()) - return true; - if(parent.data(NetworkModel::ItemTypeRole) == NetworkModel::NetworkItemType) - return true; - return false; +bool BufferModel::filterAcceptsRow(int sourceRow, const QModelIndex &parent) const +{ + Q_UNUSED(sourceRow); + // only networks and buffers are allowed + if (!parent.isValid()) + return true; + if (parent.data(NetworkModel::ItemTypeRole) == NetworkModel::NetworkItemType) + return true; + + return false; } -void BufferModel::newNetwork(NetworkId id) { - const Network *net = Client::network(id); - Q_ASSERT(net); - connect(net, SIGNAL(connectionStateSet(Network::ConnectionState)), - this, SLOT(networkConnectionChanged(Network::ConnectionState))); + +void BufferModel::newNetwork(NetworkId id) +{ + const Network *net = Client::network(id); + Q_ASSERT(net); + connect(net, SIGNAL(connectionStateSet(Network::ConnectionState)), + this, SLOT(networkConnectionChanged(Network::ConnectionState))); } -void BufferModel::networkConnectionChanged(Network::ConnectionState state) { - switch(state) { - case Network::Connecting: - case Network::Initializing: - if(currentIndex().isValid()) - return; - { - Network *net = qobject_cast(sender()); - Q_ASSERT(net); - setCurrentIndex(mapFromSource(Client::networkModel()->networkIndex(net->networkId()))); + +void BufferModel::networkConnectionChanged(Network::ConnectionState state) +{ + switch (state) { + case Network::Connecting: + case Network::Initializing: + if (currentIndex().isValid()) + return; + { + Network *net = qobject_cast(sender()); + Q_ASSERT(net); + setCurrentIndex(mapFromSource(Client::networkModel()->networkIndex(net->networkId()))); + } + break; + default: + return; } - break; - default: - return; - } } -void BufferModel::synchronizeView(QAbstractItemView *view) { - _selectionModelSynchronizer.synchronizeSelectionModel(view->selectionModel()); + +void BufferModel::synchronizeView(QAbstractItemView *view) +{ + _selectionModelSynchronizer.synchronizeSelectionModel(view->selectionModel()); } -void BufferModel::setCurrentIndex(const QModelIndex &newCurrent) { - _selectionModelSynchronizer.selectionModel()->setCurrentIndex(newCurrent, QItemSelectionModel::Current); - _selectionModelSynchronizer.selectionModel()->select(newCurrent, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + +void BufferModel::setCurrentIndex(const QModelIndex &newCurrent) +{ + _selectionModelSynchronizer.selectionModel()->setCurrentIndex(newCurrent, QItemSelectionModel::Current); + _selectionModelSynchronizer.selectionModel()->select(newCurrent, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); } -void BufferModel::switchToBuffer(const BufferId &bufferId) { - QModelIndex source_index = Client::networkModel()->bufferIndex(bufferId); - setCurrentIndex(mapFromSource(source_index)); + +void BufferModel::switchToBuffer(const BufferId &bufferId) +{ + QModelIndex source_index = Client::networkModel()->bufferIndex(bufferId); + setCurrentIndex(mapFromSource(source_index)); } -void BufferModel::switchToBufferIndex(const QModelIndex &bufferIdx) { - // we accept indexes that directly belong to us or our parent - nothing else - if(bufferIdx.model() == this) { - setCurrentIndex(bufferIdx); - return; - } - if(bufferIdx.model() == sourceModel()) { - setCurrentIndex(mapFromSource(bufferIdx)); - return; - } +void BufferModel::switchToBufferIndex(const QModelIndex &bufferIdx) +{ + // we accept indexes that directly belong to us or our parent - nothing else + if (bufferIdx.model() == this) { + setCurrentIndex(bufferIdx); + return; + } - qWarning() << "BufferModel::switchToBufferIndex(const QModelIndex &):" << bufferIdx << "does not belong to BufferModel or NetworkModel"; + if (bufferIdx.model() == sourceModel()) { + setCurrentIndex(mapFromSource(bufferIdx)); + return; + } + + qWarning() << "BufferModel::switchToBufferIndex(const QModelIndex &):" << bufferIdx << "does not belong to BufferModel or NetworkModel"; } -void BufferModel::switchToOrJoinBuffer(NetworkId networkId, const QString &name, bool isQuery) { - BufferId bufId = Client::networkModel()->bufferId(networkId, name); - if(bufId.isValid()) { - QModelIndex targetIdx = Client::networkModel()->bufferIndex(bufId); - switchToBuffer(bufId); - if(!targetIdx.data(NetworkModel::ItemActiveRole).toBool()) { - qDebug() << "switchToOrJoinBuffer failed to switch even though bufId:" << bufId << "is valid."; - Client::userInput(BufferInfo::fakeStatusBuffer(networkId), QString(isQuery ? "/QUERY %1" : "/JOIN %1").arg(name)); + +void BufferModel::switchToOrJoinBuffer(NetworkId networkId, const QString &name, bool isQuery) +{ + BufferId bufId = Client::networkModel()->bufferId(networkId, name); + if (bufId.isValid()) { + QModelIndex targetIdx = Client::networkModel()->bufferIndex(bufId); + switchToBuffer(bufId); + if (!targetIdx.data(NetworkModel::ItemActiveRole).toBool()) { + qDebug() << "switchToOrJoinBuffer failed to switch even though bufId:" << bufId << "is valid."; + Client::userInput(BufferInfo::fakeStatusBuffer(networkId), QString(isQuery ? "/QUERY %1" : "/JOIN %1").arg(name)); + } + } + else { + _bufferToSwitchTo = qMakePair(networkId, name); + Client::userInput(BufferInfo::fakeStatusBuffer(networkId), QString(isQuery ? "/QUERY %1" : "/JOIN %1").arg(name)); } - } else { - _bufferToSwitchTo = qMakePair(networkId, name); - Client::userInput(BufferInfo::fakeStatusBuffer(networkId), QString(isQuery ? "/QUERY %1" : "/JOIN %1").arg(name)); - } } -void BufferModel::debug_currentChanged(QModelIndex current, QModelIndex previous) { - Q_UNUSED(previous); - qDebug() << "Switched current Buffer: " << current << current.data().toString() << "Buffer:" << current.data(NetworkModel::BufferIdRole).value(); + +void BufferModel::debug_currentChanged(QModelIndex current, QModelIndex previous) +{ + Q_UNUSED(previous); + qDebug() << "Switched current Buffer: " << current << current.data().toString() << "Buffer:" << current.data(NetworkModel::BufferIdRole).value(); } -void BufferModel::newBuffers(const QModelIndex &parent, int start, int end) { - if(parent.data(NetworkModel::ItemTypeRole) != NetworkModel::NetworkItemType) - return; - for(int row = start; row <= end; row++) { - QModelIndex child = parent.child(row, 0); - newBuffer(child.data(NetworkModel::BufferIdRole).value()); - } +void BufferModel::newBuffers(const QModelIndex &parent, int start, int end) +{ + if (parent.data(NetworkModel::ItemTypeRole) != NetworkModel::NetworkItemType) + return; + + for (int row = start; row <= end; row++) { + QModelIndex child = parent.child(row, 0); + newBuffer(child.data(NetworkModel::BufferIdRole).value()); + } } -void BufferModel::newBuffer(BufferId bufferId) { - BufferInfo bufferInfo = Client::networkModel()->bufferInfo(bufferId); - if(_bufferToSwitchTo.first == bufferInfo.networkId() - && _bufferToSwitchTo.second == bufferInfo.bufferName()) { - _bufferToSwitchTo.first = 0; - _bufferToSwitchTo.second.clear(); - switchToBuffer(bufferId); - } + +void BufferModel::newBuffer(BufferId bufferId) +{ + BufferInfo bufferInfo = Client::networkModel()->bufferInfo(bufferId); + if (_bufferToSwitchTo.first == bufferInfo.networkId() + && _bufferToSwitchTo.second == bufferInfo.bufferName()) { + _bufferToSwitchTo.first = 0; + _bufferToSwitchTo.second.clear(); + switchToBuffer(bufferId); + } } -void BufferModel::switchToBufferAfterCreation(NetworkId network, const QString &name) { - _bufferToSwitchTo = qMakePair(network, name); + +void BufferModel::switchToBufferAfterCreation(NetworkId network, const QString &name) +{ + _bufferToSwitchTo = qMakePair(network, name); } diff --git a/src/client/buffermodel.h b/src/client/buffermodel.h index d1390c9b..8fe780b8 100644 --- a/src/client/buffermodel.h +++ b/src/client/buffermodel.h @@ -32,44 +32,49 @@ class QAbstractItemView; -class BufferModel : public QSortFilterProxyModel { - Q_OBJECT +class BufferModel : public QSortFilterProxyModel +{ + Q_OBJECT public: - BufferModel(NetworkModel *parent = 0); + BufferModel(NetworkModel *parent = 0); - bool filterAcceptsRow(int sourceRow, const QModelIndex &parent) const; + bool filterAcceptsRow(int sourceRow, const QModelIndex &parent) const; - inline const SelectionModelSynchronizer *selectionModelSynchronizer() const { return &_selectionModelSynchronizer; } - inline QItemSelectionModel *standardSelectionModel() const { return _selectionModelSynchronizer.selectionModel(); } + inline const SelectionModelSynchronizer *selectionModelSynchronizer() const { return &_selectionModelSynchronizer; } + inline QItemSelectionModel *standardSelectionModel() const { return _selectionModelSynchronizer.selectionModel(); } - inline void synchronizeSelectionModel(QItemSelectionModel *selectionModel) { _selectionModelSynchronizer.synchronizeSelectionModel(selectionModel); } - void synchronizeView(QAbstractItemView *view); + inline void synchronizeSelectionModel(QItemSelectionModel *selectionModel) { _selectionModelSynchronizer.synchronizeSelectionModel(selectionModel); } + void synchronizeView(QAbstractItemView *view); - inline QModelIndex currentIndex() { return standardSelectionModel()->currentIndex(); } - inline BufferId currentBuffer() { return currentIndex().data(NetworkModel::BufferIdRole).value(); } + inline QModelIndex currentIndex() { return standardSelectionModel()->currentIndex(); } + inline BufferId currentBuffer() { return currentIndex().data(NetworkModel::BufferIdRole).value(); } public slots: - void setCurrentIndex(const QModelIndex &newCurrent); - void switchToBuffer(const BufferId &bufferId); - void switchToBufferIndex(const QModelIndex &bufferIdx); - void switchToOrJoinBuffer(NetworkId network, const QString &bufferName, bool isQuery = false); - void switchToOrStartQuery(NetworkId network, const QString &nick) { - switchToOrJoinBuffer(network, nick, true); - } - void switchToBufferAfterCreation(NetworkId network, const QString &name); + void setCurrentIndex(const QModelIndex &newCurrent); + void switchToBuffer(const BufferId &bufferId); + void switchToBufferIndex(const QModelIndex &bufferIdx); + void switchToOrJoinBuffer(NetworkId network, const QString &bufferName, bool isQuery = false); + void switchToOrStartQuery(NetworkId network, const QString &nick) + { + switchToOrJoinBuffer(network, nick, true); + } + + + void switchToBufferAfterCreation(NetworkId network, const QString &name); private slots: - void debug_currentChanged(QModelIndex current, QModelIndex previous); - void newNetwork(NetworkId id); - void networkConnectionChanged(Network::ConnectionState state); - void newBuffers(const QModelIndex &parent, int start, int end); + void debug_currentChanged(QModelIndex current, QModelIndex previous); + void newNetwork(NetworkId id); + void networkConnectionChanged(Network::ConnectionState state); + void newBuffers(const QModelIndex &parent, int start, int end); private: - void newBuffer(BufferId bufferId); + void newBuffer(BufferId bufferId); - SelectionModelSynchronizer _selectionModelSynchronizer; - QPair _bufferToSwitchTo; + SelectionModelSynchronizer _selectionModelSynchronizer; + QPair _bufferToSwitchTo; }; + #endif // BUFFERMODEL_H diff --git a/src/client/buffersettings.cpp b/src/client/buffersettings.cpp index aebca0d2..f99e52ef 100644 --- a/src/client/buffersettings.cpp +++ b/src/client/buffersettings.cpp @@ -21,31 +21,38 @@ #include "buffersettings.h" BufferSettings::BufferSettings(BufferId bufferId) - : ClientSettings(QString("Buffer/%1").arg(bufferId.toInt())) + : ClientSettings(QString("Buffer/%1").arg(bufferId.toInt())) { } + BufferSettings::BufferSettings(const QString &idString) - : ClientSettings(QString("Buffer/%1").arg(idString)) + : ClientSettings(QString("Buffer/%1").arg(idString)) { } -void BufferSettings::filterMessage(Message::Type msgType, bool filter) { - if(!hasFilter()) - setLocalValue("hasMessageTypeFilter", true); - if(filter) - setLocalValue("MessageTypeFilter", localValue("MessageTypeFilter", 0).toInt() | msgType); - else - setLocalValue("MessageTypeFilter", localValue("MessageTypeFilter", 0).toInt() & ~msgType); + +void BufferSettings::filterMessage(Message::Type msgType, bool filter) +{ + if (!hasFilter()) + setLocalValue("hasMessageTypeFilter", true); + if (filter) + setLocalValue("MessageTypeFilter", localValue("MessageTypeFilter", 0).toInt() | msgType); + else + setLocalValue("MessageTypeFilter", localValue("MessageTypeFilter", 0).toInt() & ~msgType); } -void BufferSettings::setMessageFilter(int filter) { - if(!hasFilter()) - setLocalValue("hasMessageTypeFilter", true); - setLocalValue("MessageTypeFilter", filter); + +void BufferSettings::setMessageFilter(int filter) +{ + if (!hasFilter()) + setLocalValue("hasMessageTypeFilter", true); + setLocalValue("MessageTypeFilter", filter); } -void BufferSettings::removeFilter() { - setLocalValue("hasMessageTypeFilter", false); - removeLocalKey("MessageTypeFilter"); + +void BufferSettings::removeFilter() +{ + setLocalValue("hasMessageTypeFilter", false); + removeLocalKey("MessageTypeFilter"); } diff --git a/src/client/buffersettings.h b/src/client/buffersettings.h index 546406a6..1766d0d4 100644 --- a/src/client/buffersettings.h +++ b/src/client/buffersettings.h @@ -25,39 +25,39 @@ #include "message.h" #include "types.h" -class BufferSettings : public ClientSettings { +class BufferSettings : public ClientSettings +{ public: - enum RedirectTarget { - DefaultBuffer = 0x01, - StatusBuffer = 0x02, - CurrentBuffer = 0x04 - }; + enum RedirectTarget { + DefaultBuffer = 0x01, + StatusBuffer = 0x02, + CurrentBuffer = 0x04 + }; - BufferSettings(const QString &idString = "__default__"); - BufferSettings(BufferId bufferId); + BufferSettings(const QString &idString = "__default__"); + BufferSettings(BufferId bufferId); - inline void setValue(const QString &key, const QVariant &data) { setLocalValue(key, data); } - inline QVariant value(const QString &key, const QVariant &def = QVariant()) { return localValue(key, def); } + inline void setValue(const QString &key, const QVariant &data) { setLocalValue(key, data); } + inline QVariant value(const QString &key, const QVariant &def = QVariant()) { return localValue(key, def); } - // Message Filter (default and per view) - inline bool hasFilter() { return localValue("hasMessageTypeFilter", false).toBool(); } - inline int messageFilter() { return localValue("MessageTypeFilter", 0).toInt(); } - void setMessageFilter(int filter); - void filterMessage(Message::Type msgType, bool filter); - void removeFilter(); + // Message Filter (default and per view) + inline bool hasFilter() { return localValue("hasMessageTypeFilter", false).toBool(); } + inline int messageFilter() { return localValue("MessageTypeFilter", 0).toInt(); } + void setMessageFilter(int filter); + void filterMessage(Message::Type msgType, bool filter); + void removeFilter(); - // user state icons for query buffers (default) - inline bool showUserStateIcons() { return localValue("ShowUserStateIcons", true).toBool(); } - inline void enableUserStateIcons(bool enabled) { setLocalValue("ShowUserStateIcons", enabled); } + // user state icons for query buffers (default) + inline bool showUserStateIcons() { return localValue("ShowUserStateIcons", true).toBool(); } + inline void enableUserStateIcons(bool enabled) { setLocalValue("ShowUserStateIcons", enabled); } - - // redirection settings (default) - inline int userNoticesTarget() { return localValue("UserNoticesTarget", DefaultBuffer | CurrentBuffer).toInt(); } - inline void setUserNoticesTarget(int target) { setLocalValue("UserNoticesTarget", target); } - inline int serverNoticesTarget() { return localValue("ServerNoticesTarget", StatusBuffer).toInt(); } - inline void setServerNoticesTarget(int target) { setLocalValue("ServerNoticesTarget", target); } - inline int errorMsgsTarget() { return localValue("ErrorMsgsTarget", DefaultBuffer).toInt(); } - inline void setErrorMsgsTarget(int target) { setLocalValue("ErrorMsgsTarget", target); } + // redirection settings (default) + inline int userNoticesTarget() { return localValue("UserNoticesTarget", DefaultBuffer | CurrentBuffer).toInt(); } + inline void setUserNoticesTarget(int target) { setLocalValue("UserNoticesTarget", target); } + inline int serverNoticesTarget() { return localValue("ServerNoticesTarget", StatusBuffer).toInt(); } + inline void setServerNoticesTarget(int target) { setLocalValue("ServerNoticesTarget", target); } + inline int errorMsgsTarget() { return localValue("ErrorMsgsTarget", DefaultBuffer).toInt(); } + inline void setErrorMsgsTarget(int target) { setLocalValue("ErrorMsgsTarget", target); } }; diff --git a/src/client/bufferviewoverlay.cpp b/src/client/bufferviewoverlay.cpp index ee5fab0b..3cf58778 100644 --- a/src/client/bufferviewoverlay.cpp +++ b/src/client/bufferviewoverlay.cpp @@ -31,7 +31,7 @@ const int BufferViewOverlay::_updateEventId = QEvent::registerEventType(); BufferViewOverlay::BufferViewOverlay(QObject *parent) - : QObject(parent), + : QObject(parent), _aboutToUpdate(false), _uninitializedViewCount(0), _allowedBufferTypes(0), @@ -39,264 +39,300 @@ BufferViewOverlay::BufferViewOverlay(QObject *parent) { } -void BufferViewOverlay::reset() { - _aboutToUpdate = false; - _bufferViewIds.clear(); - _uninitializedViewCount = 0; +void BufferViewOverlay::reset() +{ + _aboutToUpdate = false; - _networkIds.clear(); - _allowedBufferTypes = 0; - _minimumActivity = 0; + _bufferViewIds.clear(); + _uninitializedViewCount = 0; - _buffers.clear(); - _removedBuffers.clear(); - _tempRemovedBuffers.clear(); -} + _networkIds.clear(); + _allowedBufferTypes = 0; + _minimumActivity = 0; -void BufferViewOverlay::save() { - CoreAccountSettings().setBufferViewOverlay(_bufferViewIds); + _buffers.clear(); + _removedBuffers.clear(); + _tempRemovedBuffers.clear(); } -void BufferViewOverlay::restore() { - QSet currentIds = _bufferViewIds; - reset(); - currentIds += CoreAccountSettings().bufferViewOverlay(); - QSet::const_iterator iter; - for(iter = currentIds.constBegin(); iter != currentIds.constEnd(); iter++) { - addView(*iter); - } +void BufferViewOverlay::save() +{ + CoreAccountSettings().setBufferViewOverlay(_bufferViewIds); } -void BufferViewOverlay::addView(int viewId) { - if(_bufferViewIds.contains(viewId)) - return; - BufferViewConfig *config = Client::bufferViewManager()->bufferViewConfig(viewId); - if(!config) { - qDebug() << "BufferViewOverlay::addView(): no such buffer view:" << viewId; - return; - } +void BufferViewOverlay::restore() +{ + QSet currentIds = _bufferViewIds; + reset(); + currentIds += CoreAccountSettings().bufferViewOverlay(); - _bufferViewIds << viewId; - bool wasInitialized = isInitialized(); - _uninitializedViewCount++; + QSet::const_iterator iter; + for (iter = currentIds.constBegin(); iter != currentIds.constEnd(); iter++) { + addView(*iter); + } +} - if(config->isInitialized()) { - viewInitialized(config); - if(wasInitialized) { - BufferIdList buffers; - if(config->networkId().isValid()) { - foreach(BufferId bufferId, config->bufferList()) { - if(Client::networkModel()->networkId(bufferId) == config->networkId()) - buffers << bufferId; - } - foreach(BufferId bufferId, config->temporarilyRemovedBuffers().toList()) { - if(Client::networkModel()->networkId(bufferId) == config->networkId()) - buffers << bufferId; - } - } else { - buffers = BufferIdList::fromSet(config->bufferList().toSet() + config->temporarilyRemovedBuffers()); - } - Client::backlogManager()->checkForBacklog(buffers); +void BufferViewOverlay::addView(int viewId) +{ + if (_bufferViewIds.contains(viewId)) + return; + + BufferViewConfig *config = Client::bufferViewManager()->bufferViewConfig(viewId); + if (!config) { + qDebug() << "BufferViewOverlay::addView(): no such buffer view:" << viewId; + return; } - } else { - disconnect(config, SIGNAL(initDone()), this, SLOT(viewInitialized())); - // we use a queued connection here since manipulating the connection list of a sending object - // doesn't seem to be such a good idea while executing a connected slots. - connect(config, SIGNAL(initDone()), this, SLOT(viewInitialized()), Qt::QueuedConnection); - } - save(); + _bufferViewIds << viewId; + bool wasInitialized = isInitialized(); + _uninitializedViewCount++; + + if (config->isInitialized()) { + viewInitialized(config); + + if (wasInitialized) { + BufferIdList buffers; + if (config->networkId().isValid()) { + foreach(BufferId bufferId, config->bufferList()) { + if (Client::networkModel()->networkId(bufferId) == config->networkId()) + buffers << bufferId; + } + foreach(BufferId bufferId, config->temporarilyRemovedBuffers().toList()) { + if (Client::networkModel()->networkId(bufferId) == config->networkId()) + buffers << bufferId; + } + } + else { + buffers = BufferIdList::fromSet(config->bufferList().toSet() + config->temporarilyRemovedBuffers()); + } + Client::backlogManager()->checkForBacklog(buffers); + } + } + else { + disconnect(config, SIGNAL(initDone()), this, SLOT(viewInitialized())); + // we use a queued connection here since manipulating the connection list of a sending object + // doesn't seem to be such a good idea while executing a connected slots. + connect(config, SIGNAL(initDone()), this, SLOT(viewInitialized()), Qt::QueuedConnection); + } + save(); } -void BufferViewOverlay::removeView(int viewId) { - if(!_bufferViewIds.contains(viewId)) - return; - - _bufferViewIds.remove(viewId); - BufferViewConfig *config = Client::bufferViewManager()->bufferViewConfig(viewId); - if(config) - disconnect(config, 0, this, 0); - - // update initialized State: - bool wasInitialized = isInitialized(); - _uninitializedViewCount = 0; - QSet::iterator viewIter = _bufferViewIds.begin(); - while(viewIter != _bufferViewIds.end()) { - config = Client::bufferViewManager()->bufferViewConfig(*viewIter); - if(!config) { - viewIter = _bufferViewIds.erase(viewIter); - } else { - if(!config->isInitialized()) - _uninitializedViewCount++; - viewIter++; + +void BufferViewOverlay::removeView(int viewId) +{ + if (!_bufferViewIds.contains(viewId)) + return; + + _bufferViewIds.remove(viewId); + BufferViewConfig *config = Client::bufferViewManager()->bufferViewConfig(viewId); + if (config) + disconnect(config, 0, this, 0); + + // update initialized State: + bool wasInitialized = isInitialized(); + _uninitializedViewCount = 0; + QSet::iterator viewIter = _bufferViewIds.begin(); + while (viewIter != _bufferViewIds.end()) { + config = Client::bufferViewManager()->bufferViewConfig(*viewIter); + if (!config) { + viewIter = _bufferViewIds.erase(viewIter); + } + else { + if (!config->isInitialized()) + _uninitializedViewCount++; + viewIter++; + } } - } - update(); - if(!wasInitialized && isInitialized()) - emit initDone(); - save(); + update(); + if (!wasInitialized && isInitialized()) + emit initDone(); + save(); } -void BufferViewOverlay::viewInitialized(BufferViewConfig *config) { - if(!config) { - qWarning() << "BufferViewOverlay::viewInitialized() received invalid view!"; - return; - } - disconnect(config, SIGNAL(initDone()), this, SLOT(viewInitialized())); - connect(config, SIGNAL(configChanged()), this, SLOT(update())); +void BufferViewOverlay::viewInitialized(BufferViewConfig *config) +{ + if (!config) { + qWarning() << "BufferViewOverlay::viewInitialized() received invalid view!"; + return; + } + disconnect(config, SIGNAL(initDone()), this, SLOT(viewInitialized())); - // check if the view was removed in the meantime... - if(_bufferViewIds.contains(config->bufferViewId())) - update(); + connect(config, SIGNAL(configChanged()), this, SLOT(update())); + + // check if the view was removed in the meantime... + if (_bufferViewIds.contains(config->bufferViewId())) + update(); - _uninitializedViewCount--; - if(isInitialized()) - emit initDone(); + _uninitializedViewCount--; + if (isInitialized()) + emit initDone(); } -void BufferViewOverlay::viewInitialized() { - BufferViewConfig *config = qobject_cast(sender()); - Q_ASSERT(config); - viewInitialized(config); -} +void BufferViewOverlay::viewInitialized() +{ + BufferViewConfig *config = qobject_cast(sender()); + Q_ASSERT(config); -void BufferViewOverlay::update() { - if(_aboutToUpdate) { - return; - } - _aboutToUpdate = true; - QCoreApplication::postEvent(this, new QEvent((QEvent::Type)_updateEventId)); + viewInitialized(config); } -void BufferViewOverlay::updateHelper() { - if(!_aboutToUpdate) - return; - bool changed = false; +void BufferViewOverlay::update() +{ + if (_aboutToUpdate) { + return; + } + _aboutToUpdate = true; + QCoreApplication::postEvent(this, new QEvent((QEvent::Type)_updateEventId)); +} - int allowedBufferTypes = 0; - int minimumActivity = -1; - QSet networkIds; - QSet buffers; - QSet removedBuffers; - QSet tempRemovedBuffers; - if(Client::bufferViewManager()) { - BufferViewConfig *config = 0; - QSet::const_iterator viewIter; - for(viewIter = _bufferViewIds.constBegin(); viewIter != _bufferViewIds.constEnd(); viewIter++) { - config = Client::bufferViewManager()->bufferViewConfig(*viewIter); - if(!config) - continue; +void BufferViewOverlay::updateHelper() +{ + if (!_aboutToUpdate) + return; + + bool changed = false; + + int allowedBufferTypes = 0; + int minimumActivity = -1; + QSet networkIds; + QSet buffers; + QSet removedBuffers; + QSet tempRemovedBuffers; + + if (Client::bufferViewManager()) { + BufferViewConfig *config = 0; + QSet::const_iterator viewIter; + for (viewIter = _bufferViewIds.constBegin(); viewIter != _bufferViewIds.constEnd(); viewIter++) { + config = Client::bufferViewManager()->bufferViewConfig(*viewIter); + if (!config) + continue; + + allowedBufferTypes |= config->allowedBufferTypes(); + if (minimumActivity == -1 || config->minimumActivity() < minimumActivity) + minimumActivity = config->minimumActivity(); + + networkIds << config->networkId(); + + // we have to apply several filters before we can add a buffer to a category (visible, removed, ...) + buffers += filterBuffersByConfig(config->bufferList(), config); + tempRemovedBuffers += filterBuffersByConfig(config->temporarilyRemovedBuffers().toList(), config); + removedBuffers += config->removedBuffers(); + } - allowedBufferTypes |= config->allowedBufferTypes(); - if(minimumActivity == -1 || config->minimumActivity() < minimumActivity) - minimumActivity = config->minimumActivity(); + // prune the sets from overlap + QSet availableBuffers = Client::networkModel()->allBufferIds().toSet(); - networkIds << config->networkId(); + buffers.intersect(availableBuffers); + tempRemovedBuffers.intersect(availableBuffers); + tempRemovedBuffers.subtract(buffers); - // we have to apply several filters before we can add a buffer to a category (visible, removed, ...) - buffers += filterBuffersByConfig(config->bufferList(), config); - tempRemovedBuffers += filterBuffersByConfig(config->temporarilyRemovedBuffers().toList(), config); - removedBuffers += config->removedBuffers(); + removedBuffers.intersect(availableBuffers); + removedBuffers.subtract(tempRemovedBuffers); + removedBuffers.subtract(buffers); } - // prune the sets from overlap - QSet availableBuffers = Client::networkModel()->allBufferIds().toSet(); - - buffers.intersect(availableBuffers); + changed |= (allowedBufferTypes != _allowedBufferTypes); + changed |= (minimumActivity != _minimumActivity); + changed |= (networkIds != _networkIds); + changed |= (buffers != _buffers); + changed |= (removedBuffers != _removedBuffers); + changed |= (tempRemovedBuffers != _tempRemovedBuffers); - tempRemovedBuffers.intersect(availableBuffers); - tempRemovedBuffers.subtract(buffers); + _allowedBufferTypes = allowedBufferTypes; + _minimumActivity = minimumActivity; + _networkIds = networkIds; + _buffers = buffers; + _removedBuffers = removedBuffers; + _tempRemovedBuffers = tempRemovedBuffers; - removedBuffers.intersect(availableBuffers); - removedBuffers.subtract(tempRemovedBuffers); - removedBuffers.subtract(buffers); - } + _aboutToUpdate = false; - changed |= (allowedBufferTypes != _allowedBufferTypes); - changed |= (minimumActivity != _minimumActivity); - changed |= (networkIds != _networkIds); - changed |= (buffers != _buffers); - changed |= (removedBuffers != _removedBuffers); - changed |= (tempRemovedBuffers != _tempRemovedBuffers); + if (changed) + emit hasChanged(); +} - _allowedBufferTypes = allowedBufferTypes; - _minimumActivity = minimumActivity; - _networkIds = networkIds; - _buffers = buffers; - _removedBuffers = removedBuffers; - _tempRemovedBuffers = tempRemovedBuffers; - _aboutToUpdate = false; +QSet BufferViewOverlay::filterBuffersByConfig(const QList &buffers, const BufferViewConfig *config) +{ + Q_ASSERT(config); + + QSet bufferIds; + BufferInfo bufferInfo; + foreach(BufferId bufferId, buffers) { + bufferInfo = Client::networkModel()->bufferInfo(bufferId); + if (!(bufferInfo.type() & config->allowedBufferTypes())) + continue; + if (config->networkId().isValid() && bufferInfo.networkId() != config->networkId()) + continue; + bufferIds << bufferId; + } - if(changed) - emit hasChanged(); + return bufferIds; } -QSet BufferViewOverlay::filterBuffersByConfig(const QList &buffers, const BufferViewConfig *config) { - Q_ASSERT(config); - - QSet bufferIds; - BufferInfo bufferInfo; - foreach(BufferId bufferId, buffers) { - bufferInfo = Client::networkModel()->bufferInfo(bufferId); - if(!(bufferInfo.type() & config->allowedBufferTypes())) - continue; - if(config->networkId().isValid() && bufferInfo.networkId() != config->networkId()) - continue; - bufferIds << bufferId; - } - - return bufferIds; + +void BufferViewOverlay::customEvent(QEvent *event) +{ + if (event->type() == _updateEventId) { + updateHelper(); + } } -void BufferViewOverlay::customEvent(QEvent *event) { - if(event->type() == _updateEventId) { +bool BufferViewOverlay::allNetworks() +{ updateHelper(); - } + return _networkIds.contains(NetworkId()); } -bool BufferViewOverlay::allNetworks() { - updateHelper(); - return _networkIds.contains(NetworkId()); -} -const QSet &BufferViewOverlay::networkIds() { - updateHelper(); - return _networkIds; +const QSet &BufferViewOverlay::networkIds() +{ + updateHelper(); + return _networkIds; } -const QSet &BufferViewOverlay::bufferIds() { - updateHelper(); - return _buffers; + +const QSet &BufferViewOverlay::bufferIds() +{ + updateHelper(); + return _buffers; } -const QSet &BufferViewOverlay::removedBufferIds() { - updateHelper(); - return _removedBuffers; + +const QSet &BufferViewOverlay::removedBufferIds() +{ + updateHelper(); + return _removedBuffers; } -const QSet &BufferViewOverlay::tempRemovedBufferIds() { - updateHelper(); - return _tempRemovedBuffers; + +const QSet &BufferViewOverlay::tempRemovedBufferIds() +{ + updateHelper(); + return _tempRemovedBuffers; } -int BufferViewOverlay::allowedBufferTypes() { - updateHelper(); - return _allowedBufferTypes; + +int BufferViewOverlay::allowedBufferTypes() +{ + updateHelper(); + return _allowedBufferTypes; } -int BufferViewOverlay::minimumActivity() { - updateHelper(); - return _minimumActivity; + +int BufferViewOverlay::minimumActivity() +{ + updateHelper(); + return _minimumActivity; } diff --git a/src/client/bufferviewoverlay.h b/src/client/bufferviewoverlay.h index 313a2e30..1b852160 100644 --- a/src/client/bufferviewoverlay.h +++ b/src/client/bufferviewoverlay.h @@ -28,65 +28,67 @@ class BufferViewConfig; class ClientBufferViewConfig; -class BufferViewOverlay : public QObject { - Q_OBJECT +class BufferViewOverlay : public QObject +{ + Q_OBJECT public: - BufferViewOverlay(QObject *parent = 0); + BufferViewOverlay(QObject *parent = 0); - inline const QSet &bufferViewIds() { return _bufferViewIds; } - bool allNetworks(); + inline const QSet &bufferViewIds() { return _bufferViewIds; } + bool allNetworks(); - const QSet &networkIds(); - const QSet &bufferIds(); - const QSet &removedBufferIds(); - const QSet &tempRemovedBufferIds(); + const QSet &networkIds(); + const QSet &bufferIds(); + const QSet &removedBufferIds(); + const QSet &tempRemovedBufferIds(); - int allowedBufferTypes(); - int minimumActivity(); + int allowedBufferTypes(); + int minimumActivity(); - inline bool isInitialized() { return _uninitializedViewCount == 0; } + inline bool isInitialized() { return _uninitializedViewCount == 0; } public slots: - void addView(int viewId); - void removeView(int viewId); + void addView(int viewId); + void removeView(int viewId); - void reset(); - void save(); - void restore(); + void reset(); + void save(); + void restore(); - // updates propagated from the actual views - void update(); + // updates propagated from the actual views + void update(); signals: - void hasChanged(); - void initDone(); + void hasChanged(); + void initDone(); protected: - virtual void customEvent(QEvent *event); + virtual void customEvent(QEvent *event); private slots: - void viewInitialized(); - void viewInitialized(BufferViewConfig *config); + void viewInitialized(); + void viewInitialized(BufferViewConfig *config); private: - void updateHelper(); - QSet filterBuffersByConfig(const QList &buffers, const BufferViewConfig *config); + void updateHelper(); + QSet filterBuffersByConfig(const QList &buffers, const BufferViewConfig *config); - bool _aboutToUpdate; + bool _aboutToUpdate; - QSet _bufferViewIds; - int _uninitializedViewCount; + QSet _bufferViewIds; + int _uninitializedViewCount; - QSet _networkIds; - int _allowedBufferTypes; - int _minimumActivity; + QSet _networkIds; + int _allowedBufferTypes; + int _minimumActivity; - QSet _buffers; - QSet _removedBuffers; - QSet _tempRemovedBuffers; + QSet _buffers; + QSet _removedBuffers; + QSet _tempRemovedBuffers; - static const int _updateEventId; + static const int _updateEventId; }; + #endif //BUFFERVIEWOVERLAY_H diff --git a/src/client/client.cpp b/src/client/client.cpp index 21beda08..e1a7a053 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -58,30 +58,37 @@ Quassel::Features Client::_coreFeatures = 0; bool Client::instanceExists() { - return instanceptr; + return instanceptr; } -Client *Client::instance() { - if(!instanceptr) - instanceptr = new Client(); - return instanceptr; + +Client *Client::instance() +{ + if (!instanceptr) + instanceptr = new Client(); + return instanceptr; } -void Client::destroy() { - if(instanceptr) { - delete instanceptr->mainUi(); - instanceptr->deleteLater(); - instanceptr = 0; - } + +void Client::destroy() +{ + if (instanceptr) { + delete instanceptr->mainUi(); + instanceptr->deleteLater(); + instanceptr = 0; + } } -void Client::init(AbstractUi *ui) { - instance()->_mainUi = ui; - instance()->init(); + +void Client::init(AbstractUi *ui) +{ + instance()->_mainUi = ui; + instance()->init(); } + Client::Client(QObject *parent) - : QObject(parent), + : QObject(parent), _signalProxy(new SignalProxy(SignalProxy::Client, this)), _mainUi(0), _networkModel(0), @@ -102,458 +109,547 @@ Client::Client(QObject *parent) _connected(false), _debugLog(&_debugLogBuffer) { - _signalProxy->synchronize(_ircListHelper); + _signalProxy->synchronize(_ircListHelper); } -Client::~Client() { - disconnectFromCore(); + +Client::~Client() +{ + disconnectFromCore(); } -void Client::init() { - _networkModel = new NetworkModel(this); - connect(this, SIGNAL(networkRemoved(NetworkId)), - _networkModel, SLOT(networkRemoved(NetworkId))); +void Client::init() +{ + _networkModel = new NetworkModel(this); + + connect(this, SIGNAL(networkRemoved(NetworkId)), + _networkModel, SLOT(networkRemoved(NetworkId))); - _bufferModel = new BufferModel(_networkModel); - _messageModel = mainUi()->createMessageModel(this); - _messageProcessor = mainUi()->createMessageProcessor(this); - _inputHandler = new ClientUserInputHandler(this); + _bufferModel = new BufferModel(_networkModel); + _messageModel = mainUi()->createMessageModel(this); + _messageProcessor = mainUi()->createMessageProcessor(this); + _inputHandler = new ClientUserInputHandler(this); - SignalProxy *p = signalProxy(); + SignalProxy *p = signalProxy(); - p->attachSlot(SIGNAL(displayMsg(const Message &)), this, SLOT(recvMessage(const Message &))); - p->attachSlot(SIGNAL(displayStatusMsg(QString, QString)), this, SLOT(recvStatusMsg(QString, QString))); + p->attachSlot(SIGNAL(displayMsg(const Message &)), this, SLOT(recvMessage(const Message &))); + p->attachSlot(SIGNAL(displayStatusMsg(QString, QString)), this, SLOT(recvStatusMsg(QString, QString))); - p->attachSlot(SIGNAL(bufferInfoUpdated(BufferInfo)), _networkModel, SLOT(bufferUpdated(BufferInfo))); - p->attachSignal(inputHandler(), SIGNAL(sendInput(BufferInfo, QString))); - p->attachSignal(this, SIGNAL(requestNetworkStates())); + p->attachSlot(SIGNAL(bufferInfoUpdated(BufferInfo)), _networkModel, SLOT(bufferUpdated(BufferInfo))); + p->attachSignal(inputHandler(), SIGNAL(sendInput(BufferInfo, QString))); + p->attachSignal(this, SIGNAL(requestNetworkStates())); - p->attachSignal(this, SIGNAL(requestCreateIdentity(const Identity &, const QVariantMap &)), SIGNAL(createIdentity(const Identity &, const QVariantMap &))); - p->attachSignal(this, SIGNAL(requestRemoveIdentity(IdentityId)), SIGNAL(removeIdentity(IdentityId))); - p->attachSlot(SIGNAL(identityCreated(const Identity &)), this, SLOT(coreIdentityCreated(const Identity &))); - p->attachSlot(SIGNAL(identityRemoved(IdentityId)), this, SLOT(coreIdentityRemoved(IdentityId))); + p->attachSignal(this, SIGNAL(requestCreateIdentity(const Identity &, const QVariantMap &)), SIGNAL(createIdentity(const Identity &, const QVariantMap &))); + p->attachSignal(this, SIGNAL(requestRemoveIdentity(IdentityId)), SIGNAL(removeIdentity(IdentityId))); + p->attachSlot(SIGNAL(identityCreated(const Identity &)), this, SLOT(coreIdentityCreated(const Identity &))); + p->attachSlot(SIGNAL(identityRemoved(IdentityId)), this, SLOT(coreIdentityRemoved(IdentityId))); - p->attachSignal(this, SIGNAL(requestCreateNetwork(const NetworkInfo &, const QStringList &)), SIGNAL(createNetwork(const NetworkInfo &, const QStringList &))); - p->attachSignal(this, SIGNAL(requestRemoveNetwork(NetworkId)), SIGNAL(removeNetwork(NetworkId))); - p->attachSlot(SIGNAL(networkCreated(NetworkId)), this, SLOT(coreNetworkCreated(NetworkId))); - p->attachSlot(SIGNAL(networkRemoved(NetworkId)), this, SLOT(coreNetworkRemoved(NetworkId))); + p->attachSignal(this, SIGNAL(requestCreateNetwork(const NetworkInfo &, const QStringList &)), SIGNAL(createNetwork(const NetworkInfo &, const QStringList &))); + p->attachSignal(this, SIGNAL(requestRemoveNetwork(NetworkId)), SIGNAL(removeNetwork(NetworkId))); + p->attachSlot(SIGNAL(networkCreated(NetworkId)), this, SLOT(coreNetworkCreated(NetworkId))); + p->attachSlot(SIGNAL(networkRemoved(NetworkId)), this, SLOT(coreNetworkRemoved(NetworkId))); - //connect(mainUi(), SIGNAL(connectToCore(const QVariantMap &)), this, SLOT(connectToCore(const QVariantMap &))); - connect(mainUi(), SIGNAL(disconnectFromCore()), this, SLOT(disconnectFromCore())); - connect(this, SIGNAL(connected()), mainUi(), SLOT(connectedToCore())); - connect(this, SIGNAL(disconnected()), mainUi(), SLOT(disconnectedFromCore())); + //connect(mainUi(), SIGNAL(connectToCore(const QVariantMap &)), this, SLOT(connectToCore(const QVariantMap &))); + connect(mainUi(), SIGNAL(disconnectFromCore()), this, SLOT(disconnectFromCore())); + connect(this, SIGNAL(connected()), mainUi(), SLOT(connectedToCore())); + connect(this, SIGNAL(disconnected()), mainUi(), SLOT(disconnectedFromCore())); - // attach backlog manager - p->synchronize(backlogManager()); - connect(backlogManager(), SIGNAL(messagesReceived(BufferId, int)), _messageModel, SLOT(messagesReceived(BufferId, int))); + // attach backlog manager + p->synchronize(backlogManager()); + connect(backlogManager(), SIGNAL(messagesReceived(BufferId, int)), _messageModel, SLOT(messagesReceived(BufferId, int))); - coreAccountModel()->load(); + coreAccountModel()->load(); - connect(coreConnection(), SIGNAL(stateChanged(CoreConnection::ConnectionState)), SLOT(connectionStateChanged(CoreConnection::ConnectionState))); - coreConnection()->init(); + connect(coreConnection(), SIGNAL(stateChanged(CoreConnection::ConnectionState)), SLOT(connectionStateChanged(CoreConnection::ConnectionState))); + coreConnection()->init(); } + /*** public static methods ***/ -AbstractUi *Client::mainUi() { - return instance()->_mainUi; +AbstractUi *Client::mainUi() +{ + return instance()->_mainUi; } -void Client::setCoreFeatures(Quassel::Features features) { - _coreFeatures = features; + +void Client::setCoreFeatures(Quassel::Features features) +{ + _coreFeatures = features; } -bool Client::isConnected() { - return instance()->_connected; + +bool Client::isConnected() +{ + return instance()->_connected; } -bool Client::internalCore() { - return currentCoreAccount().isInternal(); + +bool Client::internalCore() +{ + return currentCoreAccount().isInternal(); } + /*** Network handling ***/ -QList Client::networkIds() { - return instance()->_networks.keys(); +QList Client::networkIds() +{ + return instance()->_networks.keys(); } -const Network * Client::network(NetworkId networkid) { - if(instance()->_networks.contains(networkid)) return instance()->_networks[networkid]; - else return 0; + +const Network *Client::network(NetworkId networkid) +{ + if (instance()->_networks.contains(networkid)) return instance()->_networks[networkid]; + else return 0; } -void Client::createNetwork(const NetworkInfo &info, const QStringList &persistentChannels) { - emit instance()->requestCreateNetwork(info, persistentChannels); + +void Client::createNetwork(const NetworkInfo &info, const QStringList &persistentChannels) +{ + emit instance()->requestCreateNetwork(info, persistentChannels); } -void Client::removeNetwork(NetworkId id) { - emit instance()->requestRemoveNetwork(id); + +void Client::removeNetwork(NetworkId id) +{ + emit instance()->requestRemoveNetwork(id); } -void Client::updateNetwork(const NetworkInfo &info) { - Network *netptr = instance()->_networks.value(info.networkId, 0); - if(!netptr) { - qWarning() << "Update for unknown network requested:" << info; - return; - } - netptr->requestSetNetworkInfo(info); + +void Client::updateNetwork(const NetworkInfo &info) +{ + Network *netptr = instance()->_networks.value(info.networkId, 0); + if (!netptr) { + qWarning() << "Update for unknown network requested:" << info; + return; + } + netptr->requestSetNetworkInfo(info); } -void Client::addNetwork(Network *net) { - net->setProxy(signalProxy()); - signalProxy()->synchronize(net); - networkModel()->attachNetwork(net); - connect(net, SIGNAL(destroyed()), instance(), SLOT(networkDestroyed())); - instance()->_networks[net->networkId()] = net; - emit instance()->networkCreated(net->networkId()); + +void Client::addNetwork(Network *net) +{ + net->setProxy(signalProxy()); + signalProxy()->synchronize(net); + networkModel()->attachNetwork(net); + connect(net, SIGNAL(destroyed()), instance(), SLOT(networkDestroyed())); + instance()->_networks[net->networkId()] = net; + emit instance()->networkCreated(net->networkId()); } -void Client::coreNetworkCreated(NetworkId id) { - if(_networks.contains(id)) { - qWarning() << "Creation of already existing network requested!"; - return; - } - Network *net = new Network(id, this); - addNetwork(net); + +void Client::coreNetworkCreated(NetworkId id) +{ + if (_networks.contains(id)) { + qWarning() << "Creation of already existing network requested!"; + return; + } + Network *net = new Network(id, this); + addNetwork(net); } -void Client::coreNetworkRemoved(NetworkId id) { - if(!_networks.contains(id)) - return; - Network *net = _networks.take(id); - emit networkRemoved(net->networkId()); - net->deleteLater(); + +void Client::coreNetworkRemoved(NetworkId id) +{ + if (!_networks.contains(id)) + return; + Network *net = _networks.take(id); + emit networkRemoved(net->networkId()); + net->deleteLater(); } + /*** Identity handling ***/ -QList Client::identityIds() { - return instance()->_identities.keys(); +QList Client::identityIds() +{ + return instance()->_identities.keys(); } -const Identity *Client::identity(IdentityId id) { - if(instance()->_identities.contains(id)) return instance()->_identities[id]; - else return 0; + +const Identity *Client::identity(IdentityId id) +{ + if (instance()->_identities.contains(id)) return instance()->_identities[id]; + else return 0; } -void Client::createIdentity(const CertIdentity &id) { - QVariantMap additional; + +void Client::createIdentity(const CertIdentity &id) +{ + QVariantMap additional; #ifdef HAVE_SSL - additional["KeyPem"] = id.sslKey().toPem(); - additional["CertPem"] = id.sslCert().toPem(); + additional["KeyPem"] = id.sslKey().toPem(); + additional["CertPem"] = id.sslCert().toPem(); #endif - emit instance()->requestCreateIdentity(id, additional); + emit instance()->requestCreateIdentity(id, additional); } -void Client::updateIdentity(IdentityId id, const QVariantMap &ser) { - Identity *idptr = instance()->_identities.value(id, 0); - if(!idptr) { - qWarning() << "Update for unknown identity requested:" << id; - return; - } - idptr->requestUpdate(ser); + +void Client::updateIdentity(IdentityId id, const QVariantMap &ser) +{ + Identity *idptr = instance()->_identities.value(id, 0); + if (!idptr) { + qWarning() << "Update for unknown identity requested:" << id; + return; + } + idptr->requestUpdate(ser); } -void Client::removeIdentity(IdentityId id) { - emit instance()->requestRemoveIdentity(id); + +void Client::removeIdentity(IdentityId id) +{ + emit instance()->requestRemoveIdentity(id); } -void Client::coreIdentityCreated(const Identity &other) { - if(!_identities.contains(other.id())) { - Identity *identity = new Identity(other, this); - _identities[other.id()] = identity; - identity->setInitialized(); - signalProxy()->synchronize(identity); - emit identityCreated(other.id()); - } else { - qWarning() << tr("Identity already exists in client!"); - } + +void Client::coreIdentityCreated(const Identity &other) +{ + if (!_identities.contains(other.id())) { + Identity *identity = new Identity(other, this); + _identities[other.id()] = identity; + identity->setInitialized(); + signalProxy()->synchronize(identity); + emit identityCreated(other.id()); + } + else { + qWarning() << tr("Identity already exists in client!"); + } } -void Client::coreIdentityRemoved(IdentityId id) { - if(_identities.contains(id)) { - emit identityRemoved(id); - Identity *i = _identities.take(id); - i->deleteLater(); - } + +void Client::coreIdentityRemoved(IdentityId id) +{ + if (_identities.contains(id)) { + emit identityRemoved(id); + Identity *i = _identities.take(id); + i->deleteLater(); + } } + /*** User input handling ***/ -void Client::userInput(const BufferInfo &bufferInfo, const QString &message) { - // we need to make sure that AliasManager is ready before processing input - if(aliasManager() && aliasManager()->isInitialized()) - inputHandler()->handleUserInput(bufferInfo, message); - else - instance()-> _userInputBuffer.append(qMakePair(bufferInfo, message)); +void Client::userInput(const BufferInfo &bufferInfo, const QString &message) +{ + // we need to make sure that AliasManager is ready before processing input + if (aliasManager() && aliasManager()->isInitialized()) + inputHandler()->handleUserInput(bufferInfo, message); + else + instance()->_userInputBuffer.append(qMakePair(bufferInfo, message)); } -void Client::sendBufferedUserInput() { - for(int i = 0; i < _userInputBuffer.count(); i++) - userInput(_userInputBuffer.at(i).first, _userInputBuffer.at(i).second); - _userInputBuffer.clear(); +void Client::sendBufferedUserInput() +{ + for (int i = 0; i < _userInputBuffer.count(); i++) + userInput(_userInputBuffer.at(i).first, _userInputBuffer.at(i).second); + + _userInputBuffer.clear(); } -/*** core connection stuff ***/ -void Client::connectionStateChanged(CoreConnection::ConnectionState state) { - switch(state) { - case CoreConnection::Disconnected: - setDisconnectedFromCore(); - break; - case CoreConnection::Synchronized: - setSyncedToCore(); - break; - default: - break; - } -} - -void Client::setSyncedToCore() { - // create buffersyncer - Q_ASSERT(!_bufferSyncer); - _bufferSyncer = new BufferSyncer(this); - connect(bufferSyncer(), SIGNAL(lastSeenMsgSet(BufferId, MsgId)), _networkModel, SLOT(setLastSeenMsgId(BufferId, MsgId))); - connect(bufferSyncer(), SIGNAL(markerLineSet(BufferId,MsgId)), _networkModel, SLOT(setMarkerLineMsgId(BufferId,MsgId))); - connect(bufferSyncer(), SIGNAL(bufferRemoved(BufferId)), this, SLOT(bufferRemoved(BufferId))); - connect(bufferSyncer(), SIGNAL(bufferRenamed(BufferId, QString)), this, SLOT(bufferRenamed(BufferId, QString))); - connect(bufferSyncer(), SIGNAL(buffersPermanentlyMerged(BufferId, BufferId)), this, SLOT(buffersPermanentlyMerged(BufferId, BufferId))); - connect(bufferSyncer(), SIGNAL(buffersPermanentlyMerged(BufferId, BufferId)), _messageModel, SLOT(buffersPermanentlyMerged(BufferId, BufferId))); - connect(bufferSyncer(), SIGNAL(bufferMarkedAsRead(BufferId)), SIGNAL(bufferMarkedAsRead(BufferId))); - connect(networkModel(), SIGNAL(requestSetLastSeenMsg(BufferId, MsgId)), bufferSyncer(), SLOT(requestSetLastSeenMsg(BufferId, const MsgId &))); - signalProxy()->synchronize(bufferSyncer()); - - // create a new BufferViewManager - Q_ASSERT(!_bufferViewManager); - _bufferViewManager = new ClientBufferViewManager(signalProxy(), this); - connect(_bufferViewManager, SIGNAL(initDone()), _bufferViewOverlay, SLOT(restore())); - - // create AliasManager - Q_ASSERT(!_aliasManager); - _aliasManager = new ClientAliasManager(this); - connect(aliasManager(), SIGNAL(initDone()), SLOT(sendBufferedUserInput())); - signalProxy()->synchronize(aliasManager()); - - // create NetworkConfig - Q_ASSERT(!_networkConfig); - _networkConfig = new NetworkConfig("GlobalNetworkConfig", this); - signalProxy()->synchronize(networkConfig()); - - // create IgnoreListManager - Q_ASSERT(!_ignoreListManager); - _ignoreListManager = new ClientIgnoreListManager(this); - signalProxy()->synchronize(ignoreListManager()); - - // trigger backlog request once all active bufferviews are initialized - connect(bufferViewOverlay(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); - - _connected = true; - emit connected(); - emit coreConnectionStateChanged(true); -} - -void Client::requestInitialBacklog() { - // usually it _should_ take longer until the bufferViews are initialized, so that's what - // triggers this slot. But we have to make sure that we know all buffers yet. - // so we check the BufferSyncer and in case it wasn't initialized we wait for that instead - if(!bufferSyncer()->isInitialized()) { - disconnect(bufferViewOverlay(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); - connect(bufferSyncer(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); - return; - } - disconnect(bufferViewOverlay(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); - disconnect(bufferSyncer(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); +/*** core connection stuff ***/ - _backlogManager->requestInitialBacklog(); +void Client::connectionStateChanged(CoreConnection::ConnectionState state) +{ + switch (state) { + case CoreConnection::Disconnected: + setDisconnectedFromCore(); + break; + case CoreConnection::Synchronized: + setSyncedToCore(); + break; + default: + break; + } } -void Client::disconnectFromCore() { - if(!coreConnection()->isConnected()) - return; - coreConnection()->disconnectFromCore(); +void Client::setSyncedToCore() +{ + // create buffersyncer + Q_ASSERT(!_bufferSyncer); + _bufferSyncer = new BufferSyncer(this); + connect(bufferSyncer(), SIGNAL(lastSeenMsgSet(BufferId, MsgId)), _networkModel, SLOT(setLastSeenMsgId(BufferId, MsgId))); + connect(bufferSyncer(), SIGNAL(markerLineSet(BufferId, MsgId)), _networkModel, SLOT(setMarkerLineMsgId(BufferId, MsgId))); + connect(bufferSyncer(), SIGNAL(bufferRemoved(BufferId)), this, SLOT(bufferRemoved(BufferId))); + connect(bufferSyncer(), SIGNAL(bufferRenamed(BufferId, QString)), this, SLOT(bufferRenamed(BufferId, QString))); + connect(bufferSyncer(), SIGNAL(buffersPermanentlyMerged(BufferId, BufferId)), this, SLOT(buffersPermanentlyMerged(BufferId, BufferId))); + connect(bufferSyncer(), SIGNAL(buffersPermanentlyMerged(BufferId, BufferId)), _messageModel, SLOT(buffersPermanentlyMerged(BufferId, BufferId))); + connect(bufferSyncer(), SIGNAL(bufferMarkedAsRead(BufferId)), SIGNAL(bufferMarkedAsRead(BufferId))); + connect(networkModel(), SIGNAL(requestSetLastSeenMsg(BufferId, MsgId)), bufferSyncer(), SLOT(requestSetLastSeenMsg(BufferId, const MsgId &))); + signalProxy()->synchronize(bufferSyncer()); + + // create a new BufferViewManager + Q_ASSERT(!_bufferViewManager); + _bufferViewManager = new ClientBufferViewManager(signalProxy(), this); + connect(_bufferViewManager, SIGNAL(initDone()), _bufferViewOverlay, SLOT(restore())); + + // create AliasManager + Q_ASSERT(!_aliasManager); + _aliasManager = new ClientAliasManager(this); + connect(aliasManager(), SIGNAL(initDone()), SLOT(sendBufferedUserInput())); + signalProxy()->synchronize(aliasManager()); + + // create NetworkConfig + Q_ASSERT(!_networkConfig); + _networkConfig = new NetworkConfig("GlobalNetworkConfig", this); + signalProxy()->synchronize(networkConfig()); + + // create IgnoreListManager + Q_ASSERT(!_ignoreListManager); + _ignoreListManager = new ClientIgnoreListManager(this); + signalProxy()->synchronize(ignoreListManager()); + + // trigger backlog request once all active bufferviews are initialized + connect(bufferViewOverlay(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); + + _connected = true; + emit connected(); + emit coreConnectionStateChanged(true); +} + + +void Client::requestInitialBacklog() +{ + // usually it _should_ take longer until the bufferViews are initialized, so that's what + // triggers this slot. But we have to make sure that we know all buffers yet. + // so we check the BufferSyncer and in case it wasn't initialized we wait for that instead + if (!bufferSyncer()->isInitialized()) { + disconnect(bufferViewOverlay(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); + connect(bufferSyncer(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); + return; + } + disconnect(bufferViewOverlay(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); + disconnect(bufferSyncer(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); + + _backlogManager->requestInitialBacklog(); } -void Client::setDisconnectedFromCore() { - _connected = false; - _coreFeatures = 0; - emit disconnected(); - emit coreConnectionStateChanged(false); +void Client::disconnectFromCore() +{ + if (!coreConnection()->isConnected()) + return; + + coreConnection()->disconnectFromCore(); +} - backlogManager()->reset(); - messageProcessor()->reset(); - // Clear internal data. Hopefully nothing relies on it at this point. +void Client::setDisconnectedFromCore() +{ + _connected = false; + _coreFeatures = 0; - if(_bufferSyncer) { - _bufferSyncer->deleteLater(); - _bufferSyncer = 0; - } + emit disconnected(); + emit coreConnectionStateChanged(false); - if(_bufferViewManager) { - _bufferViewManager->deleteLater(); - _bufferViewManager = 0; - } + backlogManager()->reset(); + messageProcessor()->reset(); - _bufferViewOverlay->reset(); + // Clear internal data. Hopefully nothing relies on it at this point. - if(_aliasManager) { - _aliasManager->deleteLater(); - _aliasManager = 0; - } + if (_bufferSyncer) { + _bufferSyncer->deleteLater(); + _bufferSyncer = 0; + } - if(_ignoreListManager) { - _ignoreListManager->deleteLater(); - _ignoreListManager = 0; - } - // we probably don't want to save pending input for reconnect - _userInputBuffer.clear(); + if (_bufferViewManager) { + _bufferViewManager->deleteLater(); + _bufferViewManager = 0; + } - _messageModel->clear(); - _networkModel->clear(); + _bufferViewOverlay->reset(); - QHash::iterator netIter = _networks.begin(); - while(netIter != _networks.end()) { - Network *net = netIter.value(); - emit networkRemoved(net->networkId()); - disconnect(net, SIGNAL(destroyed()), this, 0); - netIter = _networks.erase(netIter); - net->deleteLater(); - } - Q_ASSERT(_networks.isEmpty()); + if (_aliasManager) { + _aliasManager->deleteLater(); + _aliasManager = 0; + } - QHash::iterator idIter = _identities.begin(); - while(idIter != _identities.end()) { - emit identityRemoved(idIter.key()); - Identity *id = idIter.value(); - idIter = _identities.erase(idIter); - id->deleteLater(); - } - Q_ASSERT(_identities.isEmpty()); + if (_ignoreListManager) { + _ignoreListManager->deleteLater(); + _ignoreListManager = 0; + } + // we probably don't want to save pending input for reconnect + _userInputBuffer.clear(); + + _messageModel->clear(); + _networkModel->clear(); + + QHash::iterator netIter = _networks.begin(); + while (netIter != _networks.end()) { + Network *net = netIter.value(); + emit networkRemoved(net->networkId()); + disconnect(net, SIGNAL(destroyed()), this, 0); + netIter = _networks.erase(netIter); + net->deleteLater(); + } + Q_ASSERT(_networks.isEmpty()); + + QHash::iterator idIter = _identities.begin(); + while (idIter != _identities.end()) { + emit identityRemoved(idIter.key()); + Identity *id = idIter.value(); + idIter = _identities.erase(idIter); + id->deleteLater(); + } + Q_ASSERT(_identities.isEmpty()); - if(_networkConfig) { - _networkConfig->deleteLater(); - _networkConfig = 0; - } + if (_networkConfig) { + _networkConfig->deleteLater(); + _networkConfig = 0; + } } + /*** ***/ -void Client::networkDestroyed() { - Network *net = static_cast(sender()); - QHash::iterator netIter = _networks.begin(); - while(netIter != _networks.end()) { - if(*netIter == net) { - netIter = _networks.erase(netIter); - break; - } else { - netIter++; +void Client::networkDestroyed() +{ + Network *net = static_cast(sender()); + QHash::iterator netIter = _networks.begin(); + while (netIter != _networks.end()) { + if (*netIter == net) { + netIter = _networks.erase(netIter); + break; + } + else { + netIter++; + } } - } } + // Hmm... we never used this... -void Client::recvStatusMsg(QString /*net*/, QString /*msg*/) { - //recvMessage(net, Message::server("", QString("[STATUS] %1").arg(msg))); +void Client::recvStatusMsg(QString /*net*/, QString /*msg*/) +{ + //recvMessage(net, Message::server("", QString("[STATUS] %1").arg(msg))); } -void Client::recvMessage(const Message &msg) { - Message msg_ = msg; - messageProcessor()->process(msg_); + +void Client::recvMessage(const Message &msg) +{ + Message msg_ = msg; + messageProcessor()->process(msg_); } -void Client::setBufferLastSeenMsg(BufferId id, const MsgId &msgId) { - if(bufferSyncer()) - bufferSyncer()->requestSetLastSeenMsg(id, msgId); + +void Client::setBufferLastSeenMsg(BufferId id, const MsgId &msgId) +{ + if (bufferSyncer()) + bufferSyncer()->requestSetLastSeenMsg(id, msgId); } -void Client::setMarkerLine(BufferId id, const MsgId &msgId) { - if(bufferSyncer()) - bufferSyncer()->requestSetMarkerLine(id, msgId); + +void Client::setMarkerLine(BufferId id, const MsgId &msgId) +{ + if (bufferSyncer()) + bufferSyncer()->requestSetMarkerLine(id, msgId); } -MsgId Client::markerLine(BufferId id) { - if(id.isValid() && networkModel()) - return networkModel()->markerLineMsgId(id); - return MsgId(); + +MsgId Client::markerLine(BufferId id) +{ + if (id.isValid() && networkModel()) + return networkModel()->markerLineMsgId(id); + return MsgId(); } -void Client::removeBuffer(BufferId id) { - if(!bufferSyncer()) return; - bufferSyncer()->requestRemoveBuffer(id); + +void Client::removeBuffer(BufferId id) +{ + if (!bufferSyncer()) return; + bufferSyncer()->requestRemoveBuffer(id); } -void Client::renameBuffer(BufferId bufferId, const QString &newName) { - if(!bufferSyncer()) - return; - bufferSyncer()->requestRenameBuffer(bufferId, newName); + +void Client::renameBuffer(BufferId bufferId, const QString &newName) +{ + if (!bufferSyncer()) + return; + bufferSyncer()->requestRenameBuffer(bufferId, newName); } -void Client::mergeBuffersPermanently(BufferId bufferId1, BufferId bufferId2) { - if(!bufferSyncer()) - return; - bufferSyncer()->requestMergeBuffersPermanently(bufferId1, bufferId2); + +void Client::mergeBuffersPermanently(BufferId bufferId1, BufferId bufferId2) +{ + if (!bufferSyncer()) + return; + bufferSyncer()->requestMergeBuffersPermanently(bufferId1, bufferId2); } -void Client::purgeKnownBufferIds() { - if(!bufferSyncer()) - return; - bufferSyncer()->requestPurgeBufferIds(); + +void Client::purgeKnownBufferIds() +{ + if (!bufferSyncer()) + return; + bufferSyncer()->requestPurgeBufferIds(); } -void Client::bufferRemoved(BufferId bufferId) { - // select a sane buffer (status buffer) - /* we have to manually select a buffer because otherwise inconsitent changes - * to the model might occur: - * the result of a buffer removal triggers a change in the selection model. - * the newly selected buffer might be a channel that hasn't been selected yet - * and a new nickview would be created (which never heard of the "rowsAboutToBeRemoved"). - * this new view (and/or) its sort filter will then only receive a "rowsRemoved" signal. - */ - QModelIndex current = bufferModel()->currentIndex(); - if(current.data(NetworkModel::BufferIdRole).value() == bufferId) { - bufferModel()->setCurrentIndex(current.sibling(0,0)); - } - // and remove it from the model - networkModel()->removeBuffer(bufferId); +void Client::bufferRemoved(BufferId bufferId) +{ + // select a sane buffer (status buffer) + /* we have to manually select a buffer because otherwise inconsitent changes + * to the model might occur: + * the result of a buffer removal triggers a change in the selection model. + * the newly selected buffer might be a channel that hasn't been selected yet + * and a new nickview would be created (which never heard of the "rowsAboutToBeRemoved"). + * this new view (and/or) its sort filter will then only receive a "rowsRemoved" signal. + */ + QModelIndex current = bufferModel()->currentIndex(); + if (current.data(NetworkModel::BufferIdRole).value() == bufferId) { + bufferModel()->setCurrentIndex(current.sibling(0, 0)); + } + + // and remove it from the model + networkModel()->removeBuffer(bufferId); } -void Client::bufferRenamed(BufferId bufferId, const QString &newName) { - QModelIndex bufferIndex = networkModel()->bufferIndex(bufferId); - if(bufferIndex.isValid()) { - networkModel()->setData(bufferIndex, newName, Qt::DisplayRole); - } + +void Client::bufferRenamed(BufferId bufferId, const QString &newName) +{ + QModelIndex bufferIndex = networkModel()->bufferIndex(bufferId); + if (bufferIndex.isValid()) { + networkModel()->setData(bufferIndex, newName, Qt::DisplayRole); + } } -void Client::buffersPermanentlyMerged(BufferId bufferId1, BufferId bufferId2) { - QModelIndex idx = networkModel()->bufferIndex(bufferId1); - bufferModel()->setCurrentIndex(bufferModel()->mapFromSource(idx)); - networkModel()->removeBuffer(bufferId2); + +void Client::buffersPermanentlyMerged(BufferId bufferId1, BufferId bufferId2) +{ + QModelIndex idx = networkModel()->bufferIndex(bufferId1); + bufferModel()->setCurrentIndex(bufferModel()->mapFromSource(idx)); + networkModel()->removeBuffer(bufferId2); } -void Client::markBufferAsRead(BufferId id) { - if(bufferSyncer() && id.isValid()) - bufferSyncer()->requestMarkBufferAsRead(id); + +void Client::markBufferAsRead(BufferId id) +{ + if (bufferSyncer() && id.isValid()) + bufferSyncer()->requestMarkBufferAsRead(id); } -void Client::logMessage(QtMsgType type, const char *msg) { - fprintf(stderr, "%s\n", msg); - fflush(stderr); - if(type == QtFatalMsg) { - Quassel::logFatalMessage(msg); - } else { - QString msgString = QString("%1\n").arg(msg); - //Check to see if there is an instance around, else we risk recursions - //when calling instance() and creating new ones. - if (!instanceExists()) - return; +void Client::logMessage(QtMsgType type, const char *msg) +{ + fprintf(stderr, "%s\n", msg); + fflush(stderr); + if (type == QtFatalMsg) { + Quassel::logFatalMessage(msg); + } + else { + QString msgString = QString("%1\n").arg(msg); + + //Check to see if there is an instance around, else we risk recursions + //when calling instance() and creating new ones. + if (!instanceExists()) + return; - instance()->_debugLog << msgString; - emit instance()->logUpdated(msgString); - } + instance()->_debugLog << msgString; + emit instance()->logUpdated(msgString); + } } diff --git a/src/client/client.h b/src/client/client.h index cc3803bc..a6e56221 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -57,201 +57,203 @@ class NetworkConfig; class SignalProxy; struct NetworkInfo; -class Client : public QObject { - Q_OBJECT +class Client : public QObject +{ + Q_OBJECT public: - enum ClientMode { - LocalCore, - RemoteCore - }; - - static bool instanceExists(); - static Client *instance(); - static void destroy(); - static void init(AbstractUi *); - static AbstractUi *mainUi(); - - static QList networkIds(); - static const Network * network(NetworkId); - - static QList identityIds(); - static const Identity *identity(IdentityId); - - //! Request creation of an identity with the given data. - /** The request will be sent to the core, and will be propagated back to all the clients - * with a new valid IdentityId. - * \param identity The identity template for the new identity. It does not need to have a valid ID. - */ - static void createIdentity(const CertIdentity &identity); - - //! Request update of an identity with the given data. - /** The request will be sent to the core, and will be propagated back to all the clients. - * \param id The identity to be updated. - * \param serializedData The identity's content (cf. SyncableObject::toVariantMap()) - */ - static void updateIdentity(IdentityId id, const QVariantMap &serializedData); - - //! Request removal of the identity with the given ID from the core (and all the clients, of course). - /** \param id The ID of the identity to be removed. - */ - static void removeIdentity(IdentityId id); - - static void createNetwork(const NetworkInfo &info, const QStringList &persistentChannels = QStringList()); - static void updateNetwork(const NetworkInfo &info); - static void removeNetwork(NetworkId id); - - static inline NetworkModel *networkModel() { return instance()->_networkModel; } - static inline BufferModel *bufferModel() { return instance()->_bufferModel; } - static inline MessageModel *messageModel() { return instance()->_messageModel; } - static inline AbstractMessageProcessor *messageProcessor() { return instance()->_messageProcessor; } - static inline SignalProxy *signalProxy() { return instance()->_signalProxy; } - - static inline ClientAliasManager *aliasManager() { return instance()->_aliasManager; } - static inline ClientBacklogManager *backlogManager() { return instance()->_backlogManager; } - static inline ClientIrcListHelper *ircListHelper() { return instance()->_ircListHelper; } - static inline ClientBufferViewManager *bufferViewManager() { return instance()->_bufferViewManager; } - static inline BufferViewOverlay *bufferViewOverlay() { return instance()->_bufferViewOverlay; } - static inline ClientUserInputHandler *inputHandler() { return instance()->_inputHandler; } - static inline NetworkConfig *networkConfig() { return instance()->_networkConfig; } - static inline ClientIgnoreListManager *ignoreListManager() { return instance()->_ignoreListManager; } - - static inline CoreAccountModel *coreAccountModel() { return instance()->_coreAccountModel; } - static inline CoreConnection *coreConnection() { return instance()->_coreConnection; } - static inline CoreAccount currentCoreAccount() { return coreConnection()->currentAccount(); } - static inline Quassel::Features coreFeatures() { return _coreFeatures; } - - static bool isConnected(); - static bool internalCore(); - - static void userInput(const BufferInfo &bufferInfo, const QString &message); - - static void setBufferLastSeenMsg(BufferId id, const MsgId &msgId); // this is synced to core and other clients - static void setMarkerLine(BufferId id, const MsgId &msgId); // this is synced to core and other clients - static MsgId markerLine(BufferId id); - - static void removeBuffer(BufferId id); - static void renameBuffer(BufferId bufferId, const QString &newName); - static void mergeBuffersPermanently(BufferId bufferId1, BufferId bufferId2); - static void purgeKnownBufferIds(); - - static void logMessage(QtMsgType type, const char *msg); - static inline const QString &debugLog() { return instance()->_debugLogBuffer; } + enum ClientMode { + LocalCore, + RemoteCore + }; + + static bool instanceExists(); + static Client *instance(); + static void destroy(); + static void init(AbstractUi *); + static AbstractUi *mainUi(); + + static QList networkIds(); + static const Network *network(NetworkId); + + static QList identityIds(); + static const Identity *identity(IdentityId); + + //! Request creation of an identity with the given data. + /** The request will be sent to the core, and will be propagated back to all the clients + * with a new valid IdentityId. + * \param identity The identity template for the new identity. It does not need to have a valid ID. + */ + static void createIdentity(const CertIdentity &identity); + + //! Request update of an identity with the given data. + /** The request will be sent to the core, and will be propagated back to all the clients. + * \param id The identity to be updated. + * \param serializedData The identity's content (cf. SyncableObject::toVariantMap()) + */ + static void updateIdentity(IdentityId id, const QVariantMap &serializedData); + + //! Request removal of the identity with the given ID from the core (and all the clients, of course). + /** \param id The ID of the identity to be removed. + */ + static void removeIdentity(IdentityId id); + + static void createNetwork(const NetworkInfo &info, const QStringList &persistentChannels = QStringList()); + static void updateNetwork(const NetworkInfo &info); + static void removeNetwork(NetworkId id); + + static inline NetworkModel *networkModel() { return instance()->_networkModel; } + static inline BufferModel *bufferModel() { return instance()->_bufferModel; } + static inline MessageModel *messageModel() { return instance()->_messageModel; } + static inline AbstractMessageProcessor *messageProcessor() { return instance()->_messageProcessor; } + static inline SignalProxy *signalProxy() { return instance()->_signalProxy; } + + static inline ClientAliasManager *aliasManager() { return instance()->_aliasManager; } + static inline ClientBacklogManager *backlogManager() { return instance()->_backlogManager; } + static inline ClientIrcListHelper *ircListHelper() { return instance()->_ircListHelper; } + static inline ClientBufferViewManager *bufferViewManager() { return instance()->_bufferViewManager; } + static inline BufferViewOverlay *bufferViewOverlay() { return instance()->_bufferViewOverlay; } + static inline ClientUserInputHandler *inputHandler() { return instance()->_inputHandler; } + static inline NetworkConfig *networkConfig() { return instance()->_networkConfig; } + static inline ClientIgnoreListManager *ignoreListManager() { return instance()->_ignoreListManager; } + + static inline CoreAccountModel *coreAccountModel() { return instance()->_coreAccountModel; } + static inline CoreConnection *coreConnection() { return instance()->_coreConnection; } + static inline CoreAccount currentCoreAccount() { return coreConnection()->currentAccount(); } + static inline Quassel::Features coreFeatures() { return _coreFeatures; } + + static bool isConnected(); + static bool internalCore(); + + static void userInput(const BufferInfo &bufferInfo, const QString &message); + + static void setBufferLastSeenMsg(BufferId id, const MsgId &msgId); // this is synced to core and other clients + static void setMarkerLine(BufferId id, const MsgId &msgId); // this is synced to core and other clients + static MsgId markerLine(BufferId id); + + static void removeBuffer(BufferId id); + static void renameBuffer(BufferId bufferId, const QString &newName); + static void mergeBuffersPermanently(BufferId bufferId1, BufferId bufferId2); + static void purgeKnownBufferIds(); + + static void logMessage(QtMsgType type, const char *msg); + static inline const QString &debugLog() { return instance()->_debugLogBuffer; } signals: - void requestNetworkStates(); + void requestNetworkStates(); - void showConfigWizard(const QVariantMap &coredata); + void showConfigWizard(const QVariantMap &coredata); - void connected(); - void disconnected(); - void coreConnectionStateChanged(bool); + void connected(); + void disconnected(); + void coreConnectionStateChanged(bool); - //! The identity with the given ID has been newly created in core and client. - /** \param id The ID of the newly created identity. - */ - void identityCreated(IdentityId id); + //! The identity with the given ID has been newly created in core and client. + /** \param id The ID of the newly created identity. + */ + void identityCreated(IdentityId id); - //! The identity with the given ID has been removed. - /** Upon emitting this signal, the identity is already gone from the core, and it will - * be deleted from the client immediately afterwards, so connected slots need to clean - * up their stuff. - * \param id The ID of the identity about to be removed. - */ - void identityRemoved(IdentityId id); + //! The identity with the given ID has been removed. + /** Upon emitting this signal, the identity is already gone from the core, and it will + * be deleted from the client immediately afterwards, so connected slots need to clean + * up their stuff. + * \param id The ID of the identity about to be removed. + */ + void identityRemoved(IdentityId id); - //! Sent to the core when an identity shall be created. Should not be used elsewhere. - void requestCreateIdentity(const Identity &, const QVariantMap &); - //! Sent to the core when an identity shall be removed. Should not be used elsewhere. - void requestRemoveIdentity(IdentityId); + //! Sent to the core when an identity shall be created. Should not be used elsewhere. + void requestCreateIdentity(const Identity &, const QVariantMap &); + //! Sent to the core when an identity shall be removed. Should not be used elsewhere. + void requestRemoveIdentity(IdentityId); - void networkCreated(NetworkId id); - void networkRemoved(NetworkId id); + void networkCreated(NetworkId id); + void networkRemoved(NetworkId id); - void requestCreateNetwork(const NetworkInfo &info, const QStringList &persistentChannels = QStringList()); - void requestRemoveNetwork(NetworkId); + void requestCreateNetwork(const NetworkInfo &info, const QStringList &persistentChannels = QStringList()); + void requestRemoveNetwork(NetworkId); - void logUpdated(const QString &msg); + void logUpdated(const QString &msg); - //! Emitted when a buffer has been marked as read - /** This is currently triggered by setting lastSeenMsg, either local or remote, - * or by bringing the window to front. - * \param id The buffer that has been marked as read - */ - void bufferMarkedAsRead(BufferId id); + //! Emitted when a buffer has been marked as read + /** This is currently triggered by setting lastSeenMsg, either local or remote, + * or by bringing the window to front. + * \param id The buffer that has been marked as read + */ + void bufferMarkedAsRead(BufferId id); public slots: - void disconnectFromCore(); + void disconnectFromCore(); - void bufferRemoved(BufferId bufferId); - void bufferRenamed(BufferId bufferId, const QString &newName); - void buffersPermanentlyMerged(BufferId bufferId1, BufferId bufferId2); + void bufferRemoved(BufferId bufferId); + void bufferRenamed(BufferId bufferId, const QString &newName); + void buffersPermanentlyMerged(BufferId bufferId1, BufferId bufferId2); - void markBufferAsRead(BufferId id); + void markBufferAsRead(BufferId id); private slots: - void setSyncedToCore(); - void setDisconnectedFromCore(); - void connectionStateChanged(CoreConnection::ConnectionState); + void setSyncedToCore(); + void setDisconnectedFromCore(); + void connectionStateChanged(CoreConnection::ConnectionState); - void recvMessage(const Message &message); - void recvStatusMsg(QString network, QString message); + void recvMessage(const Message &message); + void recvStatusMsg(QString network, QString message); - void networkDestroyed(); - void coreIdentityCreated(const Identity &); - void coreIdentityRemoved(IdentityId); - void coreNetworkCreated(NetworkId); - void coreNetworkRemoved(NetworkId); + void networkDestroyed(); + void coreIdentityCreated(const Identity &); + void coreIdentityRemoved(IdentityId); + void coreNetworkCreated(NetworkId); + void coreNetworkRemoved(NetworkId); - void requestInitialBacklog(); + void requestInitialBacklog(); - void sendBufferedUserInput(); + void sendBufferedUserInput(); private: - Client(QObject *parent = 0); - virtual ~Client(); - void init(); + Client(QObject *parent = 0); + virtual ~Client(); + void init(); - static void addNetwork(Network *); - static void setCoreFeatures(Quassel::Features); - static inline BufferSyncer *bufferSyncer() { return instance()->_bufferSyncer; } + static void addNetwork(Network *); + static void setCoreFeatures(Quassel::Features); + static inline BufferSyncer *bufferSyncer() { return instance()->_bufferSyncer; } - static QPointer instanceptr; + static QPointer instanceptr; - SignalProxy * _signalProxy; - AbstractUi * _mainUi; - NetworkModel * _networkModel; - BufferModel * _bufferModel; - BufferSyncer * _bufferSyncer; - ClientAliasManager *_aliasManager; - ClientBacklogManager *_backlogManager; - ClientBufferViewManager *_bufferViewManager; - BufferViewOverlay *_bufferViewOverlay; - ClientIrcListHelper *_ircListHelper; - ClientUserInputHandler *_inputHandler; - NetworkConfig *_networkConfig; - ClientIgnoreListManager *_ignoreListManager; + SignalProxy *_signalProxy; + AbstractUi *_mainUi; + NetworkModel *_networkModel; + BufferModel *_bufferModel; + BufferSyncer *_bufferSyncer; + ClientAliasManager *_aliasManager; + ClientBacklogManager *_backlogManager; + ClientBufferViewManager *_bufferViewManager; + BufferViewOverlay *_bufferViewOverlay; + ClientIrcListHelper *_ircListHelper; + ClientUserInputHandler *_inputHandler; + NetworkConfig *_networkConfig; + ClientIgnoreListManager *_ignoreListManager; - MessageModel *_messageModel; - AbstractMessageProcessor *_messageProcessor; + MessageModel *_messageModel; + AbstractMessageProcessor *_messageProcessor; - CoreAccountModel *_coreAccountModel; - CoreConnection *_coreConnection; + CoreAccountModel *_coreAccountModel; + CoreConnection *_coreConnection; - ClientMode clientMode; + ClientMode clientMode; - QHash _networks; - QHash _identities; + QHash _networks; + QHash _identities; - bool _connected; - static Quassel::Features _coreFeatures; + bool _connected; + static Quassel::Features _coreFeatures; - QString _debugLogBuffer; - QTextStream _debugLog; + QString _debugLogBuffer; + QTextStream _debugLog; - QList > _userInputBuffer; + QList > _userInputBuffer; - friend class CoreConnection; + friend class CoreConnection; }; + #endif diff --git a/src/client/clientaliasmanager.cpp b/src/client/clientaliasmanager.cpp index 3b4a9539..da97f08e 100644 --- a/src/client/clientaliasmanager.cpp +++ b/src/client/clientaliasmanager.cpp @@ -24,11 +24,12 @@ INIT_SYNCABLE_OBJECT(ClientAliasManager) ClientAliasManager::ClientAliasManager(QObject *parent) - : AliasManager(parent) + : AliasManager(parent) { - } -const Network *ClientAliasManager::network(NetworkId id) const { - return Client::network(id); + +const Network *ClientAliasManager::network(NetworkId id) const +{ + return Client::network(id); } diff --git a/src/client/clientaliasmanager.h b/src/client/clientaliasmanager.h index 8b6aa37d..5598f5f5 100644 --- a/src/client/clientaliasmanager.h +++ b/src/client/clientaliasmanager.h @@ -23,18 +23,19 @@ #include "aliasmanager.h" -class ClientAliasManager : public AliasManager { - SYNCABLE_OBJECT - Q_OBJECT +class ClientAliasManager : public AliasManager +{ + SYNCABLE_OBJECT + Q_OBJECT public: - explicit ClientAliasManager(QObject *parent = 0); + explicit ClientAliasManager(QObject *parent = 0); - inline virtual const QMetaObject *syncMetaObject() const { return &AliasManager::staticMetaObject; } + inline virtual const QMetaObject *syncMetaObject() const { return &AliasManager::staticMetaObject; } protected: - const Network *network(NetworkId) const; - + const Network *network(NetworkId) const; }; + #endif //CLIENTALIASMANAGER_H diff --git a/src/client/clientbacklogmanager.cpp b/src/client/clientbacklogmanager.cpp index 8b6e2e47..4b4683fd 100644 --- a/src/client/clientbacklogmanager.cpp +++ b/src/client/clientbacklogmanager.cpp @@ -31,139 +31,158 @@ INIT_SYNCABLE_OBJECT(ClientBacklogManager) ClientBacklogManager::ClientBacklogManager(QObject *parent) - : BacklogManager(parent), - _requester(0), - _initBacklogRequested(false) + : BacklogManager(parent), + _requester(0), + _initBacklogRequested(false) { } -QVariantList ClientBacklogManager::requestBacklog(BufferId bufferId, MsgId first, MsgId last, int limit, int additional) { - _buffersRequested << bufferId; - return BacklogManager::requestBacklog(bufferId, first, last, limit, additional); + +QVariantList ClientBacklogManager::requestBacklog(BufferId bufferId, MsgId first, MsgId last, int limit, int additional) +{ + _buffersRequested << bufferId; + return BacklogManager::requestBacklog(bufferId, first, last, limit, additional); } -void ClientBacklogManager::receiveBacklog(BufferId bufferId, MsgId first, MsgId last, int limit, int additional, QVariantList msgs) { - Q_UNUSED(first) Q_UNUSED(last) Q_UNUSED(limit) Q_UNUSED(additional) - emit messagesReceived(bufferId, msgs.count()); +void ClientBacklogManager::receiveBacklog(BufferId bufferId, MsgId first, MsgId last, int limit, int additional, QVariantList msgs) +{ + Q_UNUSED(first) Q_UNUSED(last) Q_UNUSED(limit) Q_UNUSED(additional) - MessageList msglist; - foreach(QVariant v, msgs) { - Message msg = v.value(); - msg.setFlags(msg.flags() | Message::Backlog); - msglist << msg; - } + emit messagesReceived(bufferId, msgs.count()); - if(isBuffering()) { - bool lastPart = !_requester->buffer(bufferId, msglist); - updateProgress(_requester->totalBuffers() - _requester->buffersWaiting(), _requester->totalBuffers()); - if(lastPart) { - dispatchMessages(_requester->bufferedMessages(), true); - _requester->flushBuffer(); + MessageList msglist; + foreach(QVariant v, msgs) { + Message msg = v.value(); + msg.setFlags(msg.flags() | Message::Backlog); + msglist << msg; + } + + if (isBuffering()) { + bool lastPart = !_requester->buffer(bufferId, msglist); + updateProgress(_requester->totalBuffers() - _requester->buffersWaiting(), _requester->totalBuffers()); + if (lastPart) { + dispatchMessages(_requester->bufferedMessages(), true); + _requester->flushBuffer(); + } + } + else { + dispatchMessages(msglist); } - } else { - dispatchMessages(msglist); - } } -void ClientBacklogManager::receiveBacklogAll(MsgId first, MsgId last, int limit, int additional, QVariantList msgs) { - Q_UNUSED(first) Q_UNUSED(last) Q_UNUSED(limit) Q_UNUSED(additional) - MessageList msglist; - foreach(QVariant v, msgs) { - Message msg = v.value(); - msg.setFlags(msg.flags() | Message::Backlog); - msglist << msg; - } +void ClientBacklogManager::receiveBacklogAll(MsgId first, MsgId last, int limit, int additional, QVariantList msgs) +{ + Q_UNUSED(first) Q_UNUSED(last) Q_UNUSED(limit) Q_UNUSED(additional) - dispatchMessages(msglist); + MessageList msglist; + foreach(QVariant v, msgs) { + Message msg = v.value(); + msg.setFlags(msg.flags() | Message::Backlog); + msglist << msg; + } + + dispatchMessages(msglist); } -void ClientBacklogManager::requestInitialBacklog() { - if(_initBacklogRequested) { - Q_ASSERT(_requester); - qWarning() << "ClientBacklogManager::requestInitialBacklog() called twice in the same session! (Backlog has already been requested)"; - return; - } - - BacklogSettings settings; - switch(settings.requesterType()) { - case BacklogRequester::GlobalUnread: - _requester = new GlobalUnreadBacklogRequester(this); - break; - case BacklogRequester::PerBufferUnread: - _requester = new PerBufferUnreadBacklogRequester(this); - break; - case BacklogRequester::PerBufferFixed: - default: - _requester = new FixedBacklogRequester(this); - }; - - _requester->requestInitialBacklog(); - _initBacklogRequested = true; - if(_requester->isBuffering()) { - updateProgress(0, _requester->totalBuffers()); - } + +void ClientBacklogManager::requestInitialBacklog() +{ + if (_initBacklogRequested) { + Q_ASSERT(_requester); + qWarning() << "ClientBacklogManager::requestInitialBacklog() called twice in the same session! (Backlog has already been requested)"; + return; + } + + BacklogSettings settings; + switch (settings.requesterType()) { + case BacklogRequester::GlobalUnread: + _requester = new GlobalUnreadBacklogRequester(this); + break; + case BacklogRequester::PerBufferUnread: + _requester = new PerBufferUnreadBacklogRequester(this); + break; + case BacklogRequester::PerBufferFixed: + default: + _requester = new FixedBacklogRequester(this); + }; + + _requester->requestInitialBacklog(); + _initBacklogRequested = true; + if (_requester->isBuffering()) { + updateProgress(0, _requester->totalBuffers()); + } } -BufferIdList ClientBacklogManager::filterNewBufferIds(const BufferIdList &bufferIds) { - BufferIdList newBuffers; - QSet availableBuffers = Client::networkModel()->allBufferIds().toSet(); - foreach(BufferId bufferId, bufferIds) { - if(_buffersRequested.contains(bufferId) || !availableBuffers.contains(bufferId)) - continue; - newBuffers << bufferId; - } - return newBuffers; + +BufferIdList ClientBacklogManager::filterNewBufferIds(const BufferIdList &bufferIds) +{ + BufferIdList newBuffers; + QSet availableBuffers = Client::networkModel()->allBufferIds().toSet(); + foreach(BufferId bufferId, bufferIds) { + if (_buffersRequested.contains(bufferId) || !availableBuffers.contains(bufferId)) + continue; + newBuffers << bufferId; + } + return newBuffers; } -void ClientBacklogManager::checkForBacklog(const QList &bufferIds) { - // we ingore all backlogrequests until we had our initial request - if(!_initBacklogRequested) { - return; - } - - if(!_requester) { - // during client start up this message is to be expected in some situations. - qDebug() << "ClientBacklogManager::checkForBacklog(): no active backlog requester."; - return; - } - switch(_requester->type()) { - case BacklogRequester::GlobalUnread: - break; - case BacklogRequester::PerBufferUnread: - case BacklogRequester::PerBufferFixed: - default: + +void ClientBacklogManager::checkForBacklog(const QList &bufferIds) +{ + // we ingore all backlogrequests until we had our initial request + if (!_initBacklogRequested) { + return; + } + + if (!_requester) { + // during client start up this message is to be expected in some situations. + qDebug() << "ClientBacklogManager::checkForBacklog(): no active backlog requester."; + return; + } + switch (_requester->type()) { + case BacklogRequester::GlobalUnread: + break; + case BacklogRequester::PerBufferUnread: + case BacklogRequester::PerBufferFixed: + default: { - BufferIdList buffers = filterNewBufferIds(bufferIds); - if(!buffers.isEmpty()) - _requester->requestBacklog(buffers); + BufferIdList buffers = filterNewBufferIds(bufferIds); + if (!buffers.isEmpty()) + _requester->requestBacklog(buffers); } - }; + }; } -bool ClientBacklogManager::isBuffering() { - return _requester && _requester->isBuffering(); + +bool ClientBacklogManager::isBuffering() +{ + return _requester && _requester->isBuffering(); } -void ClientBacklogManager::dispatchMessages(const MessageList &messages, bool sort) { - if(messages.isEmpty()) - return; - MessageList msgs = messages; +void ClientBacklogManager::dispatchMessages(const MessageList &messages, bool sort) +{ + if (messages.isEmpty()) + return; - clock_t start_t = clock(); - if(sort) - qSort(msgs); - Client::messageProcessor()->process(msgs); - clock_t end_t = clock(); + MessageList msgs = messages; - emit messagesProcessed(tr("Processed %1 messages in %2 seconds.").arg(messages.count()).arg((float)(end_t - start_t) / CLOCKS_PER_SEC)); + clock_t start_t = clock(); + if (sort) + qSort(msgs); + Client::messageProcessor()->process(msgs); + clock_t end_t = clock(); + + emit messagesProcessed(tr("Processed %1 messages in %2 seconds.").arg(messages.count()).arg((float)(end_t - start_t) / CLOCKS_PER_SEC)); } -void ClientBacklogManager::reset() { - delete _requester; - _requester = 0; - _initBacklogRequested = false; - _buffersRequested.clear(); + +void ClientBacklogManager::reset() +{ + delete _requester; + _requester = 0; + _initBacklogRequested = false; + _buffersRequested.clear(); } diff --git a/src/client/clientbacklogmanager.h b/src/client/clientbacklogmanager.h index f4a7b905..181017b8 100644 --- a/src/client/clientbacklogmanager.h +++ b/src/client/clientbacklogmanager.h @@ -26,49 +26,53 @@ class BacklogRequester; -class ClientBacklogManager : public BacklogManager { - SYNCABLE_OBJECT - Q_OBJECT +class ClientBacklogManager : public BacklogManager +{ + SYNCABLE_OBJECT + Q_OBJECT public: - ClientBacklogManager(QObject *parent = 0); + ClientBacklogManager(QObject *parent = 0); - // helper for the backlogRequester, as it isn't a QObject and can't emit itself - inline void emitMessagesRequested(const QString &msg) const { emit messagesRequested(msg); } + // helper for the backlogRequester, as it isn't a QObject and can't emit itself + inline void emitMessagesRequested(const QString &msg) const { emit messagesRequested(msg); } - void reset(); + void reset(); public slots: - virtual QVariantList requestBacklog(BufferId bufferId, MsgId first = -1, MsgId last = -1, int limit = -1, int additional = 0); - virtual void receiveBacklog(BufferId bufferId, MsgId first, MsgId last, int limit, int additional, QVariantList msgs); - virtual void receiveBacklogAll(MsgId first, MsgId last, int limit, int additional, QVariantList msgs); + virtual QVariantList requestBacklog(BufferId bufferId, MsgId first = -1, MsgId last = -1, int limit = -1, int additional = 0); + virtual void receiveBacklog(BufferId bufferId, MsgId first, MsgId last, int limit, int additional, QVariantList msgs); + virtual void receiveBacklogAll(MsgId first, MsgId last, int limit, int additional, QVariantList msgs); - void requestInitialBacklog(); + void requestInitialBacklog(); - void checkForBacklog(BufferId bufferId); - void checkForBacklog(const BufferIdList &bufferIds); + void checkForBacklog(BufferId bufferId); + void checkForBacklog(const BufferIdList &bufferIds); signals: - void messagesReceived(BufferId bufferId, int count) const; - void messagesRequested(const QString &) const; - void messagesProcessed(const QString &) const; + void messagesReceived(BufferId bufferId, int count) const; + void messagesRequested(const QString &) const; + void messagesProcessed(const QString &) const; - void updateProgress(int, int); + void updateProgress(int, int); private: - bool isBuffering(); - BufferIdList filterNewBufferIds(const BufferIdList &bufferIds); + bool isBuffering(); + BufferIdList filterNewBufferIds(const BufferIdList &bufferIds); - void dispatchMessages(const MessageList &messages, bool sort = false); + void dispatchMessages(const MessageList &messages, bool sort = false); - BacklogRequester *_requester; - bool _initBacklogRequested; - QSet _buffersRequested; + BacklogRequester *_requester; + bool _initBacklogRequested; + QSet _buffersRequested; }; + // inlines -inline void ClientBacklogManager::checkForBacklog(BufferId bufferId) { - checkForBacklog(BufferIdList() << bufferId); +inline void ClientBacklogManager::checkForBacklog(BufferId bufferId) +{ + checkForBacklog(BufferIdList() << bufferId); } + #endif // CLIENTBACKLOGMANAGER_H diff --git a/src/client/clientbufferviewconfig.cpp b/src/client/clientbufferviewconfig.cpp index 1e7f816c..90771a69 100644 --- a/src/client/clientbufferviewconfig.cpp +++ b/src/client/clientbufferviewconfig.cpp @@ -22,19 +22,21 @@ INIT_SYNCABLE_OBJECT(ClientBufferViewConfig) ClientBufferViewConfig::ClientBufferViewConfig(int bufferViewId, QObject *parent) - : BufferViewConfig(bufferViewId, parent), + : BufferViewConfig(bufferViewId, parent), _locked(false) { - connect(this, SIGNAL(initDone()), this, SLOT(ensureDecoration())); + connect(this, SIGNAL(initDone()), this, SLOT(ensureDecoration())); } + // currently we don't have a possibility to configure disableDecoration // if we have an old config this value can be true which is... bad. // so we upgrade the core stored bufferViewConfig. // This can be removed with the next release -void ClientBufferViewConfig::ensureDecoration() { - if(!disableDecoration()) - return; - setDisableDecoration(false); - requestUpdate(toVariantMap()); +void ClientBufferViewConfig::ensureDecoration() +{ + if (!disableDecoration()) + return; + setDisableDecoration(false); + requestUpdate(toVariantMap()); } diff --git a/src/client/clientbufferviewconfig.h b/src/client/clientbufferviewconfig.h index 5f6c0ed4..faf37831 100644 --- a/src/client/clientbufferviewconfig.h +++ b/src/client/clientbufferviewconfig.h @@ -23,23 +23,25 @@ #include "bufferviewconfig.h" -class ClientBufferViewConfig : public BufferViewConfig { - SYNCABLE_OBJECT - Q_OBJECT +class ClientBufferViewConfig : public BufferViewConfig +{ + SYNCABLE_OBJECT + Q_OBJECT public: - ClientBufferViewConfig(int bufferViewId, QObject *parent = 0); + ClientBufferViewConfig(int bufferViewId, QObject *parent = 0); - inline bool isLocked() { return _locked || sortAlphabetically(); } - inline void setLocked(bool locked) { _locked = locked; } - inline void lock() { setLocked(true); }; - inline void unlock() { setLocked(false); }; + inline bool isLocked() { return _locked || sortAlphabetically(); } + inline void setLocked(bool locked) { _locked = locked; } + inline void lock() { setLocked(true); }; + inline void unlock() { setLocked(false); }; private slots: - void ensureDecoration(); // remove this in next release + void ensureDecoration(); // remove this in next release private: - bool _locked; + bool _locked; }; + #endif //CLIENTBUFFERVIEWCONFIG_H diff --git a/src/client/clientbufferviewmanager.cpp b/src/client/clientbufferviewmanager.cpp index 504604f5..36443c2a 100644 --- a/src/client/clientbufferviewmanager.cpp +++ b/src/client/clientbufferviewmanager.cpp @@ -26,32 +26,40 @@ INIT_SYNCABLE_OBJECT(ClientBufferViewManager) ClientBufferViewManager::ClientBufferViewManager(SignalProxy *proxy, QObject *parent) - : BufferViewManager(proxy, parent) + : BufferViewManager(proxy, parent) { } -BufferViewConfig *ClientBufferViewManager::bufferViewConfigFactory(int bufferViewConfigId) { - return new ClientBufferViewConfig(bufferViewConfigId, this); + +BufferViewConfig *ClientBufferViewManager::bufferViewConfigFactory(int bufferViewConfigId) +{ + return new ClientBufferViewConfig(bufferViewConfigId, this); } -QList ClientBufferViewManager::clientBufferViewConfigs() const { - QList clientConfigs; - foreach(BufferViewConfig *config, bufferViewConfigs()) { - clientConfigs << static_cast(config); - } - return clientConfigs; + +QList ClientBufferViewManager::clientBufferViewConfigs() const +{ + QList clientConfigs; + foreach(BufferViewConfig *config, bufferViewConfigs()) { + clientConfigs << static_cast(config); + } + return clientConfigs; } -ClientBufferViewConfig *ClientBufferViewManager::clientBufferViewConfig(int bufferViewId) const { - return static_cast(bufferViewConfig(bufferViewId)); + +ClientBufferViewConfig *ClientBufferViewManager::clientBufferViewConfig(int bufferViewId) const +{ + return static_cast(bufferViewConfig(bufferViewId)); } -void ClientBufferViewManager::setInitialized() { - if(bufferViewConfigs().isEmpty()) { - BufferViewConfig config(-1); - config.setBufferViewName(tr("All Chats")); - config.initSetBufferList(Client::networkModel()->allBufferIdsSorted()); - requestCreateBufferView(config.toVariantMap()); - } - BufferViewManager::setInitialized(); + +void ClientBufferViewManager::setInitialized() +{ + if (bufferViewConfigs().isEmpty()) { + BufferViewConfig config(-1); + config.setBufferViewName(tr("All Chats")); + config.initSetBufferList(Client::networkModel()->allBufferIdsSorted()); + requestCreateBufferView(config.toVariantMap()); + } + BufferViewManager::setInitialized(); } diff --git a/src/client/clientbufferviewmanager.h b/src/client/clientbufferviewmanager.h index a413a8f6..17a10c8e 100644 --- a/src/client/clientbufferviewmanager.h +++ b/src/client/clientbufferviewmanager.h @@ -26,21 +26,23 @@ class ClientBufferViewConfig; class BufferViewOverlay; -class ClientBufferViewManager : public BufferViewManager { - SYNCABLE_OBJECT - Q_OBJECT +class ClientBufferViewManager : public BufferViewManager +{ + SYNCABLE_OBJECT + Q_OBJECT public: - ClientBufferViewManager(SignalProxy *proxy, QObject *parent = 0); + ClientBufferViewManager(SignalProxy *proxy, QObject *parent = 0); - QList clientBufferViewConfigs() const; - ClientBufferViewConfig *clientBufferViewConfig(int bufferViewId) const; + QList clientBufferViewConfigs() const; + ClientBufferViewConfig *clientBufferViewConfig(int bufferViewId) const; public slots: - virtual void setInitialized(); + virtual void setInitialized(); protected: - virtual BufferViewConfig *bufferViewConfigFactory(int bufferViewConfigId); + virtual BufferViewConfig *bufferViewConfigFactory(int bufferViewConfigId); }; + #endif //CLIENTBUFFERVIEWMANAGER_H diff --git a/src/client/clientcoreinfo.h b/src/client/clientcoreinfo.h index 3bd08a47..e32ba977 100644 --- a/src/client/clientcoreinfo.h +++ b/src/client/clientcoreinfo.h @@ -26,23 +26,25 @@ /* * Yes this name is somewhat stupid... but it fits the general naming scheme * which is prefixing client specific sync objects with "Client"... ;) - */ -class ClientCoreInfo : public CoreInfo { - Q_OBJECT - SYNCABLE_OBJECT + */ +class ClientCoreInfo : public CoreInfo +{ + Q_OBJECT + SYNCABLE_OBJECT public: - ClientCoreInfo(QObject *parent = 0) : CoreInfo(parent) {} + ClientCoreInfo(QObject *parent = 0) : CoreInfo(parent) {} - inline virtual const QMetaObject *syncMetaObject() const { return &CoreInfo::staticMetaObject; } + inline virtual const QMetaObject *syncMetaObject() const { return &CoreInfo::staticMetaObject; } - inline QVariant &operator[](const QString &key) { return _coreData[key]; } + inline QVariant &operator[](const QString &key) { return _coreData[key]; } public slots: - inline virtual void setCoreData(const QVariantMap &data) { _coreData = data; } + inline virtual void setCoreData(const QVariantMap &data) { _coreData = data; } private: - QVariantMap _coreData; + QVariantMap _coreData; }; + #endif //CLIENTCOREINFO_H diff --git a/src/client/clientidentity.cpp b/src/client/clientidentity.cpp index af3541cf..cb34e268 100644 --- a/src/client/clientidentity.cpp +++ b/src/client/clientidentity.cpp @@ -25,27 +25,29 @@ INIT_SYNCABLE_OBJECT(CertIdentity) CertIdentity::CertIdentity(IdentityId id, QObject *parent) - : Identity(id, parent) + : Identity(id, parent) #ifdef HAVE_SSL - , _certManager(0), + , _certManager(0), _isDirty(false) #endif { } + CertIdentity::CertIdentity(const Identity &other, QObject *parent) - : Identity(other, parent) + : Identity(other, parent) #ifdef HAVE_SSL - , _certManager(0), + , _certManager(0), _isDirty(false) #endif { } + CertIdentity::CertIdentity(const CertIdentity &other, QObject *parent) - : Identity(other, parent) + : Identity(other, parent) #ifdef HAVE_SSL - , _certManager(0), + , _certManager(0), _isDirty(other._isDirty), _sslKey(other._sslKey), _sslCert(other._sslCert) @@ -53,57 +55,71 @@ CertIdentity::CertIdentity(const CertIdentity &other, QObject *parent) { } + #ifdef HAVE_SSL -void CertIdentity::enableEditSsl(bool enable) { - if(!enable || _certManager) - return; - - _certManager = new ClientCertManager(id(), this); - if(isValid()) { // this means we are not a newly created Identity but have a proper Id - Client::signalProxy()->synchronize(_certManager); - connect(_certManager, SIGNAL(updated()), this, SLOT(markClean())); - connect(_certManager, SIGNAL(initDone()), this, SLOT(markClean())); - } +void CertIdentity::enableEditSsl(bool enable) +{ + if (!enable || _certManager) + return; + + _certManager = new ClientCertManager(id(), this); + if (isValid()) { // this means we are not a newly created Identity but have a proper Id + Client::signalProxy()->synchronize(_certManager); + connect(_certManager, SIGNAL(updated()), this, SLOT(markClean())); + connect(_certManager, SIGNAL(initDone()), this, SLOT(markClean())); + } } -void CertIdentity::setSslKey(const QSslKey &key) { - if(key.toPem() == _sslKey.toPem()) - return; - _sslKey = key; - _isDirty = true; + +void CertIdentity::setSslKey(const QSslKey &key) +{ + if (key.toPem() == _sslKey.toPem()) + return; + _sslKey = key; + _isDirty = true; } -void CertIdentity::setSslCert(const QSslCertificate &cert) { - if(cert.toPem() == _sslCert.toPem()) - return; - _sslCert = cert; - _isDirty = true; + +void CertIdentity::setSslCert(const QSslCertificate &cert) +{ + if (cert.toPem() == _sslCert.toPem()) + return; + _sslCert = cert; + _isDirty = true; } -void CertIdentity::requestUpdateSslSettings() { - if(!_certManager) - return; - _certManager->requestUpdate(_certManager->toVariantMap()); +void CertIdentity::requestUpdateSslSettings() +{ + if (!_certManager) + return; + + _certManager->requestUpdate(_certManager->toVariantMap()); } -void CertIdentity::markClean() { - _isDirty = false; - emit sslSettingsUpdated(); + +void CertIdentity::markClean() +{ + _isDirty = false; + emit sslSettingsUpdated(); } + // ======================================== // ClientCertManager // ======================================== -void ClientCertManager::setSslKey(const QByteArray &encoded) { - QSslKey key(encoded, QSsl::Rsa); - if(key.isNull()) - key = QSslKey(encoded, QSsl::Dsa); - _certIdentity->setSslKey(key); +void ClientCertManager::setSslKey(const QByteArray &encoded) +{ + QSslKey key(encoded, QSsl::Rsa); + if (key.isNull()) + key = QSslKey(encoded, QSsl::Dsa); + _certIdentity->setSslKey(key); } -void ClientCertManager::setSslCert(const QByteArray &encoded) { - _certIdentity->setSslCert(QSslCertificate(encoded)); + +void ClientCertManager::setSslCert(const QByteArray &encoded) +{ + _certIdentity->setSslCert(QSslCertificate(encoded)); } diff --git a/src/client/clientidentity.h b/src/client/clientidentity.h index 730b6628..5ccaf92f 100644 --- a/src/client/clientidentity.h +++ b/src/client/clientidentity.h @@ -25,66 +25,71 @@ class ClientCertManager; -class CertIdentity : public Identity { - SYNCABLE_OBJECT - Q_OBJECT +class CertIdentity : public Identity +{ + SYNCABLE_OBJECT + Q_OBJECT public: - CertIdentity(IdentityId id = 0, QObject *parent = 0); - CertIdentity(const Identity &other, QObject *parent = 0); - CertIdentity(const CertIdentity &other, QObject *parent = 0); + CertIdentity(IdentityId id = 0, QObject *parent = 0); + CertIdentity(const Identity &other, QObject *parent = 0); + CertIdentity(const CertIdentity &other, QObject *parent = 0); #ifdef HAVE_SSL - inline bool isDirty() const { return _isDirty; } + inline bool isDirty() const { return _isDirty; } #else - inline bool isDirty() const { return false; } + inline bool isDirty() const { return false; } #endif #ifdef HAVE_SSL - void enableEditSsl(bool enable = true); - inline const QSslKey &sslKey() const { return _sslKey; } - inline const QSslCertificate &sslCert() const { return _sslCert; } + void enableEditSsl(bool enable = true); + inline const QSslKey &sslKey() const { return _sslKey; } + inline const QSslCertificate &sslCert() const { return _sslCert; } - void setSslKey(const QSslKey &key); - void setSslCert(const QSslCertificate &cert); + void setSslKey(const QSslKey &key); + void setSslCert(const QSslCertificate &cert); public slots: - void requestUpdateSslSettings(); + void requestUpdateSslSettings(); signals: - void sslSettingsUpdated(); + void sslSettingsUpdated(); private slots: - void markClean(); + void markClean(); private: - ClientCertManager *_certManager; - bool _isDirty; - QSslKey _sslKey; - QSslCertificate _sslCert; + ClientCertManager *_certManager; + bool _isDirty; + QSslKey _sslKey; + QSslCertificate _sslCert; #endif //HAVE_SSL }; + // ======================================== // ClientCertManager // ======================================== #ifdef HAVE_SSL -class ClientCertManager : public CertManager { - Q_OBJECT +class ClientCertManager : public CertManager +{ + Q_OBJECT public: - ClientCertManager(IdentityId id, CertIdentity *parent) : CertManager(id, parent), _certIdentity(parent) {} + ClientCertManager(IdentityId id, CertIdentity *parent) : CertManager(id, parent), _certIdentity(parent) {} - virtual inline const QSslKey &sslKey() const { return _certIdentity->sslKey(); } - virtual inline const QSslCertificate &sslCert() const { return _certIdentity->sslCert(); } + virtual inline const QSslKey &sslKey() const { return _certIdentity->sslKey(); } + virtual inline const QSslCertificate &sslCert() const { return _certIdentity->sslCert(); } public slots: - virtual void setSslKey(const QByteArray &encoded); - virtual void setSslCert(const QByteArray &encoded); + virtual void setSslKey(const QByteArray &encoded); + virtual void setSslCert(const QByteArray &encoded); private: - CertIdentity *_certIdentity; + CertIdentity *_certIdentity; }; + + #endif //HAVE_SSL #endif //CLIENTIDENTITY_H diff --git a/src/client/clientignorelistmanager.cpp b/src/client/clientignorelistmanager.cpp index f146313f..8e912292 100644 --- a/src/client/clientignorelistmanager.cpp +++ b/src/client/clientignorelistmanager.cpp @@ -27,31 +27,34 @@ INIT_SYNCABLE_OBJECT(ClientIgnoreListManager) ClientIgnoreListManager::ClientIgnoreListManager(QObject *parent) : IgnoreListManager(parent) { - connect(this, SIGNAL(updatedRemotely()), SIGNAL(ignoreListChanged())); + connect(this, SIGNAL(updatedRemotely()), SIGNAL(ignoreListChanged())); } -bool ClientIgnoreListManager::pureMatch(const IgnoreListItem &item, const QString &string) const { - QRegExp ruleRx = QRegExp(item.ignoreRule); - ruleRx.setCaseSensitivity(Qt::CaseInsensitive); - if(!item.isRegEx) - ruleRx.setPatternSyntax(QRegExp::Wildcard); - if((!item.isRegEx && ruleRx.exactMatch(string)) || - (item.isRegEx && ruleRx.indexIn(string) != -1)) - return true; - return false; +bool ClientIgnoreListManager::pureMatch(const IgnoreListItem &item, const QString &string) const +{ + QRegExp ruleRx = QRegExp(item.ignoreRule); + ruleRx.setCaseSensitivity(Qt::CaseInsensitive); + if (!item.isRegEx) + ruleRx.setPatternSyntax(QRegExp::Wildcard); + + if ((!item.isRegEx && ruleRx.exactMatch(string)) || + (item.isRegEx && ruleRx.indexIn(string) != -1)) + return true; + return false; } -QMap ClientIgnoreListManager::matchingRulesForHostmask(const QString &hostmask, const QString &network, const QString &channel) const { - QMap result; - foreach(IgnoreListItem item, ignoreList()) { - if(item.type == SenderIgnore && pureMatch(item, hostmask) - && ((network.isEmpty() && channel.isEmpty()) || item.scope == GlobalScope || (item.scope == NetworkScope && scopeMatch(item.scopeRule, network)) - || (item.scope == ChannelScope && scopeMatch(item.scopeRule, channel)))) { - result[item.ignoreRule] = item.isActive; + +QMap ClientIgnoreListManager::matchingRulesForHostmask(const QString &hostmask, const QString &network, const QString &channel) const +{ + QMap result; + foreach(IgnoreListItem item, ignoreList()) { + if (item.type == SenderIgnore && pureMatch(item, hostmask) + && ((network.isEmpty() && channel.isEmpty()) || item.scope == GlobalScope || (item.scope == NetworkScope && scopeMatch(item.scopeRule, network)) + || (item.scope == ChannelScope && scopeMatch(item.scopeRule, channel)))) { + result[item.ignoreRule] = item.isActive; // qDebug() << "matchingRulesForHostmask found: " << item.ignoreRule << "is active: " << item.isActive; + } } - - } - return result; + return result; } diff --git a/src/client/clientignorelistmanager.h b/src/client/clientignorelistmanager.h index 51f02030..9692b835 100644 --- a/src/client/clientignorelistmanager.h +++ b/src/client/clientignorelistmanager.h @@ -26,27 +26,28 @@ class ClientIgnoreListManager : public IgnoreListManager { - SYNCABLE_OBJECT - Q_OBJECT + SYNCABLE_OBJECT + Q_OBJECT public: - explicit ClientIgnoreListManager(QObject *parent = 0); - inline virtual const QMetaObject *syncMetaObject() const { return &IgnoreListManager::staticMetaObject; } + explicit ClientIgnoreListManager(QObject *parent = 0); + inline virtual const QMetaObject *syncMetaObject() const { return &IgnoreListManager::staticMetaObject; } - //! Fetch all matching ignore rules for a given hostmask - /** \param hostmask The hostmask of the user - * \param network The network name - * \param channel The channel name - * \return Returns a QMap with the rule as key and a bool, representing if the rule is enabled or not, as value - */ - QMap matchingRulesForHostmask(const QString &hostmask, const QString &network, const QString &channel) const; + //! Fetch all matching ignore rules for a given hostmask + /** \param hostmask The hostmask of the user + * \param network The network name + * \param channel The channel name + * \return Returns a QMap with the rule as key and a bool, representing if the rule is enabled or not, as value + */ + QMap matchingRulesForHostmask(const QString &hostmask, const QString &network, const QString &channel) const; signals: - void ignoreListChanged(); + void ignoreListChanged(); private: - // matches an ignore rule against a given string - bool pureMatch(const IgnoreListItem &item, const QString &string) const; + // matches an ignore rule against a given string + bool pureMatch(const IgnoreListItem &item, const QString &string) const; }; + #endif // CLIENTIGNORELISTMANAGER_H diff --git a/src/client/clientirclisthelper.cpp b/src/client/clientirclisthelper.cpp index fd52b9ae..2426e8e7 100644 --- a/src/client/clientirclisthelper.cpp +++ b/src/client/clientirclisthelper.cpp @@ -26,30 +26,34 @@ #include "irclistmodel.h" INIT_SYNCABLE_OBJECT(ClientIrcListHelper) -QVariantList ClientIrcListHelper::requestChannelList(const NetworkId &netId, const QStringList &channelFilters) { - _netId = netId; - return IrcListHelper::requestChannelList(netId, channelFilters); +QVariantList ClientIrcListHelper::requestChannelList(const NetworkId &netId, const QStringList &channelFilters) +{ + _netId = netId; + return IrcListHelper::requestChannelList(netId, channelFilters); } -void ClientIrcListHelper::receiveChannelList(const NetworkId &netId, const QStringList &channelFilters, const QVariantList &channels) { - QVariantList::const_iterator iter = channels.constBegin(); - QVariantList::const_iterator iterEnd = channels.constEnd(); - QList channelList; - while(iter != iterEnd) { - QVariantList channelVar = iter->toList(); - ChannelDescription channelDescription(channelVar[0].toString(), channelVar[1].toUInt(), channelVar[2].toString()); - channelList << channelDescription; - iter++; - } +void ClientIrcListHelper::receiveChannelList(const NetworkId &netId, const QStringList &channelFilters, const QVariantList &channels) +{ + QVariantList::const_iterator iter = channels.constBegin(); + QVariantList::const_iterator iterEnd = channels.constEnd(); - emit channelListReceived(netId, channelFilters, channelList); -} + QList channelList; + while (iter != iterEnd) { + QVariantList channelVar = iter->toList(); + ChannelDescription channelDescription(channelVar[0].toString(), channelVar[1].toUInt(), channelVar[2].toString()); + channelList << channelDescription; + iter++; + } -void ClientIrcListHelper::reportFinishedList(const NetworkId &netId) { - if(_netId == netId) { - requestChannelList(netId, QStringList()); - emit finishedListReported(netId); - } + emit channelListReceived(netId, channelFilters, channelList); } + +void ClientIrcListHelper::reportFinishedList(const NetworkId &netId) +{ + if (_netId == netId) { + requestChannelList(netId, QStringList()); + emit finishedListReported(netId); + } +} diff --git a/src/client/clientirclisthelper.h b/src/client/clientirclisthelper.h index 3cc5b7bf..47592c0d 100644 --- a/src/client/clientirclisthelper.h +++ b/src/client/clientirclisthelper.h @@ -23,28 +23,30 @@ #include "irclisthelper.h" -class ClientIrcListHelper : public IrcListHelper { - SYNCABLE_OBJECT - Q_OBJECT +class ClientIrcListHelper : public IrcListHelper +{ + SYNCABLE_OBJECT + Q_OBJECT public: - inline ClientIrcListHelper(QObject *object = 0) : IrcListHelper(object) {}; + inline ClientIrcListHelper(QObject *object = 0) : IrcListHelper(object) {}; - inline virtual const QMetaObject *syncMetaObject() const { return &IrcListHelper::staticMetaObject; } + inline virtual const QMetaObject *syncMetaObject() const { return &IrcListHelper::staticMetaObject; } public slots: - virtual QVariantList requestChannelList(const NetworkId &netId, const QStringList &channelFilters); - virtual void receiveChannelList(const NetworkId &netId, const QStringList &channelFilters, const QVariantList &channels); - virtual void reportFinishedList(const NetworkId &netId); - inline virtual void reportError(const QString &error) { emit errorReported(error); } + virtual QVariantList requestChannelList(const NetworkId &netId, const QStringList &channelFilters); + virtual void receiveChannelList(const NetworkId &netId, const QStringList &channelFilters, const QVariantList &channels); + virtual void reportFinishedList(const NetworkId &netId); + inline virtual void reportError(const QString &error) { emit errorReported(error); } signals: - void channelListReceived(const NetworkId &netId, const QStringList &channelFilters, const QList &channelList); - void finishedListReported(const NetworkId &netId); - void errorReported(const QString &error); + void channelListReceived(const NetworkId &netId, const QStringList &channelFilters, const QList &channelList); + void finishedListReported(const NetworkId &netId); + void errorReported(const QString &error); private: - NetworkId _netId; + NetworkId _netId; }; + #endif //CLIENTIRCLISTHELPER_H diff --git a/src/client/clientsettings.cpp b/src/client/clientsettings.cpp index 045c8e43..72fe3697 100644 --- a/src/client/clientsettings.cpp +++ b/src/client/clientsettings.cpp @@ -20,7 +20,6 @@ #include - #include "clientsettings.h" #include @@ -28,302 +27,402 @@ #include #endif - #include "client.h" #include "quassel.h" -ClientSettings::ClientSettings(QString g) : Settings(g, Quassel::buildInfo().clientApplicationName) { +ClientSettings::ClientSettings(QString g) : Settings(g, Quassel::buildInfo().clientApplicationName) +{ } -ClientSettings::~ClientSettings() { + +ClientSettings::~ClientSettings() +{ } + /***********************************************************************************************/ CoreAccountSettings::CoreAccountSettings(const QString &subgroup) - : ClientSettings("CoreAccounts"), + : ClientSettings("CoreAccounts"), _subgroup(subgroup) { } -void CoreAccountSettings::notify(const QString &key, QObject *receiver, const char *slot) { - ClientSettings::notify(QString("%1/%2/%3").arg(Client::currentCoreAccount().accountId().toInt()).arg(_subgroup).arg(key), receiver, slot); -} -QList CoreAccountSettings::knownAccounts() { - QList ids; - foreach(const QString &key, localChildGroups()) { - AccountId acc = key.toInt(); - if(acc.isValid()) - ids << acc; - } - return ids; +void CoreAccountSettings::notify(const QString &key, QObject *receiver, const char *slot) +{ + ClientSettings::notify(QString("%1/%2/%3").arg(Client::currentCoreAccount().accountId().toInt()).arg(_subgroup).arg(key), receiver, slot); } -AccountId CoreAccountSettings::lastAccount() { - return localValue("LastAccount", 0).toInt(); -} -void CoreAccountSettings::setLastAccount(AccountId account) { - setLocalValue("LastAccount", account.toInt()); +QList CoreAccountSettings::knownAccounts() +{ + QList ids; + foreach(const QString &key, localChildGroups()) { + AccountId acc = key.toInt(); + if (acc.isValid()) + ids << acc; + } + return ids; } -AccountId CoreAccountSettings::autoConnectAccount() { - return localValue("AutoConnectAccount", 0).toInt(); + +AccountId CoreAccountSettings::lastAccount() +{ + return localValue("LastAccount", 0).toInt(); } -void CoreAccountSettings::setAutoConnectAccount(AccountId account) { - setLocalValue("AutoConnectAccount", account.toInt()); + +void CoreAccountSettings::setLastAccount(AccountId account) +{ + setLocalValue("LastAccount", account.toInt()); } -bool CoreAccountSettings::autoConnectOnStartup() { - return localValue("AutoConnectOnStartup", false).toBool(); + +AccountId CoreAccountSettings::autoConnectAccount() +{ + return localValue("AutoConnectAccount", 0).toInt(); } -void CoreAccountSettings::setAutoConnectOnStartup(bool b) { - setLocalValue("AutoConnectOnStartup", b); + +void CoreAccountSettings::setAutoConnectAccount(AccountId account) +{ + setLocalValue("AutoConnectAccount", account.toInt()); } -bool CoreAccountSettings::autoConnectToFixedAccount() { - return localValue("AutoConnectToFixedAccount", false).toBool(); + +bool CoreAccountSettings::autoConnectOnStartup() +{ + return localValue("AutoConnectOnStartup", false).toBool(); } -void CoreAccountSettings::setAutoConnectToFixedAccount(bool b) { - setLocalValue("AutoConnectToFixedAccount", b); + +void CoreAccountSettings::setAutoConnectOnStartup(bool b) +{ + setLocalValue("AutoConnectOnStartup", b); } -void CoreAccountSettings::storeAccountData(AccountId id, const QVariantMap &data) { - QString base = QString::number(id.toInt()); - foreach(const QString &key, data.keys()) { - setLocalValue(base + "/" + key, data.value(key)); - } - // FIXME Migration from 0.5 -> 0.6 - removeLocalKey(QString("%1/Connection").arg(base)); +bool CoreAccountSettings::autoConnectToFixedAccount() +{ + return localValue("AutoConnectToFixedAccount", false).toBool(); } -QVariantMap CoreAccountSettings::retrieveAccountData(AccountId id) { - QVariantMap map; - QString base = QString::number(id.toInt()); - foreach(const QString &key, localChildKeys(base)) { - map[key] = localValue(base + "/" + key); - } - // FIXME Migration from 0.5 -> 0.6 - if(!map.contains("Uuid") && map.contains("Connection")) { - QVariantMap oldmap = map.value("Connection").toMap(); - map["AccountName"] = oldmap.value("AccountName"); - map["HostName"] = oldmap.value("Host"); - map["Port"] = oldmap.value("Port"); - map["User"] = oldmap.value("User"); - map["Password"] = oldmap.value("Password"); - map["StorePassword"] = oldmap.value("RememberPasswd"); - map["UseSSL"] = oldmap.value("useSsl"); - map["UseProxy"] = oldmap.value("useProxy"); - map["ProxyHostName"] = oldmap.value("proxyHost"); - map["ProxyPort"] = oldmap.value("proxyPort"); - map["ProxyUser"] = oldmap.value("proxyUser"); - map["ProxyPassword"] = oldmap.value("proxyPassword"); - map["ProxyType"] = oldmap.value("proxyType"); - map["Internal"] = oldmap.value("InternalAccount"); +void CoreAccountSettings::setAutoConnectToFixedAccount(bool b) +{ + setLocalValue("AutoConnectToFixedAccount", b); +} + - map["AccountId"] = id.toInt(); - map["Uuid"] = QUuid::createUuid().toString(); - } +void CoreAccountSettings::storeAccountData(AccountId id, const QVariantMap &data) +{ + QString base = QString::number(id.toInt()); + foreach(const QString &key, data.keys()) { + setLocalValue(base + "/" + key, data.value(key)); + } - return map; + // FIXME Migration from 0.5 -> 0.6 + removeLocalKey(QString("%1/Connection").arg(base)); } -void CoreAccountSettings::setAccountValue(const QString &key, const QVariant &value) { - if(!Client::currentCoreAccount().isValid()) - return; - setLocalValue(QString("%1/%2/%3").arg(Client::currentCoreAccount().accountId().toInt()).arg(_subgroup).arg(key), value); + +QVariantMap CoreAccountSettings::retrieveAccountData(AccountId id) +{ + QVariantMap map; + QString base = QString::number(id.toInt()); + foreach(const QString &key, localChildKeys(base)) { + map[key] = localValue(base + "/" + key); + } + + // FIXME Migration from 0.5 -> 0.6 + if (!map.contains("Uuid") && map.contains("Connection")) { + QVariantMap oldmap = map.value("Connection").toMap(); + map["AccountName"] = oldmap.value("AccountName"); + map["HostName"] = oldmap.value("Host"); + map["Port"] = oldmap.value("Port"); + map["User"] = oldmap.value("User"); + map["Password"] = oldmap.value("Password"); + map["StorePassword"] = oldmap.value("RememberPasswd"); + map["UseSSL"] = oldmap.value("useSsl"); + map["UseProxy"] = oldmap.value("useProxy"); + map["ProxyHostName"] = oldmap.value("proxyHost"); + map["ProxyPort"] = oldmap.value("proxyPort"); + map["ProxyUser"] = oldmap.value("proxyUser"); + map["ProxyPassword"] = oldmap.value("proxyPassword"); + map["ProxyType"] = oldmap.value("proxyType"); + map["Internal"] = oldmap.value("InternalAccount"); + + map["AccountId"] = id.toInt(); + map["Uuid"] = QUuid::createUuid().toString(); + } + + return map; +} + + +void CoreAccountSettings::setAccountValue(const QString &key, const QVariant &value) +{ + if (!Client::currentCoreAccount().isValid()) + return; + setLocalValue(QString("%1/%2/%3").arg(Client::currentCoreAccount().accountId().toInt()).arg(_subgroup).arg(key), value); } -QVariant CoreAccountSettings::accountValue(const QString &key, const QVariant &def) { - if(!Client::currentCoreAccount().isValid()) - return QVariant(); - return localValue(QString("%1/%2/%3").arg(Client::currentCoreAccount().accountId().toInt()).arg(_subgroup).arg(key), def); + +QVariant CoreAccountSettings::accountValue(const QString &key, const QVariant &def) +{ + if (!Client::currentCoreAccount().isValid()) + return QVariant(); + return localValue(QString("%1/%2/%3").arg(Client::currentCoreAccount().accountId().toInt()).arg(_subgroup).arg(key), def); } -void CoreAccountSettings::setJumpKeyMap(const QHash &keyMap) { - QVariantMap variants; - QHash::const_iterator mapIter = keyMap.constBegin(); - while(mapIter != keyMap.constEnd()) { - variants[QString::number(mapIter.key())] = qVariantFromValue(mapIter.value()); - ++mapIter; - } - setAccountValue("JumpKeyMap", variants); + +void CoreAccountSettings::setJumpKeyMap(const QHash &keyMap) +{ + QVariantMap variants; + QHash::const_iterator mapIter = keyMap.constBegin(); + while (mapIter != keyMap.constEnd()) { + variants[QString::number(mapIter.key())] = qVariantFromValue(mapIter.value()); + ++mapIter; + } + setAccountValue("JumpKeyMap", variants); } -QHash CoreAccountSettings::jumpKeyMap() { - QHash keyMap; - QVariantMap variants = accountValue("JumpKeyMap", QVariant()).toMap(); - QVariantMap::const_iterator mapIter = variants.constBegin(); - while(mapIter != variants.constEnd()) { - keyMap[mapIter.key().toInt()] = mapIter.value().value(); - ++mapIter; - } - return keyMap; + +QHash CoreAccountSettings::jumpKeyMap() +{ + QHash keyMap; + QVariantMap variants = accountValue("JumpKeyMap", QVariant()).toMap(); + QVariantMap::const_iterator mapIter = variants.constBegin(); + while (mapIter != variants.constEnd()) { + keyMap[mapIter.key().toInt()] = mapIter.value().value(); + ++mapIter; + } + return keyMap; } -void CoreAccountSettings::setBufferViewOverlay(const QSet &viewIds) { - QVariantList variants; - foreach(int viewId, viewIds) { - variants << qVariantFromValue(viewId); - } - setAccountValue("BufferViewOverlay", variants); + +void CoreAccountSettings::setBufferViewOverlay(const QSet &viewIds) +{ + QVariantList variants; + foreach(int viewId, viewIds) { + variants << qVariantFromValue(viewId); + } + setAccountValue("BufferViewOverlay", variants); } -QSet CoreAccountSettings::bufferViewOverlay() { - QSet viewIds; - QVariantList variants = accountValue("BufferViewOverlay").toList(); - for(QVariantList::const_iterator iter = variants.constBegin(); iter != variants.constEnd(); iter++) { - viewIds << iter->toInt(); - } - return viewIds; + +QSet CoreAccountSettings::bufferViewOverlay() +{ + QSet viewIds; + QVariantList variants = accountValue("BufferViewOverlay").toList(); + for (QVariantList::const_iterator iter = variants.constBegin(); iter != variants.constEnd(); iter++) { + viewIds << iter->toInt(); + } + return viewIds; } -void CoreAccountSettings::removeAccount(AccountId id) { - removeLocalKey(QString("%1").arg(id.toInt())); + +void CoreAccountSettings::removeAccount(AccountId id) +{ + removeLocalKey(QString("%1").arg(id.toInt())); } -void CoreAccountSettings::clearAccounts() { - foreach(const QString &key, localChildGroups()) + +void CoreAccountSettings::clearAccounts() +{ + foreach(const QString &key, localChildGroups()) removeLocalKey(key); } + /***********************************************************************************************/ // CoreConnectionSettings: CoreConnectionSettings::CoreConnectionSettings() : ClientSettings("CoreConnection") {} -void CoreConnectionSettings::setNetworkDetectionMode(NetworkDetectionMode mode) { - setLocalValue("NetworkDetectionMode", mode); +void CoreConnectionSettings::setNetworkDetectionMode(NetworkDetectionMode mode) +{ + setLocalValue("NetworkDetectionMode", mode); } -CoreConnectionSettings::NetworkDetectionMode CoreConnectionSettings::networkDetectionMode() { + +CoreConnectionSettings::NetworkDetectionMode CoreConnectionSettings::networkDetectionMode() +{ #ifdef HAVE_KDE - NetworkDetectionMode def = UseSolid; + NetworkDetectionMode def = UseSolid; #else - NetworkDetectionMode def = UsePingTimeout; + NetworkDetectionMode def = UsePingTimeout; #endif - return (NetworkDetectionMode)localValue("NetworkDetectionMode", def).toInt(); + return (NetworkDetectionMode)localValue("NetworkDetectionMode", def).toInt(); } -void CoreConnectionSettings::setAutoReconnect(bool autoReconnect) { - setLocalValue("AutoReconnect", autoReconnect); + +void CoreConnectionSettings::setAutoReconnect(bool autoReconnect) +{ + setLocalValue("AutoReconnect", autoReconnect); } -bool CoreConnectionSettings::autoReconnect() { - return localValue("AutoReconnect", true).toBool(); + +bool CoreConnectionSettings::autoReconnect() +{ + return localValue("AutoReconnect", true).toBool(); } -void CoreConnectionSettings::setPingTimeoutInterval(int interval) { - setLocalValue("PingTimeoutInterval", interval); + +void CoreConnectionSettings::setPingTimeoutInterval(int interval) +{ + setLocalValue("PingTimeoutInterval", interval); } -int CoreConnectionSettings::pingTimeoutInterval() { - return localValue("PingTimeoutInterval", 60).toInt(); + +int CoreConnectionSettings::pingTimeoutInterval() +{ + return localValue("PingTimeoutInterval", 60).toInt(); } -void CoreConnectionSettings::setReconnectInterval(int interval) { - setLocalValue("ReconnectInterval", interval); + +void CoreConnectionSettings::setReconnectInterval(int interval) +{ + setLocalValue("ReconnectInterval", interval); } -int CoreConnectionSettings::reconnectInterval() { - return localValue("ReconnectInterval", 60).toInt(); + +int CoreConnectionSettings::reconnectInterval() +{ + return localValue("ReconnectInterval", 60).toInt(); } + /***********************************************************************************************/ // NotificationSettings: -NotificationSettings::NotificationSettings() : ClientSettings("Notification") { +NotificationSettings::NotificationSettings() : ClientSettings("Notification") +{ } -void NotificationSettings::setHighlightList(const QVariantList &highlightList) { - setLocalValue("Highlights/CustomList", highlightList); + +void NotificationSettings::setHighlightList(const QVariantList &highlightList) +{ + setLocalValue("Highlights/CustomList", highlightList); } -QVariantList NotificationSettings::highlightList() { - return localValue("Highlights/CustomList").toList(); + +QVariantList NotificationSettings::highlightList() +{ + return localValue("Highlights/CustomList").toList(); } -void NotificationSettings::setHighlightNick(NotificationSettings::HighlightNickType highlightNickType) { - setLocalValue("Highlights/HighlightNick", highlightNickType); + +void NotificationSettings::setHighlightNick(NotificationSettings::HighlightNickType highlightNickType) +{ + setLocalValue("Highlights/HighlightNick", highlightNickType); } -NotificationSettings::HighlightNickType NotificationSettings::highlightNick() { - return (NotificationSettings::HighlightNickType) localValue("Highlights/HighlightNick", CurrentNick).toInt(); + +NotificationSettings::HighlightNickType NotificationSettings::highlightNick() +{ + return (NotificationSettings::HighlightNickType)localValue("Highlights/HighlightNick", CurrentNick).toInt(); } -void NotificationSettings::setNicksCaseSensitive(bool cs) { - setLocalValue("Highlights/NicksCaseSensitive", cs); + +void NotificationSettings::setNicksCaseSensitive(bool cs) +{ + setLocalValue("Highlights/NicksCaseSensitive", cs); } -bool NotificationSettings::nicksCaseSensitive() { - return localValue("Highlights/NicksCaseSensitive", false).toBool(); + +bool NotificationSettings::nicksCaseSensitive() +{ + return localValue("Highlights/NicksCaseSensitive", false).toBool(); } + // ======================================== // TabCompletionSettings // ======================================== -TabCompletionSettings::TabCompletionSettings() : ClientSettings("TabCompletion") { +TabCompletionSettings::TabCompletionSettings() : ClientSettings("TabCompletion") +{ } -void TabCompletionSettings::setCompletionSuffix(const QString &suffix) { - setLocalValue("CompletionSuffix", suffix); + +void TabCompletionSettings::setCompletionSuffix(const QString &suffix) +{ + setLocalValue("CompletionSuffix", suffix); } -QString TabCompletionSettings::completionSuffix() { - return localValue("CompletionSuffix", ": ").toString(); + +QString TabCompletionSettings::completionSuffix() +{ + return localValue("CompletionSuffix", ": ").toString(); } -void TabCompletionSettings::setAddSpaceMidSentence(bool space) { - setLocalValue("AddSpaceMidSentence", space); + +void TabCompletionSettings::setAddSpaceMidSentence(bool space) +{ + setLocalValue("AddSpaceMidSentence", space); } -bool TabCompletionSettings::addSpaceMidSentence() { - return localValue("AddSpaceMidSentence", false).toBool(); + +bool TabCompletionSettings::addSpaceMidSentence() +{ + return localValue("AddSpaceMidSentence", false).toBool(); } -void TabCompletionSettings::setSortMode(SortMode mode) { - setLocalValue("SortMode", mode); + +void TabCompletionSettings::setSortMode(SortMode mode) +{ + setLocalValue("SortMode", mode); } -TabCompletionSettings::SortMode TabCompletionSettings::sortMode() { - return static_cast(localValue("SortMode"), LastActivity); + +TabCompletionSettings::SortMode TabCompletionSettings::sortMode() +{ + return static_cast(localValue("SortMode"), LastActivity); } -void TabCompletionSettings::setCaseSensitivity(Qt::CaseSensitivity cs) { - setLocalValue("CaseSensitivity", cs); + +void TabCompletionSettings::setCaseSensitivity(Qt::CaseSensitivity cs) +{ + setLocalValue("CaseSensitivity", cs); } -Qt::CaseSensitivity TabCompletionSettings::caseSensitivity() { - return (Qt::CaseSensitivity)localValue("CaseSensitivity", Qt::CaseInsensitive).toInt(); + +Qt::CaseSensitivity TabCompletionSettings::caseSensitivity() +{ + return (Qt::CaseSensitivity)localValue("CaseSensitivity", Qt::CaseInsensitive).toInt(); } -void TabCompletionSettings::setUseLastSpokenTo(bool use) { - setLocalValue("UseLastSpokenTo", use); + +void TabCompletionSettings::setUseLastSpokenTo(bool use) +{ + setLocalValue("UseLastSpokenTo", use); } -bool TabCompletionSettings::useLastSpokenTo() { - return localValue("UseLastSpokenTo", false).toBool(); + +bool TabCompletionSettings::useLastSpokenTo() +{ + return localValue("UseLastSpokenTo", false).toBool(); } + // ======================================== // ItemViewSettings // ======================================== -ItemViewSettings::ItemViewSettings(const QString &group) : ClientSettings(group) { - +ItemViewSettings::ItemViewSettings(const QString &group) : ClientSettings(group) +{ } -bool ItemViewSettings::displayTopicInTooltip() { - return localValue("DisplayTopicInTooltip", false).toBool(); + +bool ItemViewSettings::displayTopicInTooltip() +{ + return localValue("DisplayTopicInTooltip", false).toBool(); } -bool ItemViewSettings::mouseWheelChangesBuffer() { - return localValue("MouseWheelChangesBuffer", false).toBool(); + +bool ItemViewSettings::mouseWheelChangesBuffer() +{ + return localValue("MouseWheelChangesBuffer", false).toBool(); } diff --git a/src/client/clientsettings.h b/src/client/clientsettings.h index 8d873983..b14f009e 100644 --- a/src/client/clientsettings.h +++ b/src/client/clientsettings.h @@ -28,14 +28,16 @@ class QHostAddress; class QSslSocket; -class ClientSettings : public Settings { +class ClientSettings : public Settings +{ public: - virtual ~ClientSettings(); + virtual ~ClientSettings(); protected: - ClientSettings(QString group = "General"); + ClientSettings(QString group = "General"); }; + // ======================================== // CoreAccountSettings // ======================================== @@ -47,135 +49,144 @@ protected: // // Note that you'll get invalid data (and setting is ignored) if you are not connected to a core! -class CoreAccountSettings : public ClientSettings { +class CoreAccountSettings : public ClientSettings +{ public: - // stores account-specific data in CoreAccounts/$ACCID/$SUBGROUP/$KEY) - CoreAccountSettings(const QString &subgroup = "General"); + // stores account-specific data in CoreAccounts/$ACCID/$SUBGROUP/$KEY) + CoreAccountSettings(const QString &subgroup = "General"); - virtual void notify(const QString &key, QObject *receiver, const char *slot); + virtual void notify(const QString &key, QObject *receiver, const char *slot); - QList knownAccounts(); - AccountId lastAccount(); - void setLastAccount(AccountId); - AccountId autoConnectAccount(); - void setAutoConnectAccount(AccountId); - bool autoConnectOnStartup(); - void setAutoConnectOnStartup(bool); - bool autoConnectToFixedAccount(); - void setAutoConnectToFixedAccount(bool); + QList knownAccounts(); + AccountId lastAccount(); + void setLastAccount(AccountId); + AccountId autoConnectAccount(); + void setAutoConnectAccount(AccountId); + bool autoConnectOnStartup(); + void setAutoConnectOnStartup(bool); + bool autoConnectToFixedAccount(); + void setAutoConnectToFixedAccount(bool); - void clearAccounts(); + void clearAccounts(); - void storeAccountData(AccountId id, const QVariantMap &data); - QVariantMap retrieveAccountData(AccountId); - void removeAccount(AccountId); + void storeAccountData(AccountId id, const QVariantMap &data); + QVariantMap retrieveAccountData(AccountId); + void removeAccount(AccountId); - void setJumpKeyMap(const QHash &keyMap); - QHash jumpKeyMap(); + void setJumpKeyMap(const QHash &keyMap); + QHash jumpKeyMap(); - void setBufferViewOverlay(const QSet &viewIds); - QSet bufferViewOverlay(); + void setBufferViewOverlay(const QSet &viewIds); + QSet bufferViewOverlay(); - void setAccountValue(const QString &key, const QVariant &data); - QVariant accountValue(const QString &key, const QVariant &def = QVariant()); + void setAccountValue(const QString &key, const QVariant &data); + QVariant accountValue(const QString &key, const QVariant &def = QVariant()); private: - QString _subgroup; + QString _subgroup; }; + // ======================================== // NotificationSettings // ======================================== -class NotificationSettings : public ClientSettings { +class NotificationSettings : public ClientSettings +{ public: - enum HighlightNickType { - NoNick = 0x00, - CurrentNick= 0x01, - AllNicks = 0x02 - }; + enum HighlightNickType { + NoNick = 0x00, + CurrentNick = 0x01, + AllNicks = 0x02 + }; - NotificationSettings(); + NotificationSettings(); - inline void setValue(const QString &key, const QVariant &data) { setLocalValue(key, data); } - inline QVariant value(const QString &key, const QVariant &def = QVariant()) { return localValue(key, def); } - inline void remove(const QString &key) { removeLocalKey(key); } + inline void setValue(const QString &key, const QVariant &data) { setLocalValue(key, data); } + inline QVariant value(const QString &key, const QVariant &def = QVariant()) { return localValue(key, def); } + inline void remove(const QString &key) { removeLocalKey(key); } - void setHighlightList(const QVariantList &highlightList); - QVariantList highlightList(); + void setHighlightList(const QVariantList &highlightList); + QVariantList highlightList(); - void setHighlightNick(HighlightNickType); - HighlightNickType highlightNick(); + void setHighlightNick(HighlightNickType); + HighlightNickType highlightNick(); - void setNicksCaseSensitive(bool); - bool nicksCaseSensitive(); + void setNicksCaseSensitive(bool); + bool nicksCaseSensitive(); }; + // ======================================== // CoreConnectionSettings // ======================================== -class CoreConnectionSettings : public ClientSettings { +class CoreConnectionSettings : public ClientSettings +{ public: - enum NetworkDetectionMode { - UseSolid, - UsePingTimeout, - NoActiveDetection - }; + enum NetworkDetectionMode { + UseSolid, + UsePingTimeout, + NoActiveDetection + }; - CoreConnectionSettings(); + CoreConnectionSettings(); - void setNetworkDetectionMode(NetworkDetectionMode mode); - NetworkDetectionMode networkDetectionMode(); + void setNetworkDetectionMode(NetworkDetectionMode mode); + NetworkDetectionMode networkDetectionMode(); - void setAutoReconnect(bool autoReconnect); - bool autoReconnect(); + void setAutoReconnect(bool autoReconnect); + bool autoReconnect(); - void setPingTimeoutInterval(int interval); - int pingTimeoutInterval(); + void setPingTimeoutInterval(int interval); + int pingTimeoutInterval(); - void setReconnectInterval(int interval); - int reconnectInterval(); + void setReconnectInterval(int interval); + int reconnectInterval(); }; + // ======================================== // TabCompletionSettings // ======================================== -class TabCompletionSettings : public ClientSettings { +class TabCompletionSettings : public ClientSettings +{ public: - enum SortMode { - Alphabetical, - LastActivity - }; + enum SortMode { + Alphabetical, + LastActivity + }; - TabCompletionSettings(); + TabCompletionSettings(); - void setCompletionSuffix(const QString &); - QString completionSuffix(); + void setCompletionSuffix(const QString &); + QString completionSuffix(); - void setAddSpaceMidSentence(bool); - bool addSpaceMidSentence(); + void setAddSpaceMidSentence(bool); + bool addSpaceMidSentence(); - void setSortMode(SortMode); - SortMode sortMode(); + void setSortMode(SortMode); + SortMode sortMode(); - void setCaseSensitivity(Qt::CaseSensitivity); - Qt::CaseSensitivity caseSensitivity(); - - void setUseLastSpokenTo(bool); - bool useLastSpokenTo(); + void setCaseSensitivity(Qt::CaseSensitivity); + Qt::CaseSensitivity caseSensitivity(); + void setUseLastSpokenTo(bool); + bool useLastSpokenTo(); }; + // ======================================== // ItemViewSettings // ======================================== -class ItemViewSettings : public ClientSettings { - public: - ItemViewSettings(const QString& group = "ItemViews"); +class ItemViewSettings : public ClientSettings +{ +public: + ItemViewSettings(const QString &group = "ItemViews"); bool displayTopicInTooltip(); bool mouseWheelChangesBuffer(); }; + #endif diff --git a/src/client/clientuserinputhandler.cpp b/src/client/clientuserinputhandler.cpp index aa614f2a..97901cb0 100644 --- a/src/client/clientuserinputhandler.cpp +++ b/src/client/clientuserinputhandler.cpp @@ -36,92 +36,106 @@ #include ClientUserInputHandler::ClientUserInputHandler(QObject *parent) -: BasicHandler(parent) + : BasicHandler(parent) { - TabCompletionSettings s; - s.notify("CompletionSuffix", this, SLOT(completionSuffixChanged(QVariant))); - completionSuffixChanged(s.completionSuffix()); + TabCompletionSettings s; + s.notify("CompletionSuffix", this, SLOT(completionSuffixChanged(QVariant))); + completionSuffixChanged(s.completionSuffix()); } -void ClientUserInputHandler::completionSuffixChanged(const QVariant &v) { - QString suffix = v.toString(); - QString letter = "A-Za-z"; - QString special = "\x5b-\x60\x7b-\x7d"; - _nickRx = QRegExp(QString("^([%1%2][%1%2\\d-]*)%3").arg(letter, special, suffix).trimmed()); + +void ClientUserInputHandler::completionSuffixChanged(const QVariant &v) +{ + QString suffix = v.toString(); + QString letter = "A-Za-z"; + QString special = "\x5b-\x60\x7b-\x7d"; + _nickRx = QRegExp(QString("^([%1%2][%1%2\\d-]*)%3").arg(letter, special, suffix).trimmed()); } + // this would be the place for a client-side hook -void ClientUserInputHandler::handleUserInput(const BufferInfo &bufferInfo, const QString &msg) { - if(msg.isEmpty()) - return; - - if(!msg.startsWith('/')) { - if(_nickRx.indexIn(msg) == 0) { - const Network *net = Client::network(bufferInfo.networkId()); - IrcUser *user = net ? net->ircUser(_nickRx.cap(1)) : 0; - if(user) - user->setLastSpokenTo(bufferInfo.bufferId(), QDateTime::currentDateTime().toUTC()); +void ClientUserInputHandler::handleUserInput(const BufferInfo &bufferInfo, const QString &msg) +{ + if (msg.isEmpty()) + return; + + if (!msg.startsWith('/')) { + if (_nickRx.indexIn(msg) == 0) { + const Network *net = Client::network(bufferInfo.networkId()); + IrcUser *user = net ? net->ircUser(_nickRx.cap(1)) : 0; + if (user) + user->setLastSpokenTo(bufferInfo.bufferId(), QDateTime::currentDateTime().toUTC()); + } } - } - AliasManager::CommandList clist = Client::aliasManager()->processInput(bufferInfo, msg); + AliasManager::CommandList clist = Client::aliasManager()->processInput(bufferInfo, msg); - for(int i = 0; i < clist.count(); i++) { - QString cmd = clist.at(i).second.section(' ', 0, 0).remove(0, 1).toUpper(); - QString payload = clist.at(i).second.section(' ', 1); - handle(cmd, Q_ARG(BufferInfo, clist.at(i).first), Q_ARG(QString, payload)); - } + for (int i = 0; i < clist.count(); i++) { + QString cmd = clist.at(i).second.section(' ', 0, 0).remove(0, 1).toUpper(); + QString payload = clist.at(i).second.section(' ', 1); + handle(cmd, Q_ARG(BufferInfo, clist.at(i).first), Q_ARG(QString, payload)); + } } -void ClientUserInputHandler::defaultHandler(const QString &cmd, const BufferInfo &bufferInfo, const QString &text) { - QString command = QString("/%1 %2").arg(cmd, text); - emit sendInput(bufferInfo, command); + +void ClientUserInputHandler::defaultHandler(const QString &cmd, const BufferInfo &bufferInfo, const QString &text) +{ + QString command = QString("/%1 %2").arg(cmd, text); + emit sendInput(bufferInfo, command); } -void ClientUserInputHandler::handleExec(const BufferInfo &bufferInfo, const QString &execString) { - ExecWrapper *exec = new ExecWrapper(this); // gets suicidal when it's done - exec->start(bufferInfo, execString); + +void ClientUserInputHandler::handleExec(const BufferInfo &bufferInfo, const QString &execString) +{ + ExecWrapper *exec = new ExecWrapper(this); // gets suicidal when it's done + exec->start(bufferInfo, execString); } -void ClientUserInputHandler::handleJoin(const BufferInfo &bufferInfo, const QString &text) { - if(text.isEmpty()) { - Client::messageModel()->insertErrorMessage(bufferInfo, tr("/JOIN expects a channel")); - return; - } - switchBuffer(bufferInfo.networkId(), text.section(' ', 0, 0)); - // send to core - defaultHandler("JOIN", bufferInfo, text); + +void ClientUserInputHandler::handleJoin(const BufferInfo &bufferInfo, const QString &text) +{ + if (text.isEmpty()) { + Client::messageModel()->insertErrorMessage(bufferInfo, tr("/JOIN expects a channel")); + return; + } + switchBuffer(bufferInfo.networkId(), text.section(' ', 0, 0)); + // send to core + defaultHandler("JOIN", bufferInfo, text); } -void ClientUserInputHandler::handleQuery(const BufferInfo &bufferInfo, const QString &text) { - if(text.isEmpty()) { - Client::messageModel()->insertErrorMessage(bufferInfo, tr("/QUERY expects at least a nick")); - return; - } - switchBuffer(bufferInfo.networkId(), text.section(' ', 0, 0)); - // send to core - defaultHandler("QUERY", bufferInfo, text); + +void ClientUserInputHandler::handleQuery(const BufferInfo &bufferInfo, const QString &text) +{ + if (text.isEmpty()) { + Client::messageModel()->insertErrorMessage(bufferInfo, tr("/QUERY expects at least a nick")); + return; + } + switchBuffer(bufferInfo.networkId(), text.section(' ', 0, 0)); + // send to core + defaultHandler("QUERY", bufferInfo, text); } -void ClientUserInputHandler::switchBuffer(const NetworkId &networkId, const QString &bufferName) { - BufferId newBufId = Client::networkModel()->bufferId(networkId, bufferName); - if(!newBufId.isValid()) { - Client::bufferModel()->switchToBufferAfterCreation(networkId, bufferName); - } - else { - Client::bufferModel()->switchToBuffer(newBufId); - // unhide the buffer - ClientBufferViewManager *clientBufferViewManager = Client::bufferViewManager(); - QList bufferViewConfigList = clientBufferViewManager->clientBufferViewConfigs(); - foreach (ClientBufferViewConfig *bufferViewConfig, bufferViewConfigList) { - if (bufferViewConfig->temporarilyRemovedBuffers().contains(newBufId)) { - bufferViewConfig->addBuffer(newBufId, bufferViewConfig->bufferList().length()); - //if (bufferViewConfig->sortAlphabetically()) { - // TODO we need to trigger a sort here, but can't reach the model required - // to get a bufferviewfilter, as the bufferviewmanager only managers configs - //BufferViewFilter *filter = qobject_cast(model()); - //} - } + +void ClientUserInputHandler::switchBuffer(const NetworkId &networkId, const QString &bufferName) +{ + BufferId newBufId = Client::networkModel()->bufferId(networkId, bufferName); + if (!newBufId.isValid()) { + Client::bufferModel()->switchToBufferAfterCreation(networkId, bufferName); + } + else { + Client::bufferModel()->switchToBuffer(newBufId); + // unhide the buffer + ClientBufferViewManager *clientBufferViewManager = Client::bufferViewManager(); + QList bufferViewConfigList = clientBufferViewManager->clientBufferViewConfigs(); + foreach(ClientBufferViewConfig *bufferViewConfig, bufferViewConfigList) { + if (bufferViewConfig->temporarilyRemovedBuffers().contains(newBufId)) { + bufferViewConfig->addBuffer(newBufId, bufferViewConfig->bufferList().length()); + //if (bufferViewConfig->sortAlphabetically()) { + // TODO we need to trigger a sort here, but can't reach the model required + // to get a bufferviewfilter, as the bufferviewmanager only managers configs + //BufferViewFilter *filter = qobject_cast(model()); + //} + } + } } - } } diff --git a/src/client/clientuserinputhandler.h b/src/client/clientuserinputhandler.h index e27f26ea..4b7db834 100644 --- a/src/client/clientuserinputhandler.h +++ b/src/client/clientuserinputhandler.h @@ -26,34 +26,36 @@ class BufferInfo; class NetworkId; -class ClientUserInputHandler : public BasicHandler { - Q_OBJECT +class ClientUserInputHandler : public BasicHandler +{ + Q_OBJECT public: - ClientUserInputHandler(QObject *parent = 0); + ClientUserInputHandler(QObject *parent = 0); public slots: - void handleUserInput(const BufferInfo &bufferInfo, const QString &msg); + void handleUserInput(const BufferInfo &bufferInfo, const QString &msg); signals: - void sendInput(const BufferInfo &, const QString &); + void sendInput(const BufferInfo &, const QString &); private slots: - void completionSuffixChanged(const QVariant &); + void completionSuffixChanged(const QVariant &); - void handleExec(const BufferInfo &bufferInfo, const QString &execString); - void handleJoin(const BufferInfo &bufferInfo, const QString &text); - void handleQuery(const BufferInfo &bufferInfo, const QString &text); - void defaultHandler(const QString &cmd, const BufferInfo &bufferInfo, const QString &text); + void handleExec(const BufferInfo &bufferInfo, const QString &execString); + void handleJoin(const BufferInfo &bufferInfo, const QString &text); + void handleQuery(const BufferInfo &bufferInfo, const QString &text); + void defaultHandler(const QString &cmd, const BufferInfo &bufferInfo, const QString &text); private: - QRegExp _nickRx; + QRegExp _nickRx; - //! Helper method for switching to new/existing buffers - /** Immediately switches to the given buffer or schedules a switch for whenever - * the buffer is created - */ - void switchBuffer(const NetworkId &networkId, const QString &bufferName); + //! Helper method for switching to new/existing buffers + /** Immediately switches to the given buffer or schedules a switch for whenever + * the buffer is created + */ + void switchBuffer(const NetworkId &networkId, const QString &bufferName); }; + #endif diff --git a/src/client/coreaccount.cpp b/src/client/coreaccount.cpp index 4fcccedd..50524c49 100644 --- a/src/client/coreaccount.cpp +++ b/src/client/coreaccount.cpp @@ -20,126 +20,165 @@ #include "coreaccount.h" -CoreAccount::CoreAccount(AccountId accountId) { - _accountId = accountId; - _internal = false; - _port = 4242; - _storePassword = false; - _useSsl = true; - _useProxy = false; - _proxyType = QNetworkProxy::Socks5Proxy; - _proxyPort = 8080; +CoreAccount::CoreAccount(AccountId accountId) +{ + _accountId = accountId; + _internal = false; + _port = 4242; + _storePassword = false; + _useSsl = true; + _useProxy = false; + _proxyType = QNetworkProxy::Socks5Proxy; + _proxyPort = 8080; } -void CoreAccount::setAccountId(AccountId id) { - _accountId = id; + +void CoreAccount::setAccountId(AccountId id) +{ + _accountId = id; } -void CoreAccount::setAccountName(const QString &name) { - _accountName = name; + +void CoreAccount::setAccountName(const QString &name) +{ + _accountName = name; } -void CoreAccount::setUuid(const QUuid &uuid) { - _uuid = uuid; + +void CoreAccount::setUuid(const QUuid &uuid) +{ + _uuid = uuid; } -void CoreAccount::setInternal(bool internal) { - _internal = internal; + +void CoreAccount::setInternal(bool internal) +{ + _internal = internal; } -void CoreAccount::setUser(const QString &user) { - _user = user; + +void CoreAccount::setUser(const QString &user) +{ + _user = user; } -void CoreAccount::setPassword(const QString &password) { - _password = password; + +void CoreAccount::setPassword(const QString &password) +{ + _password = password; } -void CoreAccount::setStorePassword(bool store) { - _storePassword = store; + +void CoreAccount::setStorePassword(bool store) +{ + _storePassword = store; } -void CoreAccount::setHostName(const QString &hostname) { - _hostName = hostname; + +void CoreAccount::setHostName(const QString &hostname) +{ + _hostName = hostname; } -void CoreAccount::setPort(uint port) { - _port = port; + +void CoreAccount::setPort(uint port) +{ + _port = port; } -void CoreAccount::setUseSsl(bool useSsl) { - _useSsl = useSsl; + +void CoreAccount::setUseSsl(bool useSsl) +{ + _useSsl = useSsl; } -void CoreAccount::setUseProxy(bool useProxy) { - _useProxy = useProxy; + +void CoreAccount::setUseProxy(bool useProxy) +{ + _useProxy = useProxy; } -void CoreAccount::setProxyType(QNetworkProxy::ProxyType type) { - _proxyType = type; + +void CoreAccount::setProxyType(QNetworkProxy::ProxyType type) +{ + _proxyType = type; } -void CoreAccount::setProxyUser(const QString &proxyUser) { - _proxyUser = proxyUser; + +void CoreAccount::setProxyUser(const QString &proxyUser) +{ + _proxyUser = proxyUser; } -void CoreAccount::setProxyPassword(const QString &proxyPassword) { - _proxyPassword = proxyPassword; + +void CoreAccount::setProxyPassword(const QString &proxyPassword) +{ + _proxyPassword = proxyPassword; } -void CoreAccount::setProxyHostName(const QString &proxyHostName) { - _proxyHostName = proxyHostName; + +void CoreAccount::setProxyHostName(const QString &proxyHostName) +{ + _proxyHostName = proxyHostName; } -void CoreAccount::setProxyPort(uint proxyPort) { - _proxyPort = proxyPort; + +void CoreAccount::setProxyPort(uint proxyPort) +{ + _proxyPort = proxyPort; } -QVariantMap CoreAccount::toVariantMap(bool forcePassword) const { - QVariantMap v; - v["AccountId"] = accountId().toInt(); // can't use AccountId because then comparison fails - v["AccountName"] = accountName(); - v["Uuid"] = uuid().toString(); - v["Internal"] = isInternal(); - v["User"] = user(); - if(_storePassword || forcePassword) - v["Password"] = password(); - else - v["Password"] = QString(); - v["StorePassword"] = storePassword(); - v["HostName"] = hostName(); - v["Port"] = port(); - v["UseSSL"] = useSsl(); - v["UseProxy"] = useProxy(); - v["ProxyType"] = proxyType(); - v["ProxyUser"] = proxyUser(); - v["ProxyPassword"] = proxyPassword(); - v["ProxyHostName"] = proxyHostName(); - v["ProxyPort"] = proxyPort(); - return v; + +QVariantMap CoreAccount::toVariantMap(bool forcePassword) const +{ + QVariantMap v; + v["AccountId"] = accountId().toInt(); // can't use AccountId because then comparison fails + v["AccountName"] = accountName(); + v["Uuid"] = uuid().toString(); + v["Internal"] = isInternal(); + v["User"] = user(); + if (_storePassword || forcePassword) + v["Password"] = password(); + else + v["Password"] = QString(); + v["StorePassword"] = storePassword(); + v["HostName"] = hostName(); + v["Port"] = port(); + v["UseSSL"] = useSsl(); + v["UseProxy"] = useProxy(); + v["ProxyType"] = proxyType(); + v["ProxyUser"] = proxyUser(); + v["ProxyPassword"] = proxyPassword(); + v["ProxyHostName"] = proxyHostName(); + v["ProxyPort"] = proxyPort(); + return v; } -void CoreAccount::fromVariantMap(const QVariantMap &v) { - setAccountId((AccountId)v.value("AccountId").toInt()); - setAccountName(v.value("AccountName").toString()); - setUuid(QUuid(v.value("Uuid").toString())); - setInternal(v.value("Internal").toBool()); - setUser(v.value("User").toString()); - setPassword(v.value("Password").toString()); - setStorePassword(v.value("StorePassword").toBool()); - setHostName(v.value("HostName").toString()); - setPort(v.value("Port").toUInt()); - setUseSsl(v.value("UseSSL").toBool()); - setUseProxy(v.value("UseProxy").toBool()); - setProxyType((QNetworkProxy::ProxyType)v.value("ProxyType").toInt()); - setProxyUser(v.value("ProxyUser").toString()); - setProxyPassword(v.value("ProxyPassword").toString()); - setProxyHostName(v.value("ProxyHostName").toString()); - setProxyPort(v.value("ProxyPort").toUInt()); - _storePassword = !password().isEmpty(); +void CoreAccount::fromVariantMap(const QVariantMap &v) +{ + setAccountId((AccountId)v.value("AccountId").toInt()); + setAccountName(v.value("AccountName").toString()); + setUuid(QUuid(v.value("Uuid").toString())); + setInternal(v.value("Internal").toBool()); + setUser(v.value("User").toString()); + setPassword(v.value("Password").toString()); + setStorePassword(v.value("StorePassword").toBool()); + setHostName(v.value("HostName").toString()); + setPort(v.value("Port").toUInt()); + setUseSsl(v.value("UseSSL").toBool()); + setUseProxy(v.value("UseProxy").toBool()); + setProxyType((QNetworkProxy::ProxyType)v.value("ProxyType").toInt()); + setProxyUser(v.value("ProxyUser").toString()); + setProxyPassword(v.value("ProxyPassword").toString()); + setProxyHostName(v.value("ProxyHostName").toString()); + setProxyPort(v.value("ProxyPort").toUInt()); + + _storePassword = !password().isEmpty(); } -bool CoreAccount::operator==(const CoreAccount &o) const { - return toVariantMap(true) == o.toVariantMap(true); + +bool CoreAccount::operator==(const CoreAccount &o) const +{ + return toVariantMap(true) == o.toVariantMap(true); } diff --git a/src/client/coreaccount.h b/src/client/coreaccount.h index f684743c..5ea6a1ca 100644 --- a/src/client/coreaccount.h +++ b/src/client/coreaccount.h @@ -27,70 +27,72 @@ #include #include "types.h" -class CoreAccount { - Q_DECLARE_TR_FUNCTIONS(CoreAccount) +class CoreAccount +{ + Q_DECLARE_TR_FUNCTIONS(CoreAccount) public: - CoreAccount(AccountId accountId = 0); - virtual ~CoreAccount() {}; - - inline bool isValid() const { return accountId().isValid(); } - inline AccountId accountId() const { return _accountId; } - inline QString accountName() const { return isInternal() ? tr("Internal Core") : _accountName; } - inline QUuid uuid() const { return _uuid; } - inline bool isInternal() const { return _internal; } - - inline QString user() const { return _user; } - inline bool storePassword() const { return _storePassword; } - inline QString hostName() const { return _hostName; } - inline uint port() const { return _port; } - inline bool useSsl() const { return _useSsl; } - - inline bool useProxy() const { return _useProxy; } - inline QNetworkProxy::ProxyType proxyType() const { return _proxyType; } - inline QString proxyUser() const { return _proxyUser; } - inline QString proxyHostName() const { return _proxyHostName; } - inline uint proxyPort() const { return _proxyPort; } - - void setAccountId(AccountId id); - void setAccountName(const QString &accountName); - void setUuid(const QUuid &uuid); - void setInternal(bool); - - void setUser(const QString &user); - void setStorePassword(bool); - void setHostName(const QString &hostname); - void setPort(uint port); - void setUseSsl(bool); - - void setUseProxy(bool); - void setProxyType(QNetworkProxy::ProxyType); - void setProxyUser(const QString &); - void setProxyHostName(const QString &); - void setProxyPort(uint); - - /* These might be overridden for KWallet support */ - virtual inline QString password() const { return _password; } - virtual void setPassword(const QString &password); - virtual inline QString proxyPassword() const { return _proxyPassword; } - virtual void setProxyPassword(const QString &); - - virtual QVariantMap toVariantMap(bool forcePassword = false) const; - virtual void fromVariantMap(const QVariantMap &); - - bool operator==(const CoreAccount &other) const; + CoreAccount(AccountId accountId = 0); + virtual ~CoreAccount() {}; + + inline bool isValid() const { return accountId().isValid(); } + inline AccountId accountId() const { return _accountId; } + inline QString accountName() const { return isInternal() ? tr("Internal Core") : _accountName; } + inline QUuid uuid() const { return _uuid; } + inline bool isInternal() const { return _internal; } + + inline QString user() const { return _user; } + inline bool storePassword() const { return _storePassword; } + inline QString hostName() const { return _hostName; } + inline uint port() const { return _port; } + inline bool useSsl() const { return _useSsl; } + + inline bool useProxy() const { return _useProxy; } + inline QNetworkProxy::ProxyType proxyType() const { return _proxyType; } + inline QString proxyUser() const { return _proxyUser; } + inline QString proxyHostName() const { return _proxyHostName; } + inline uint proxyPort() const { return _proxyPort; } + + void setAccountId(AccountId id); + void setAccountName(const QString &accountName); + void setUuid(const QUuid &uuid); + void setInternal(bool); + + void setUser(const QString &user); + void setStorePassword(bool); + void setHostName(const QString &hostname); + void setPort(uint port); + void setUseSsl(bool); + + void setUseProxy(bool); + void setProxyType(QNetworkProxy::ProxyType); + void setProxyUser(const QString &); + void setProxyHostName(const QString &); + void setProxyPort(uint); + + /* These might be overridden for KWallet support */ + virtual inline QString password() const { return _password; } + virtual void setPassword(const QString &password); + virtual inline QString proxyPassword() const { return _proxyPassword; } + virtual void setProxyPassword(const QString &); + + virtual QVariantMap toVariantMap(bool forcePassword = false) const; + virtual void fromVariantMap(const QVariantMap &); + + bool operator==(const CoreAccount &other) const; private: - AccountId _accountId; - QString _accountName; - QUuid _uuid; - bool _internal; - QString _user, _password, _hostName; - uint _port; - bool _storePassword, _useSsl, _useProxy; - QNetworkProxy::ProxyType _proxyType; - QString _proxyUser, _proxyPassword, _proxyHostName; - uint _proxyPort; + AccountId _accountId; + QString _accountName; + QUuid _uuid; + bool _internal; + QString _user, _password, _hostName; + uint _port; + bool _storePassword, _useSsl, _useProxy; + QNetworkProxy::ProxyType _proxyType; + QString _proxyUser, _proxyPassword, _proxyHostName; + uint _proxyPort; }; + #endif diff --git a/src/client/coreaccountmodel.cpp b/src/client/coreaccountmodel.cpp index a7a2f017..a54cd2f9 100644 --- a/src/client/coreaccountmodel.cpp +++ b/src/client/coreaccountmodel.cpp @@ -24,200 +24,234 @@ #include "quassel.h" CoreAccountModel::CoreAccountModel(QObject *parent) - : QAbstractListModel(parent), - _internalAccount(0) + : QAbstractListModel(parent), + _internalAccount(0) { - } + CoreAccountModel::CoreAccountModel(const CoreAccountModel *other, QObject *parent) - : QAbstractListModel(parent), - _internalAccount(0) + : QAbstractListModel(parent), + _internalAccount(0) { - update(other); + update(other); } -void CoreAccountModel::update(const CoreAccountModel *other) { - clear(); - if (other->_accounts.count() > 0) { - beginInsertRows(QModelIndex(), 0, other->_accounts.count() -1); - _accounts = other->_accounts; - endInsertRows(); - } - _internalAccount = other->internalAccount(); - _removedAccounts = other->_removedAccounts; -} - -void CoreAccountModel::load() { - clear(); - CoreAccountSettings s; - foreach(AccountId accId, s.knownAccounts()) { - QVariantMap map = s.retrieveAccountData(accId); - CoreAccount acc; - acc.fromVariantMap(map); // TODO Hook into kwallet/password saving stuff - insertAccount(acc); - } - if(Quassel::runMode() == Quassel::Monolithic && !internalAccount().isValid()) { - // Make sure we have an internal account in monolithic mode - CoreAccount intAcc; - intAcc.setInternal(true); - intAcc.setAccountName(tr("Internal Core")); - _internalAccount = createOrUpdateAccount(intAcc); - } -} - -void CoreAccountModel::save() { - CoreAccountSettings s; - foreach(AccountId id, _removedAccounts) { - s.removeAccount(id); - } - _removedAccounts.clear(); - foreach(const CoreAccount &acc, accounts()) { - QVariantMap map = acc.toVariantMap(false); // TODO Hook into kwallet/password saving stuff - s.storeAccountData(acc.accountId(), map); - } -} - -void CoreAccountModel::clear() { - if(rowCount()) { - beginRemoveRows(QModelIndex(), 0, rowCount()-1); - _internalAccount = 0; - _accounts.clear(); - endRemoveRows(); - } + +void CoreAccountModel::update(const CoreAccountModel *other) +{ + clear(); + if (other->_accounts.count() > 0) { + beginInsertRows(QModelIndex(), 0, other->_accounts.count() -1); + _accounts = other->_accounts; + endInsertRows(); + } + _internalAccount = other->internalAccount(); + _removedAccounts = other->_removedAccounts; } -QVariant CoreAccountModel::data(const QModelIndex &index, int role) const { - if(!index.isValid() || index.row() >= rowCount() || index.column() >= 1) - return QVariant(); - const CoreAccount &acc = accounts().at(index.row()); +void CoreAccountModel::load() +{ + clear(); + CoreAccountSettings s; + foreach(AccountId accId, s.knownAccounts()) { + QVariantMap map = s.retrieveAccountData(accId); + CoreAccount acc; + acc.fromVariantMap(map); // TODO Hook into kwallet/password saving stuff + insertAccount(acc); + } + if (Quassel::runMode() == Quassel::Monolithic && !internalAccount().isValid()) { + // Make sure we have an internal account in monolithic mode + CoreAccount intAcc; + intAcc.setInternal(true); + intAcc.setAccountName(tr("Internal Core")); + _internalAccount = createOrUpdateAccount(intAcc); + } +} - switch(role) { - case Qt::DisplayRole: - return acc.accountName(); - case AccountIdRole: - return QVariant::fromValue(acc.accountId()); - case UuidRole: - return acc.uuid().toString(); - default: - return QVariant(); +void CoreAccountModel::save() +{ + CoreAccountSettings s; + foreach(AccountId id, _removedAccounts) { + s.removeAccount(id); + } + _removedAccounts.clear(); + foreach(const CoreAccount &acc, accounts()) { + QVariantMap map = acc.toVariantMap(false); // TODO Hook into kwallet/password saving stuff + s.storeAccountData(acc.accountId(), map); + } +} + - } +void CoreAccountModel::clear() +{ + if (rowCount()) { + beginRemoveRows(QModelIndex(), 0, rowCount()-1); + _internalAccount = 0; + _accounts.clear(); + endRemoveRows(); + } } -CoreAccount CoreAccountModel::account(AccountId id) const { - int idx = findAccountIdx(id); - if(idx >= 0) - return _accounts.value(idx); - return CoreAccount(); + +QVariant CoreAccountModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() >= rowCount() || index.column() >= 1) + return QVariant(); + + const CoreAccount &acc = accounts().at(index.row()); + + switch (role) { + case Qt::DisplayRole: + return acc.accountName(); + case AccountIdRole: + return QVariant::fromValue(acc.accountId()); + case UuidRole: + return acc.uuid().toString(); + + default: + return QVariant(); + } +} + + +CoreAccount CoreAccountModel::account(AccountId id) const +{ + int idx = findAccountIdx(id); + if (idx >= 0) + return _accounts.value(idx); + return CoreAccount(); } -CoreAccount CoreAccountModel::account(const QModelIndex &idx) const { - if(idx.isValid() && idx.row() < _accounts.count()) - return _accounts.value(idx.row()); - return CoreAccount(); + +CoreAccount CoreAccountModel::account(const QModelIndex &idx) const +{ + if (idx.isValid() && idx.row() < _accounts.count()) + return _accounts.value(idx.row()); + return CoreAccount(); } -QList CoreAccountModel::accounts() const { - return _accounts; + +QList CoreAccountModel::accounts() const +{ + return _accounts; } -QList CoreAccountModel::accountIds() const { - QList list; - foreach(const CoreAccount &acc, accounts()) + +QList CoreAccountModel::accountIds() const +{ + QList list; + foreach(const CoreAccount &acc, accounts()) list << acc.accountId(); - return list; + return list; } -bool CoreAccountModel::operator==(const CoreAccountModel &other) const { - return _accounts == other._accounts; + +bool CoreAccountModel::operator==(const CoreAccountModel &other) const +{ + return _accounts == other._accounts; } + // TODO with Qt 4.6, use QAbstractItemModel move semantics to properly do this -AccountId CoreAccountModel::createOrUpdateAccount(const CoreAccount &newAcc) { - CoreAccount acc = newAcc; - - if(acc.uuid().isNull()) - acc.setUuid(QUuid::createUuid()); - - if(!acc.accountId().isValid()) { - // find free Id - AccountId newId = 0; - const QList &ids = accountIds(); - for(int i = 1; ; i++) { - if(!_removedAccounts.contains(i) && !ids.contains(i)) { - newId = i; - break; - } - } - acc.setAccountId(newId); - insertAccount(acc); - } else { - int idx = findAccountIdx(acc.accountId()); - if(idx >= 0) { - if(acc.accountName() == accounts().at(idx).accountName()) { - _accounts[idx] = acc; - emit dataChanged(index(idx, 0), index(idx, 0)); - } else { - takeAccount(acc.accountId()); +AccountId CoreAccountModel::createOrUpdateAccount(const CoreAccount &newAcc) +{ + CoreAccount acc = newAcc; + + if (acc.uuid().isNull()) + acc.setUuid(QUuid::createUuid()); + + if (!acc.accountId().isValid()) { + // find free Id + AccountId newId = 0; + const QList &ids = accountIds(); + for (int i = 1;; i++) { + if (!_removedAccounts.contains(i) && !ids.contains(i)) { + newId = i; + break; + } + } + acc.setAccountId(newId); insertAccount(acc); - } - } else - insertAccount(acc); - } - return acc.accountId(); -} - -void CoreAccountModel::insertAccount(const CoreAccount &acc) { - if(acc.isInternal()) { - if(internalAccount().isValid()) { - qWarning() << "Trying to insert a second internal account in CoreAccountModel, ignoring"; - return; } - _internalAccount = acc.accountId(); - } + else { + int idx = findAccountIdx(acc.accountId()); + if (idx >= 0) { + if (acc.accountName() == accounts().at(idx).accountName()) { + _accounts[idx] = acc; + emit dataChanged(index(idx, 0), index(idx, 0)); + } + else { + takeAccount(acc.accountId()); + insertAccount(acc); + } + } + else + insertAccount(acc); + } + return acc.accountId(); +} - // check for Quuid - int idx = 0; - while(idx < _accounts.count() && acc.accountName() > _accounts.at(idx).accountName() && !acc.isInternal()) - ++idx; - beginInsertRows(QModelIndex(), idx, idx); - _accounts.insert(idx, acc); - endInsertRows(); +void CoreAccountModel::insertAccount(const CoreAccount &acc) +{ + if (acc.isInternal()) { + if (internalAccount().isValid()) { + qWarning() << "Trying to insert a second internal account in CoreAccountModel, ignoring"; + return; + } + _internalAccount = acc.accountId(); + } + + // check for Quuid + int idx = 0; + while (idx<_accounts.count() && acc.accountName()> _accounts.at(idx).accountName() && !acc.isInternal()) + ++idx; + + beginInsertRows(QModelIndex(), idx, idx); + _accounts.insert(idx, acc); + endInsertRows(); } -CoreAccount CoreAccountModel::takeAccount(AccountId accId) { - int idx = findAccountIdx(accId); - if(idx < 0) - return CoreAccount(); - beginRemoveRows(QModelIndex(), idx, idx); - CoreAccount acc = _accounts.takeAt(idx); - endRemoveRows(); +CoreAccount CoreAccountModel::takeAccount(AccountId accId) +{ + int idx = findAccountIdx(accId); + if (idx < 0) + return CoreAccount(); + + beginRemoveRows(QModelIndex(), idx, idx); + CoreAccount acc = _accounts.takeAt(idx); + endRemoveRows(); - if(acc.isInternal()) - _internalAccount = 0; + if (acc.isInternal()) + _internalAccount = 0; - return acc; + return acc; } -void CoreAccountModel::removeAccount(AccountId accId) { - takeAccount(accId); - _removedAccounts.insert(accId); + +void CoreAccountModel::removeAccount(AccountId accId) +{ + takeAccount(accId); + _removedAccounts.insert(accId); } -QModelIndex CoreAccountModel::accountIndex(AccountId accId) const { - for(int i = 0; i < _accounts.count(); i++) { - if(_accounts.at(i).accountId() == accId) - return index(i, 0); - } - return QModelIndex(); + +QModelIndex CoreAccountModel::accountIndex(AccountId accId) const +{ + for (int i = 0; i < _accounts.count(); i++) { + if (_accounts.at(i).accountId() == accId) + return index(i, 0); + } + return QModelIndex(); } -int CoreAccountModel::findAccountIdx(AccountId id) const { - QModelIndex idx = accountIndex(id); - return idx.isValid() ? idx.row() : -1; + +int CoreAccountModel::findAccountIdx(AccountId id) const +{ + QModelIndex idx = accountIndex(id); + return idx.isValid() ? idx.row() : -1; } diff --git a/src/client/coreaccountmodel.h b/src/client/coreaccountmodel.h index 1c314693..dbcb20eb 100644 --- a/src/client/coreaccountmodel.h +++ b/src/client/coreaccountmodel.h @@ -26,61 +26,67 @@ #include "coreaccount.h" -class CoreAccountModel : public QAbstractListModel { - Q_OBJECT +class CoreAccountModel : public QAbstractListModel +{ + Q_OBJECT public: - enum { - AccountIdRole = Qt::UserRole, - UuidRole - }; + enum { + AccountIdRole = Qt::UserRole, + UuidRole + }; - CoreAccountModel(QObject *parent = 0); - CoreAccountModel(const CoreAccountModel *other, QObject *parent = 0); + CoreAccountModel(QObject *parent = 0); + CoreAccountModel(const CoreAccountModel *other, QObject *parent = 0); - inline int rowCount(const QModelIndex &parent = QModelIndex()) const; - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + inline int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - CoreAccount account(const QModelIndex &) const; - CoreAccount account(AccountId) const; - QList accounts() const; - QList accountIds() const; - QModelIndex accountIndex(AccountId id) const; + CoreAccount account(const QModelIndex &) const; + CoreAccount account(AccountId) const; + QList accounts() const; + QList accountIds() const; + QModelIndex accountIndex(AccountId id) const; - inline AccountId internalAccount() const; + inline AccountId internalAccount() const; - AccountId createOrUpdateAccount(const CoreAccount &newAccountData = CoreAccount()); - CoreAccount takeAccount(AccountId); - void removeAccount(AccountId); + AccountId createOrUpdateAccount(const CoreAccount &newAccountData = CoreAccount()); + CoreAccount takeAccount(AccountId); + void removeAccount(AccountId); - void update(const CoreAccountModel *other); + void update(const CoreAccountModel *other); - bool operator==(const CoreAccountModel &other) const; + bool operator==(const CoreAccountModel &other) const; public slots: - void save(); - void load(); - void clear(); + void save(); + void load(); + void clear(); protected: - void insertAccount(const CoreAccount &); - int findAccountIdx(AccountId) const; + void insertAccount(const CoreAccount &); + int findAccountIdx(AccountId) const; private: - int listIndex(AccountId); + int listIndex(AccountId); - QList _accounts; - QSet _removedAccounts; - AccountId _internalAccount; + QList _accounts; + QSet _removedAccounts; + AccountId _internalAccount; }; + // Inlines -int CoreAccountModel::rowCount(const QModelIndex &) const { - return _accounts.count(); +int CoreAccountModel::rowCount(const QModelIndex &) const +{ + return _accounts.count(); } -AccountId CoreAccountModel::internalAccount() const { - return _internalAccount; + +AccountId CoreAccountModel::internalAccount() const +{ + return _internalAccount; } + #endif diff --git a/src/client/coreconnection.cpp b/src/client/coreconnection.cpp index 717fff39..c1ab23c0 100644 --- a/src/client/coreconnection.cpp +++ b/src/client/coreconnection.cpp @@ -35,675 +35,764 @@ #include "util.h" CoreConnection::CoreConnection(CoreAccountModel *model, QObject *parent) - : QObject(parent), - _model(model), - _blockSize(0), - _state(Disconnected), - _wantReconnect(false), - _progressMinimum(0), - _progressMaximum(-1), - _progressValue(-1), - _wasReconnect(false), - _requestedDisconnect(false) + : QObject(parent), + _model(model), + _blockSize(0), + _state(Disconnected), + _wantReconnect(false), + _progressMinimum(0), + _progressMaximum(-1), + _progressValue(-1), + _wasReconnect(false), + _requestedDisconnect(false) { - qRegisterMetaType("CoreConnection::ConnectionState"); + qRegisterMetaType("CoreConnection::ConnectionState"); } -void CoreConnection::init() { - Client::signalProxy()->setHeartBeatInterval(30); - connect(Client::signalProxy(), SIGNAL(disconnected()), SLOT(coreSocketDisconnected())); - connect(Client::signalProxy(), SIGNAL(lagUpdated(int)), SIGNAL(lagUpdated(int))); - _reconnectTimer.setSingleShot(true); - connect(&_reconnectTimer, SIGNAL(timeout()), SLOT(reconnectTimeout())); +void CoreConnection::init() +{ + Client::signalProxy()->setHeartBeatInterval(30); + connect(Client::signalProxy(), SIGNAL(disconnected()), SLOT(coreSocketDisconnected())); + connect(Client::signalProxy(), SIGNAL(lagUpdated(int)), SIGNAL(lagUpdated(int))); + + _reconnectTimer.setSingleShot(true); + connect(&_reconnectTimer, SIGNAL(timeout()), SLOT(reconnectTimeout())); #ifdef HAVE_KDE - connect(Solid::Networking::notifier(), SIGNAL(statusChanged(Solid::Networking::Status)), - SLOT(solidNetworkStatusChanged(Solid::Networking::Status))); + connect(Solid::Networking::notifier(), SIGNAL(statusChanged(Solid::Networking::Status)), + SLOT(solidNetworkStatusChanged(Solid::Networking::Status))); #endif - CoreConnectionSettings s; - s.initAndNotify("PingTimeoutInterval", this, SLOT(pingTimeoutIntervalChanged(QVariant)), 60); - s.initAndNotify("ReconnectInterval", this, SLOT(reconnectIntervalChanged(QVariant)), 60); - s.notify("NetworkDetectionMode", this, SLOT(networkDetectionModeChanged(QVariant))); - networkDetectionModeChanged(s.networkDetectionMode()); + CoreConnectionSettings s; + s.initAndNotify("PingTimeoutInterval", this, SLOT(pingTimeoutIntervalChanged(QVariant)), 60); + s.initAndNotify("ReconnectInterval", this, SLOT(reconnectIntervalChanged(QVariant)), 60); + s.notify("NetworkDetectionMode", this, SLOT(networkDetectionModeChanged(QVariant))); + networkDetectionModeChanged(s.networkDetectionMode()); } -void CoreConnection::setProgressText(const QString &text) { - if(_progressText != text) { - _progressText = text; - emit progressTextChanged(text); - } + +void CoreConnection::setProgressText(const QString &text) +{ + if (_progressText != text) { + _progressText = text; + emit progressTextChanged(text); + } } -void CoreConnection::setProgressValue(int value) { - if(_progressValue != value) { - _progressValue = value; - emit progressValueChanged(value); - } + +void CoreConnection::setProgressValue(int value) +{ + if (_progressValue != value) { + _progressValue = value; + emit progressValueChanged(value); + } } -void CoreConnection::setProgressMinimum(int minimum) { - if(_progressMinimum != minimum) { - _progressMinimum = minimum; - emit progressRangeChanged(minimum, _progressMaximum); - } + +void CoreConnection::setProgressMinimum(int minimum) +{ + if (_progressMinimum != minimum) { + _progressMinimum = minimum; + emit progressRangeChanged(minimum, _progressMaximum); + } } -void CoreConnection::setProgressMaximum(int maximum) { - if(_progressMaximum != maximum) { - _progressMaximum = maximum; - emit progressRangeChanged(_progressMinimum, maximum); - } + +void CoreConnection::setProgressMaximum(int maximum) +{ + if (_progressMaximum != maximum) { + _progressMaximum = maximum; + emit progressRangeChanged(_progressMinimum, maximum); + } } -void CoreConnection::updateProgress(int value, int max) { - if(max != _progressMaximum) { - _progressMaximum = max; - emit progressRangeChanged(_progressMinimum, _progressMaximum); - } - setProgressValue(value); + +void CoreConnection::updateProgress(int value, int max) +{ + if (max != _progressMaximum) { + _progressMaximum = max; + emit progressRangeChanged(_progressMinimum, _progressMaximum); + } + setProgressValue(value); } -void CoreConnection::reconnectTimeout() { - if(!_socket) { - CoreConnectionSettings s; - if(_wantReconnect && s.autoReconnect()) { +void CoreConnection::reconnectTimeout() +{ + if (!_socket) { + CoreConnectionSettings s; + if (_wantReconnect && s.autoReconnect()) { #ifdef HAVE_KDE - // If using Solid, we don't want to reconnect if we're offline - if(s.networkDetectionMode() == CoreConnectionSettings::UseSolid) { - if(Solid::Networking::status() != Solid::Networking::Connected - && Solid::Networking::status() != Solid::Networking::Unknown) { - return; - } - } + // If using Solid, we don't want to reconnect if we're offline + if (s.networkDetectionMode() == CoreConnectionSettings::UseSolid) { + if (Solid::Networking::status() != Solid::Networking::Connected + && Solid::Networking::status() != Solid::Networking::Unknown) { + return; + } + } #endif /* HAVE_KDE */ - reconnectToCore(); + reconnectToCore(); + } } - } } -void CoreConnection::networkDetectionModeChanged(const QVariant &vmode) { - CoreConnectionSettings s; - CoreConnectionSettings::NetworkDetectionMode mode = (CoreConnectionSettings::NetworkDetectionMode)vmode.toInt(); - if(mode == CoreConnectionSettings::UsePingTimeout) - Client::signalProxy()->setMaxHeartBeatCount(s.pingTimeoutInterval() / 30); - else { - Client::signalProxy()->setMaxHeartBeatCount(-1); - } + +void CoreConnection::networkDetectionModeChanged(const QVariant &vmode) +{ + CoreConnectionSettings s; + CoreConnectionSettings::NetworkDetectionMode mode = (CoreConnectionSettings::NetworkDetectionMode)vmode.toInt(); + if (mode == CoreConnectionSettings::UsePingTimeout) + Client::signalProxy()->setMaxHeartBeatCount(s.pingTimeoutInterval() / 30); + else { + Client::signalProxy()->setMaxHeartBeatCount(-1); + } } -void CoreConnection::pingTimeoutIntervalChanged(const QVariant &interval) { - CoreConnectionSettings s; - if(s.networkDetectionMode() == CoreConnectionSettings::UsePingTimeout) - Client::signalProxy()->setMaxHeartBeatCount(interval.toInt() / 30); // interval is 30 seconds + +void CoreConnection::pingTimeoutIntervalChanged(const QVariant &interval) +{ + CoreConnectionSettings s; + if (s.networkDetectionMode() == CoreConnectionSettings::UsePingTimeout) + Client::signalProxy()->setMaxHeartBeatCount(interval.toInt() / 30); // interval is 30 seconds } -void CoreConnection::reconnectIntervalChanged(const QVariant &interval) { - _reconnectTimer.setInterval(interval.toInt() * 1000); + +void CoreConnection::reconnectIntervalChanged(const QVariant &interval) +{ + _reconnectTimer.setInterval(interval.toInt() * 1000); } + #ifdef HAVE_KDE -void CoreConnection::solidNetworkStatusChanged(Solid::Networking::Status status) { - CoreConnectionSettings s; - if(s.networkDetectionMode() != CoreConnectionSettings::UseSolid) - return; - - switch(status) { - case Solid::Networking::Unknown: - case Solid::Networking::Connected: - //qDebug() << "Solid: Network status changed to connected or unknown"; - if(state() == Disconnected) { - if(_wantReconnect && s.autoReconnect()) { - reconnectToCore(); - } +void CoreConnection::solidNetworkStatusChanged(Solid::Networking::Status status) +{ + CoreConnectionSettings s; + if (s.networkDetectionMode() != CoreConnectionSettings::UseSolid) + return; + + switch (status) { + case Solid::Networking::Unknown: + case Solid::Networking::Connected: + //qDebug() << "Solid: Network status changed to connected or unknown"; + if (state() == Disconnected) { + if (_wantReconnect && s.autoReconnect()) { + reconnectToCore(); + } + } + break; + case Solid::Networking::Disconnecting: + case Solid::Networking::Unconnected: + if (state() != Disconnected && !isLocalConnection()) + disconnectFromCore(tr("Network is down"), true); + break; + default: + break; } - break; - case Solid::Networking::Disconnecting: - case Solid::Networking::Unconnected: - if(state() != Disconnected && !isLocalConnection()) - disconnectFromCore(tr("Network is down"), true); - break; - default: - break; - } } + #endif -bool CoreConnection::isEncrypted() const { +bool CoreConnection::isEncrypted() const +{ #ifndef HAVE_SSL - return false; + return false; #else - QSslSocket *sock = qobject_cast(_socket); - return isConnected() && sock && sock->isEncrypted(); + QSslSocket *sock = qobject_cast(_socket); + return isConnected() && sock && sock->isEncrypted(); #endif } -bool CoreConnection::isLocalConnection() const { - if(!isConnected()) + +bool CoreConnection::isLocalConnection() const +{ + if (!isConnected()) + return false; + if (currentAccount().isInternal()) + return true; + if (_socket->peerAddress().isInSubnet(QHostAddress::LocalHost, 0x00ffffff)) + return true; + return false; - if(currentAccount().isInternal()) - return true; - if(_socket->peerAddress().isInSubnet(QHostAddress::LocalHost, 0x00ffffff)) - return true; +} - return false; -} - -void CoreConnection::socketStateChanged(QAbstractSocket::SocketState socketState) { - QString text; - - switch(socketState) { - case QAbstractSocket::UnconnectedState: - text = tr("Disconnected"); - break; - case QAbstractSocket::HostLookupState: - text = tr("Looking up %1...").arg(currentAccount().hostName()); - break; - case QAbstractSocket::ConnectingState: - text = tr("Connecting to %1...").arg(currentAccount().hostName()); - break; - case QAbstractSocket::ConnectedState: - text = tr("Connected to %1").arg(currentAccount().hostName()); - break; - case QAbstractSocket::ClosingState: - text = tr("Disconnecting from %1...").arg(currentAccount().hostName()); - break; - default: - break; - } - - if(!text.isEmpty()) - emit progressTextChanged(text); - - setState(socketState); -} - -void CoreConnection::setState(QAbstractSocket::SocketState socketState) { - ConnectionState state; - - switch(socketState) { - case QAbstractSocket::UnconnectedState: - state = Disconnected; - break; - case QAbstractSocket::HostLookupState: - case QAbstractSocket::ConnectingState: - case QAbstractSocket::ConnectedState: // we'll set it to Connected in connectionReady() - state = Connecting; - break; - default: - state = Disconnected; - } - - setState(state); -} - -void CoreConnection::setState(ConnectionState state) { - if(state != _state) { - _state = state; - emit stateChanged(state); - if(state == Disconnected) - emit disconnected(); - } -} - -void CoreConnection::coreSocketError(QAbstractSocket::SocketError) { - qDebug() << "coreSocketError" << _socket << _socket->errorString(); - disconnectFromCore(_socket->errorString(), true); -} - -void CoreConnection::coreSocketDisconnected() { - // qDebug() << Q_FUNC_INFO; - _wasReconnect = !_requestedDisconnect; - resetConnection(true); - // FIXME handle disconnects gracefully -} - -void CoreConnection::coreHasData() { - QVariant item; - while(SignalProxy::readDataFromDevice(_socket, _blockSize, item)) { - QVariantMap msg = item.toMap(); - if(!msg.contains("MsgType")) { - // This core is way too old and does not even speak our init protocol... - emit connectionErrorPopup(tr("The Quassel Core you try to connect to is too old! Please consider upgrading.")); - disconnectFromCore(QString(), false); - return; + +void CoreConnection::socketStateChanged(QAbstractSocket::SocketState socketState) +{ + QString text; + + switch (socketState) { + case QAbstractSocket::UnconnectedState: + text = tr("Disconnected"); + break; + case QAbstractSocket::HostLookupState: + text = tr("Looking up %1...").arg(currentAccount().hostName()); + break; + case QAbstractSocket::ConnectingState: + text = tr("Connecting to %1...").arg(currentAccount().hostName()); + break; + case QAbstractSocket::ConnectedState: + text = tr("Connected to %1").arg(currentAccount().hostName()); + break; + case QAbstractSocket::ClosingState: + text = tr("Disconnecting from %1...").arg(currentAccount().hostName()); + break; + default: + break; } - if(msg["MsgType"] == "ClientInitAck") { - clientInitAck(msg); - } else if(msg["MsgType"] == "ClientInitReject") { - emit connectionErrorPopup(msg["Error"].toString()); - disconnectFromCore(QString(), false); - return; - } else if(msg["MsgType"] == "CoreSetupAck") { - emit coreSetupSuccess(); - } else if(msg["MsgType"] == "CoreSetupReject") { - emit coreSetupFailed(msg["Error"].toString()); - } else if(msg["MsgType"] == "ClientLoginReject") { - loginFailed(msg["Error"].toString()); - } else if(msg["MsgType"] == "ClientLoginAck") { - loginSuccess(); - } else if(msg["MsgType"] == "SessionInit") { - // that's it, let's hand over to the signal proxy - // if the socket is an orphan, the signalProxy adopts it. - // -> we don't need to care about it anymore - _socket->setParent(0); - Client::signalProxy()->addPeer(_socket); - - sessionStateReceived(msg["SessionState"].toMap()); - break; // this is definitively the last message we process here! - } else { - disconnectFromCore(tr("Invalid data received from core"), false); - return; + + if (!text.isEmpty()) + emit progressTextChanged(text); + + setState(socketState); +} + + +void CoreConnection::setState(QAbstractSocket::SocketState socketState) +{ + ConnectionState state; + + switch (socketState) { + case QAbstractSocket::UnconnectedState: + state = Disconnected; + break; + case QAbstractSocket::HostLookupState: + case QAbstractSocket::ConnectingState: + case QAbstractSocket::ConnectedState: // we'll set it to Connected in connectionReady() + state = Connecting; + break; + default: + state = Disconnected; } - } - if(_blockSize > 0) { - updateProgress(_socket->bytesAvailable(), _blockSize); - } + + setState(state); } -void CoreConnection::disconnectFromCore() { - _requestedDisconnect = true; - disconnectFromCore(QString(), false); // requested disconnect, so don't try to reconnect + +void CoreConnection::setState(ConnectionState state) +{ + if (state != _state) { + _state = state; + emit stateChanged(state); + if (state == Disconnected) + emit disconnected(); + } } -void CoreConnection::disconnectFromCore(const QString &errorString, bool wantReconnect) { - if(!wantReconnect) - _reconnectTimer.stop(); - _wasReconnect = wantReconnect; // store if disconnect was requested +void CoreConnection::coreSocketError(QAbstractSocket::SocketError) +{ + qDebug() << "coreSocketError" << _socket << _socket->errorString(); + disconnectFromCore(_socket->errorString(), true); +} - if(errorString.isEmpty()) - emit connectionError(tr("Disconnected")); - else - emit connectionError(errorString); - Client::signalProxy()->removeAllPeers(); - resetConnection(wantReconnect); +void CoreConnection::coreSocketDisconnected() +{ + // qDebug() << Q_FUNC_INFO; + _wasReconnect = !_requestedDisconnect; + resetConnection(true); + // FIXME handle disconnects gracefully } -void CoreConnection::resetConnection(bool wantReconnect) { - _wantReconnect = wantReconnect; - if(_socket) { - disconnect(_socket, 0, this, 0); - _socket->deleteLater(); - _socket = 0; - } - _requestedDisconnect = false; - _blockSize = 0; +void CoreConnection::coreHasData() +{ + QVariant item; + while (SignalProxy::readDataFromDevice(_socket, _blockSize, item)) { + QVariantMap msg = item.toMap(); + if (!msg.contains("MsgType")) { + // This core is way too old and does not even speak our init protocol... + emit connectionErrorPopup(tr("The Quassel Core you try to connect to is too old! Please consider upgrading.")); + disconnectFromCore(QString(), false); + return; + } + if (msg["MsgType"] == "ClientInitAck") { + clientInitAck(msg); + } + else if (msg["MsgType"] == "ClientInitReject") { + emit connectionErrorPopup(msg["Error"].toString()); + disconnectFromCore(QString(), false); + return; + } + else if (msg["MsgType"] == "CoreSetupAck") { + emit coreSetupSuccess(); + } + else if (msg["MsgType"] == "CoreSetupReject") { + emit coreSetupFailed(msg["Error"].toString()); + } + else if (msg["MsgType"] == "ClientLoginReject") { + loginFailed(msg["Error"].toString()); + } + else if (msg["MsgType"] == "ClientLoginAck") { + loginSuccess(); + } + else if (msg["MsgType"] == "SessionInit") { + // that's it, let's hand over to the signal proxy + // if the socket is an orphan, the signalProxy adopts it. + // -> we don't need to care about it anymore + _socket->setParent(0); + Client::signalProxy()->addPeer(_socket); + + sessionStateReceived(msg["SessionState"].toMap()); + break; // this is definitively the last message we process here! + } + else { + disconnectFromCore(tr("Invalid data received from core"), false); + return; + } + } + if (_blockSize > 0) { + updateProgress(_socket->bytesAvailable(), _blockSize); + } +} + - _coreMsgBuffer.clear(); +void CoreConnection::disconnectFromCore() +{ + _requestedDisconnect = true; + disconnectFromCore(QString(), false); // requested disconnect, so don't try to reconnect +} - _netsToSync.clear(); - _numNetsToSync = 0; - setProgressMaximum(-1); // disable - setState(Disconnected); - emit lagUpdated(-1); +void CoreConnection::disconnectFromCore(const QString &errorString, bool wantReconnect) +{ + if (!wantReconnect) + _reconnectTimer.stop(); - emit connectionMsg(tr("Disconnected from core.")); - emit encrypted(false); + _wasReconnect = wantReconnect; // store if disconnect was requested - // initiate if a reconnect if appropriate - CoreConnectionSettings s; - if(wantReconnect && s.autoReconnect()) { - _reconnectTimer.start(); - } -} + if (errorString.isEmpty()) + emit connectionError(tr("Disconnected")); + else + emit connectionError(errorString); -void CoreConnection::reconnectToCore() { - if(currentAccount().isValid()) - connectToCore(currentAccount().accountId()); + Client::signalProxy()->removeAllPeers(); + resetConnection(wantReconnect); } -bool CoreConnection::connectToCore(AccountId accId) { - if(isConnected()) - return false; - CoreAccountSettings s; +void CoreConnection::resetConnection(bool wantReconnect) +{ + _wantReconnect = wantReconnect; - // FIXME: Don't force connection to internal core in mono client - if(Quassel::runMode() == Quassel::Monolithic) { - _account = accountModel()->account(accountModel()->internalAccount()); - Q_ASSERT(_account.isValid()); - } else { - if(!accId.isValid()) { - // check our settings and figure out what to do - if(!s.autoConnectOnStartup()) - return false; - if(s.autoConnectToFixedAccount()) - accId = s.autoConnectAccount(); - else - accId = s.lastAccount(); - if(!accId.isValid()) - return false; + if (_socket) { + disconnect(_socket, 0, this, 0); + _socket->deleteLater(); + _socket = 0; } - _account = accountModel()->account(accId); - if(!_account.accountId().isValid()) { - return false; + _requestedDisconnect = false; + _blockSize = 0; + + _coreMsgBuffer.clear(); + + _netsToSync.clear(); + _numNetsToSync = 0; + + setProgressMaximum(-1); // disable + setState(Disconnected); + emit lagUpdated(-1); + + emit connectionMsg(tr("Disconnected from core.")); + emit encrypted(false); + + // initiate if a reconnect if appropriate + CoreConnectionSettings s; + if (wantReconnect && s.autoReconnect()) { + _reconnectTimer.start(); } - if(Quassel::runMode() != Quassel::Monolithic) { - if(_account.isInternal()) +} + + +void CoreConnection::reconnectToCore() +{ + if (currentAccount().isValid()) + connectToCore(currentAccount().accountId()); +} + + +bool CoreConnection::connectToCore(AccountId accId) +{ + if (isConnected()) return false; + + CoreAccountSettings s; + + // FIXME: Don't force connection to internal core in mono client + if (Quassel::runMode() == Quassel::Monolithic) { + _account = accountModel()->account(accountModel()->internalAccount()); + Q_ASSERT(_account.isValid()); + } + else { + if (!accId.isValid()) { + // check our settings and figure out what to do + if (!s.autoConnectOnStartup()) + return false; + if (s.autoConnectToFixedAccount()) + accId = s.autoConnectAccount(); + else + accId = s.lastAccount(); + if (!accId.isValid()) + return false; + } + _account = accountModel()->account(accId); + if (!_account.accountId().isValid()) { + return false; + } + if (Quassel::runMode() != Quassel::Monolithic) { + if (_account.isInternal()) + return false; + } } - } - s.setLastAccount(accId); - connectToCurrentAccount(); - return true; + s.setLastAccount(accId); + connectToCurrentAccount(); + return true; } -void CoreConnection::connectToCurrentAccount() { - resetConnection(false); - if(currentAccount().isInternal()) { - if(Quassel::runMode() != Quassel::Monolithic) { - qWarning() << "Cannot connect to internal core in client-only mode!"; - return; +void CoreConnection::connectToCurrentAccount() +{ + resetConnection(false); + + if (currentAccount().isInternal()) { + if (Quassel::runMode() != Quassel::Monolithic) { + qWarning() << "Cannot connect to internal core in client-only mode!"; + return; + } + emit startInternalCore(); + emit connectToInternalCore(Client::instance()->signalProxy()); + return; } - emit startInternalCore(); - emit connectToInternalCore(Client::instance()->signalProxy()); - return; - } - CoreAccountSettings s; + CoreAccountSettings s; - Q_ASSERT(!_socket); + Q_ASSERT(!_socket); #ifdef HAVE_SSL - QSslSocket *sock = new QSslSocket(Client::instance()); - // make sure the warning is shown if we happen to connect without SSL support later - s.setAccountValue("ShowNoClientSslWarning", true); + QSslSocket *sock = new QSslSocket(Client::instance()); + // make sure the warning is shown if we happen to connect without SSL support later + s.setAccountValue("ShowNoClientSslWarning", true); #else - if(_account.useSsl()) { - if(s.accountValue("ShowNoClientSslWarning", true).toBool()) { - bool accepted = false; - emit handleNoSslInClient(&accepted); - if(!accepted) { - emit connectionError(tr("Unencrypted connection canceled")); - return; - } - s.setAccountValue("ShowNoClientSslWarning", false); + if (_account.useSsl()) { + if (s.accountValue("ShowNoClientSslWarning", true).toBool()) { + bool accepted = false; + emit handleNoSslInClient(&accepted); + if (!accepted) { + emit connectionError(tr("Unencrypted connection canceled")); + return; + } + s.setAccountValue("ShowNoClientSslWarning", false); + } } - } - QTcpSocket *sock = new QTcpSocket(Client::instance()); + QTcpSocket *sock = new QTcpSocket(Client::instance()); #endif #ifndef QT_NO_NETWORKPROXY - if(_account.useProxy()) { - QNetworkProxy proxy(_account.proxyType(), _account.proxyHostName(), _account.proxyPort(), _account.proxyUser(), _account.proxyPassword()); - sock->setProxy(proxy); - } + if (_account.useProxy()) { + QNetworkProxy proxy(_account.proxyType(), _account.proxyHostName(), _account.proxyPort(), _account.proxyUser(), _account.proxyPassword()); + sock->setProxy(proxy); + } #endif - _socket = sock; - connect(sock, SIGNAL(readyRead()), SLOT(coreHasData())); - connect(sock, SIGNAL(connected()), SLOT(coreSocketConnected())); - connect(sock, SIGNAL(disconnected()), SLOT(coreSocketDisconnected())); - connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(coreSocketError(QAbstractSocket::SocketError))); - connect(sock, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SLOT(socketStateChanged(QAbstractSocket::SocketState))); + _socket = sock; + connect(sock, SIGNAL(readyRead()), SLOT(coreHasData())); + connect(sock, SIGNAL(connected()), SLOT(coreSocketConnected())); + connect(sock, SIGNAL(disconnected()), SLOT(coreSocketDisconnected())); + connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(coreSocketError(QAbstractSocket::SocketError))); + connect(sock, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SLOT(socketStateChanged(QAbstractSocket::SocketState))); - emit connectionMsg(tr("Connecting to %1...").arg(currentAccount().accountName())); - sock->connectToHost(_account.hostName(), _account.port()); + emit connectionMsg(tr("Connecting to %1...").arg(currentAccount().accountName())); + sock->connectToHost(_account.hostName(), _account.port()); } -void CoreConnection::coreSocketConnected() { - // Phase One: Send client info and wait for core info - emit connectionMsg(tr("Synchronizing to core...")); +void CoreConnection::coreSocketConnected() +{ + // Phase One: Send client info and wait for core info + + emit connectionMsg(tr("Synchronizing to core...")); - QVariantMap clientInit; - clientInit["MsgType"] = "ClientInit"; - clientInit["ClientVersion"] = Quassel::buildInfo().fancyVersionString; - clientInit["ClientDate"] = Quassel::buildInfo().buildDate; - clientInit["ProtocolVersion"] = Quassel::buildInfo().protocolVersion; - clientInit["UseSsl"] = _account.useSsl(); + QVariantMap clientInit; + clientInit["MsgType"] = "ClientInit"; + clientInit["ClientVersion"] = Quassel::buildInfo().fancyVersionString; + clientInit["ClientDate"] = Quassel::buildInfo().buildDate; + clientInit["ProtocolVersion"] = Quassel::buildInfo().protocolVersion; + clientInit["UseSsl"] = _account.useSsl(); #ifndef QT_NO_COMPRESS - clientInit["UseCompression"] = true; + clientInit["UseCompression"] = true; #else - clientInit["UseCompression"] = false; + clientInit["UseCompression"] = false; #endif - SignalProxy::writeDataToDevice(_socket, clientInit); + SignalProxy::writeDataToDevice(_socket, clientInit); } -void CoreConnection::clientInitAck(const QVariantMap &msg) { - // Core has accepted our version info and sent its own. Let's see if we accept it as well... - uint ver = msg["ProtocolVersion"].toUInt(); - if(ver < Quassel::buildInfo().clientNeedsProtocol) { - emit connectionErrorPopup(tr("The Quassel Core you are trying to connect to is too old!
" - "Need at least core/client protocol v%1 to connect.").arg(Quassel::buildInfo().clientNeedsProtocol)); - disconnectFromCore(QString(), false); - return; - } - Client::setCoreFeatures((Quassel::Features)msg["CoreFeatures"].toUInt()); +void CoreConnection::clientInitAck(const QVariantMap &msg) +{ + // Core has accepted our version info and sent its own. Let's see if we accept it as well... + uint ver = msg["ProtocolVersion"].toUInt(); + if (ver < Quassel::buildInfo().clientNeedsProtocol) { + emit connectionErrorPopup(tr("The Quassel Core you are trying to connect to is too old!
" + "Need at least core/client protocol v%1 to connect.").arg(Quassel::buildInfo().clientNeedsProtocol)); + disconnectFromCore(QString(), false); + return; + } + + Client::setCoreFeatures((Quassel::Features)msg["CoreFeatures"].toUInt()); #ifndef QT_NO_COMPRESS - if(msg["SupportsCompression"].toBool()) { - _socket->setProperty("UseCompression", true); - } + if (msg["SupportsCompression"].toBool()) { + _socket->setProperty("UseCompression", true); + } #endif - _coreMsgBuffer = msg; + _coreMsgBuffer = msg; #ifdef HAVE_SSL - CoreAccountSettings s; - if(currentAccount().useSsl()) { - if(msg["SupportSsl"].toBool()) { - // Make sure the warning is shown next time we don't have SSL in the core - s.setAccountValue("ShowNoCoreSslWarning", true); - - QSslSocket *sslSocket = qobject_cast(_socket); - Q_ASSERT(sslSocket); - connect(sslSocket, SIGNAL(encrypted()), SLOT(sslSocketEncrypted())); - connect(sslSocket, SIGNAL(sslErrors(const QList &)), SLOT(sslErrors())); - sslSocket->startClientEncryption(); - } else { - if(s.accountValue("ShowNoCoreSslWarning", true).toBool()) { - bool accepted = false; - emit handleNoSslInCore(&accepted); - if(!accepted) { - disconnectFromCore(tr("Unencrypted connection canceled"), false); - return; + CoreAccountSettings s; + if (currentAccount().useSsl()) { + if (msg["SupportSsl"].toBool()) { + // Make sure the warning is shown next time we don't have SSL in the core + s.setAccountValue("ShowNoCoreSslWarning", true); + + QSslSocket *sslSocket = qobject_cast(_socket); + Q_ASSERT(sslSocket); + connect(sslSocket, SIGNAL(encrypted()), SLOT(sslSocketEncrypted())); + connect(sslSocket, SIGNAL(sslErrors(const QList &)), SLOT(sslErrors())); + sslSocket->startClientEncryption(); + } + else { + if (s.accountValue("ShowNoCoreSslWarning", true).toBool()) { + bool accepted = false; + emit handleNoSslInCore(&accepted); + if (!accepted) { + disconnectFromCore(tr("Unencrypted connection canceled"), false); + return; + } + s.setAccountValue("ShowNoCoreSslWarning", false); + s.setAccountValue("SslCert", QString()); + } + connectionReady(); } - s.setAccountValue("ShowNoCoreSslWarning", false); - s.setAccountValue("SslCert", QString()); - } - connectionReady(); + return; } - return; - } #endif - // if we use SSL we wait for the next step until every SSL warning has been cleared - connectionReady(); + // if we use SSL we wait for the next step until every SSL warning has been cleared + connectionReady(); } -#ifdef HAVE_SSL -void CoreConnection::sslSocketEncrypted() { - QSslSocket *socket = qobject_cast(sender()); - Q_ASSERT(socket); +#ifdef HAVE_SSL - if(!socket->sslErrors().count()) { - // Cert is valid, so we don't want to store it as known - // That way, a warning will appear in case it becomes invalid at some point - CoreAccountSettings s; - s.setAccountValue("SSLCert", QString()); - } +void CoreConnection::sslSocketEncrypted() +{ + QSslSocket *socket = qobject_cast(sender()); + Q_ASSERT(socket); + + if (!socket->sslErrors().count()) { + // Cert is valid, so we don't want to store it as known + // That way, a warning will appear in case it becomes invalid at some point + CoreAccountSettings s; + s.setAccountValue("SSLCert", QString()); + } - emit encrypted(true); - connectionReady(); + emit encrypted(true); + connectionReady(); } -void CoreConnection::sslErrors() { - QSslSocket *socket = qobject_cast(sender()); - Q_ASSERT(socket); - CoreAccountSettings s; - QByteArray knownDigest = s.accountValue("SslCert").toByteArray(); +void CoreConnection::sslErrors() +{ + QSslSocket *socket = qobject_cast(sender()); + Q_ASSERT(socket); - if(knownDigest != socket->peerCertificate().digest()) { - bool accepted = false; - bool permanently = false; - emit handleSslErrors(socket, &accepted, &permanently); + CoreAccountSettings s; + QByteArray knownDigest = s.accountValue("SslCert").toByteArray(); - if(!accepted) { - disconnectFromCore(tr("Unencrypted connection canceled"), false); - return; - } + if (knownDigest != socket->peerCertificate().digest()) { + bool accepted = false; + bool permanently = false; + emit handleSslErrors(socket, &accepted, &permanently); - if(permanently) - s.setAccountValue("SslCert", socket->peerCertificate().digest()); - else - s.setAccountValue("SslCert", QString()); - } + if (!accepted) { + disconnectFromCore(tr("Unencrypted connection canceled"), false); + return; + } - socket->ignoreSslErrors(); + if (permanently) + s.setAccountValue("SslCert", socket->peerCertificate().digest()); + else + s.setAccountValue("SslCert", QString()); + } + + socket->ignoreSslErrors(); } + #endif /* HAVE_SSL */ -void CoreConnection::connectionReady() { - setState(Connected); - emit connectionMsg(tr("Connected to %1").arg(currentAccount().accountName())); +void CoreConnection::connectionReady() +{ + setState(Connected); + emit connectionMsg(tr("Connected to %1").arg(currentAccount().accountName())); - if(!_coreMsgBuffer["Configured"].toBool()) { - // start wizard - emit startCoreSetup(_coreMsgBuffer["StorageBackends"].toList()); - } else if(_coreMsgBuffer["LoginEnabled"].toBool()) { - loginToCore(); - } - _coreMsgBuffer.clear(); + if (!_coreMsgBuffer["Configured"].toBool()) { + // start wizard + emit startCoreSetup(_coreMsgBuffer["StorageBackends"].toList()); + } + else if (_coreMsgBuffer["LoginEnabled"].toBool()) { + loginToCore(); + } + _coreMsgBuffer.clear(); } -void CoreConnection::loginToCore(const QString &user, const QString &password, bool remember) { - _account.setUser(user); - _account.setPassword(password); - _account.setStorePassword(remember); - loginToCore(); + +void CoreConnection::loginToCore(const QString &user, const QString &password, bool remember) +{ + _account.setUser(user); + _account.setPassword(password); + _account.setStorePassword(remember); + loginToCore(); } -void CoreConnection::loginToCore(const QString &prevError) { - emit connectionMsg(tr("Logging in...")); - if(currentAccount().user().isEmpty() || currentAccount().password().isEmpty() || !prevError.isEmpty()) { - bool valid = false; - emit userAuthenticationRequired(&_account, &valid, prevError); // *must* be a synchronous call - if(!valid || currentAccount().user().isEmpty() || currentAccount().password().isEmpty()) { - disconnectFromCore(tr("Login canceled"), false); - return; + +void CoreConnection::loginToCore(const QString &prevError) +{ + emit connectionMsg(tr("Logging in...")); + if (currentAccount().user().isEmpty() || currentAccount().password().isEmpty() || !prevError.isEmpty()) { + bool valid = false; + emit userAuthenticationRequired(&_account, &valid, prevError); // *must* be a synchronous call + if (!valid || currentAccount().user().isEmpty() || currentAccount().password().isEmpty()) { + disconnectFromCore(tr("Login canceled"), false); + return; + } } - } - QVariantMap clientLogin; - clientLogin["MsgType"] = "ClientLogin"; - clientLogin["User"] = currentAccount().user(); - clientLogin["Password"] = currentAccount().password(); - SignalProxy::writeDataToDevice(_socket, clientLogin); + QVariantMap clientLogin; + clientLogin["MsgType"] = "ClientLogin"; + clientLogin["User"] = currentAccount().user(); + clientLogin["Password"] = currentAccount().password(); + SignalProxy::writeDataToDevice(_socket, clientLogin); } -void CoreConnection::loginFailed(const QString &error) { - loginToCore(error); + +void CoreConnection::loginFailed(const QString &error) +{ + loginToCore(error); } -void CoreConnection::loginSuccess() { - updateProgress(0, 0); - // save current account data - _model->createOrUpdateAccount(currentAccount()); - _model->save(); +void CoreConnection::loginSuccess() +{ + updateProgress(0, 0); - _reconnectTimer.stop(); + // save current account data + _model->createOrUpdateAccount(currentAccount()); + _model->save(); - setProgressText(tr("Receiving session state")); - setState(Synchronizing); - emit connectionMsg(tr("Synchronizing to %1...").arg(currentAccount().accountName())); + _reconnectTimer.stop(); + + setProgressText(tr("Receiving session state")); + setState(Synchronizing); + emit connectionMsg(tr("Synchronizing to %1...").arg(currentAccount().accountName())); } -void CoreConnection::sessionStateReceived(const QVariantMap &state) { - updateProgress(100, 100); - // rest of communication happens through SignalProxy... - disconnect(_socket, SIGNAL(readyRead()), this, 0); - disconnect(_socket, SIGNAL(connected()), this, 0); +void CoreConnection::sessionStateReceived(const QVariantMap &state) +{ + updateProgress(100, 100); + + // rest of communication happens through SignalProxy... + disconnect(_socket, SIGNAL(readyRead()), this, 0); + disconnect(_socket, SIGNAL(connected()), this, 0); - syncToCore(state); + syncToCore(state); } -void CoreConnection::internalSessionStateReceived(const QVariant &packedState) { - updateProgress(100, 100); - setState(Synchronizing); - syncToCore(packedState.toMap()); +void CoreConnection::internalSessionStateReceived(const QVariant &packedState) +{ + updateProgress(100, 100); + + setState(Synchronizing); + syncToCore(packedState.toMap()); } -void CoreConnection::syncToCore(const QVariantMap &sessionState) { - if(sessionState.contains("CoreFeatures")) - Client::setCoreFeatures((Quassel::Features)sessionState["CoreFeatures"].toUInt()); - setProgressText(tr("Receiving network states")); - updateProgress(0, 100); +void CoreConnection::syncToCore(const QVariantMap &sessionState) +{ + if (sessionState.contains("CoreFeatures")) + Client::setCoreFeatures((Quassel::Features)sessionState["CoreFeatures"].toUInt()); + + setProgressText(tr("Receiving network states")); + updateProgress(0, 100); - // create identities - foreach(QVariant vid, sessionState["Identities"].toList()) { - Client::instance()->coreIdentityCreated(vid.value()); - } + // create identities + foreach(QVariant vid, sessionState["Identities"].toList()) { + Client::instance()->coreIdentityCreated(vid.value()); + } - // create buffers - // FIXME: get rid of this crap -- why? - QVariantList bufferinfos = sessionState["BufferInfos"].toList(); - NetworkModel *networkModel = Client::networkModel(); - Q_ASSERT(networkModel); - foreach(QVariant vinfo, bufferinfos) + // create buffers + // FIXME: get rid of this crap -- why? + QVariantList bufferinfos = sessionState["BufferInfos"].toList(); + NetworkModel *networkModel = Client::networkModel(); + Q_ASSERT(networkModel); + foreach(QVariant vinfo, bufferinfos) networkModel->bufferUpdated(vinfo.value()); // create BufferItems - QVariantList networkids = sessionState["NetworkIds"].toList(); + QVariantList networkids = sessionState["NetworkIds"].toList(); + + // prepare sync progress thingys... + // FIXME: Care about removal of networks + _numNetsToSync = networkids.count(); + updateProgress(0, _numNetsToSync); + + // create network objects + foreach(QVariant networkid, networkids) { + NetworkId netid = networkid.value(); + if (Client::network(netid)) + continue; + Network *net = new Network(netid, Client::instance()); + _netsToSync.insert(net); + connect(net, SIGNAL(initDone()), SLOT(networkInitDone())); + connect(net, SIGNAL(destroyed()), SLOT(networkInitDone())); + Client::addNetwork(net); + } + checkSyncState(); +} - // prepare sync progress thingys... - // FIXME: Care about removal of networks - _numNetsToSync = networkids.count(); - updateProgress(0, _numNetsToSync); - // create network objects - foreach(QVariant networkid, networkids) { - NetworkId netid = networkid.value(); - if(Client::network(netid)) - continue; - Network *net = new Network(netid, Client::instance()); - _netsToSync.insert(net); - connect(net, SIGNAL(initDone()), SLOT(networkInitDone())); - connect(net, SIGNAL(destroyed()), SLOT(networkInitDone())); - Client::addNetwork(net); - } - checkSyncState(); +// this is also called for destroyed networks! +void CoreConnection::networkInitDone() +{ + QObject *net = sender(); + Q_ASSERT(net); + disconnect(net, 0, this, 0); + _netsToSync.remove(net); + updateProgress(_numNetsToSync - _netsToSync.count(), _numNetsToSync); + checkSyncState(); } -// this is also called for destroyed networks! -void CoreConnection::networkInitDone() { - QObject *net = sender(); - Q_ASSERT(net); - disconnect(net, 0, this, 0); - _netsToSync.remove(net); - updateProgress(_numNetsToSync - _netsToSync.count(), _numNetsToSync); - checkSyncState(); -} - -void CoreConnection::checkSyncState() { - if(_netsToSync.isEmpty() && state() >= Synchronizing) { - setState(Synchronized); - setProgressText(tr("Synchronized to %1").arg(currentAccount().accountName())); - setProgressMaximum(-1); - emit synchronized(); - } -} - -void CoreConnection::doCoreSetup(const QVariant &setupData) { - QVariantMap setup; - setup["MsgType"] = "CoreSetupData"; - setup["SetupData"] = setupData; - SignalProxy::writeDataToDevice(_socket, setup); + +void CoreConnection::checkSyncState() +{ + if (_netsToSync.isEmpty() && state() >= Synchronizing) { + setState(Synchronized); + setProgressText(tr("Synchronized to %1").arg(currentAccount().accountName())); + setProgressMaximum(-1); + emit synchronized(); + } +} + + +void CoreConnection::doCoreSetup(const QVariant &setupData) +{ + QVariantMap setup; + setup["MsgType"] = "CoreSetupData"; + setup["SetupData"] = setupData; + SignalProxy::writeDataToDevice(_socket, setup); } diff --git a/src/client/coreconnection.h b/src/client/coreconnection.h index 11c8d500..699a2db6 100644 --- a/src/client/coreconnection.h +++ b/src/client/coreconnection.h @@ -43,156 +43,158 @@ class CoreAccountModel; class Network; class SignalProxy; -class CoreConnection : public QObject { - Q_OBJECT +class CoreConnection : public QObject +{ + Q_OBJECT public: - enum ConnectionState { - Disconnected, - Connecting, - Connected, - Synchronizing, - Synchronized - }; + enum ConnectionState { + Disconnected, + Connecting, + Connected, + Synchronizing, + Synchronized + }; - CoreConnection(CoreAccountModel *model, QObject *parent = 0); + CoreConnection(CoreAccountModel *model, QObject *parent = 0); - void init(); + void init(); - inline bool isConnected() const; - inline ConnectionState state() const; - inline CoreAccount currentAccount() const; + inline bool isConnected() const; + inline ConnectionState state() const; + inline CoreAccount currentAccount() const; - bool isEncrypted() const; - bool isLocalConnection() const; + bool isEncrypted() const; + bool isLocalConnection() const; - inline int progressMinimum() const; - inline int progressMaximum() const; - inline int progressValue() const; - inline QString progressText() const; + inline int progressMinimum() const; + inline int progressMaximum() const; + inline int progressValue() const; + inline QString progressText() const; - //! Check if we consider the last connect as reconnect - inline bool wasReconnect() const { return _wasReconnect; } + //! Check if we consider the last connect as reconnect + inline bool wasReconnect() const { return _wasReconnect; } #ifdef HAVE_SSL - inline const QSslSocket *sslSocket() const; + inline const QSslSocket *sslSocket() const; #endif public slots: - bool connectToCore(AccountId = 0); - void reconnectToCore(); - void disconnectFromCore(); + bool connectToCore(AccountId = 0); + void reconnectToCore(); + void disconnectFromCore(); signals: - void stateChanged(CoreConnection::ConnectionState); - void encrypted(bool isEncrypted = true); - void synchronized(); - void lagUpdated(int msecs); - - void connectionError(const QString &errorMsg); - void connectionErrorPopup(const QString &errorMsg); - void connectionWarnings(const QStringList &warnings); - void connectionMsg(const QString &msg); - void disconnected(); - - void progressRangeChanged(int minimum, int maximum); - void progressValueChanged(int value); - void progressTextChanged(const QString &); - - void startCoreSetup(const QVariantList &); - void coreSetupSuccess(); - void coreSetupFailed(const QString &error); - - void startInternalCore(); - void connectToInternalCore(SignalProxy *proxy); - - // These signals MUST be handled synchronously! - void userAuthenticationRequired(CoreAccount *, bool *valid, const QString &errorMessage = QString()); - void handleNoSslInClient(bool *accepted); - void handleNoSslInCore(bool *accepted); + void stateChanged(CoreConnection::ConnectionState); + void encrypted(bool isEncrypted = true); + void synchronized(); + void lagUpdated(int msecs); + + void connectionError(const QString &errorMsg); + void connectionErrorPopup(const QString &errorMsg); + void connectionWarnings(const QStringList &warnings); + void connectionMsg(const QString &msg); + void disconnected(); + + void progressRangeChanged(int minimum, int maximum); + void progressValueChanged(int value); + void progressTextChanged(const QString &); + + void startCoreSetup(const QVariantList &); + void coreSetupSuccess(); + void coreSetupFailed(const QString &error); + + void startInternalCore(); + void connectToInternalCore(SignalProxy *proxy); + + // These signals MUST be handled synchronously! + void userAuthenticationRequired(CoreAccount *, bool *valid, const QString &errorMessage = QString()); + void handleNoSslInClient(bool *accepted); + void handleNoSslInCore(bool *accepted); #ifdef HAVE_SSL - void handleSslErrors(const QSslSocket *socket, bool *accepted, bool *permanently); + void handleSslErrors(const QSslSocket *socket, bool *accepted, bool *permanently); #endif private slots: - void connectToCurrentAccount(); - void disconnectFromCore(const QString &errorString, bool wantReconnect = true); + void connectToCurrentAccount(); + void disconnectFromCore(const QString &errorString, bool wantReconnect = true); - void socketStateChanged(QAbstractSocket::SocketState); - void coreSocketError(QAbstractSocket::SocketError); - void coreHasData(); - void coreSocketConnected(); - void coreSocketDisconnected(); + void socketStateChanged(QAbstractSocket::SocketState); + void coreSocketError(QAbstractSocket::SocketError); + void coreHasData(); + void coreSocketConnected(); + void coreSocketDisconnected(); - void clientInitAck(const QVariantMap &msg); + void clientInitAck(const QVariantMap &msg); - // for sync progress - void networkInitDone(); - void checkSyncState(); + // for sync progress + void networkInitDone(); + void checkSyncState(); - void syncToCore(const QVariantMap &sessionState); - void internalSessionStateReceived(const QVariant &packedState); - void sessionStateReceived(const QVariantMap &state); + void syncToCore(const QVariantMap &sessionState); + void internalSessionStateReceived(const QVariant &packedState); + void sessionStateReceived(const QVariantMap &state); - void resetConnection(bool wantReconnect = false); - void connectionReady(); + void resetConnection(bool wantReconnect = false); + void connectionReady(); - void loginToCore(const QString &user, const QString &password, bool remember); // for config wizard - void loginToCore(const QString &previousError = QString()); - void loginSuccess(); - void loginFailed(const QString &errorMessage); + void loginToCore(const QString &user, const QString &password, bool remember); // for config wizard + void loginToCore(const QString &previousError = QString()); + void loginSuccess(); + void loginFailed(const QString &errorMessage); - void doCoreSetup(const QVariant &setupData); + void doCoreSetup(const QVariant &setupData); - void updateProgress(int value, int maximum); - void setProgressText(const QString &text); - void setProgressValue(int value); - void setProgressMinimum(int minimum); - void setProgressMaximum(int maximum); + void updateProgress(int value, int maximum); + void setProgressText(const QString &text); + void setProgressValue(int value); + void setProgressMinimum(int minimum); + void setProgressMaximum(int maximum); - void setState(QAbstractSocket::SocketState socketState); - void setState(ConnectionState state); + void setState(QAbstractSocket::SocketState socketState); + void setState(ConnectionState state); #ifdef HAVE_SSL - void sslSocketEncrypted(); - void sslErrors(); + void sslSocketEncrypted(); + void sslErrors(); #endif - void networkDetectionModeChanged(const QVariant &mode); - void pingTimeoutIntervalChanged(const QVariant &interval); - void reconnectIntervalChanged(const QVariant &interval); - void reconnectTimeout(); + void networkDetectionModeChanged(const QVariant &mode); + void pingTimeoutIntervalChanged(const QVariant &interval); + void reconnectIntervalChanged(const QVariant &interval); + void reconnectTimeout(); #ifdef HAVE_KDE - void solidNetworkStatusChanged(Solid::Networking::Status status); + void solidNetworkStatusChanged(Solid::Networking::Status status); #endif private: - CoreAccountModel *_model; - CoreAccount _account; - QVariantMap _coreMsgBuffer; + CoreAccountModel *_model; + CoreAccount _account; + QVariantMap _coreMsgBuffer; - QPointer _socket; - quint32 _blockSize; - ConnectionState _state; + QPointer _socket; + quint32 _blockSize; + ConnectionState _state; - QTimer _reconnectTimer; - bool _wantReconnect; + QTimer _reconnectTimer; + bool _wantReconnect; - QSet _netsToSync; - int _numNetsToSync; - int _progressMinimum, _progressMaximum, _progressValue; - QString _progressText; + QSet _netsToSync; + int _numNetsToSync; + int _progressMinimum, _progressMaximum, _progressValue; + QString _progressText; - QString _coreInfoString(const QVariantMap &); - bool _wasReconnect; - bool _requestedDisconnect; + QString _coreInfoString(const QVariantMap &); + bool _wasReconnect; + bool _requestedDisconnect; - inline CoreAccountModel *accountModel() const; + inline CoreAccountModel *accountModel() const; - friend class CoreConfigWizard; + friend class CoreConfigWizard; }; + Q_DECLARE_METATYPE(CoreConnection::ConnectionState) // Inlines diff --git a/src/client/execwrapper.cpp b/src/client/execwrapper.cpp index e04e0946..7c9ce12d 100644 --- a/src/client/execwrapper.cpp +++ b/src/client/execwrapper.cpp @@ -27,101 +27,117 @@ #include "messagemodel.h" #include "quassel.h" -ExecWrapper::ExecWrapper(QObject* parent) : QObject(parent) { - connect(&_process, SIGNAL(readyReadStandardOutput()), SLOT(processReadStdout())); - connect(&_process, SIGNAL(readyReadStandardError()), SLOT(processReadStderr())); - connect(&_process, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(processFinished(int, QProcess::ExitStatus))); - connect(&_process, SIGNAL(error(QProcess::ProcessError)), SLOT(processError(QProcess::ProcessError))); - - connect(this, SIGNAL(output(QString)), SLOT(postStdout(QString))); - connect(this, SIGNAL(error(QString)), SLOT(postStderr(QString))); +ExecWrapper::ExecWrapper(QObject *parent) : QObject(parent) +{ + connect(&_process, SIGNAL(readyReadStandardOutput()), SLOT(processReadStdout())); + connect(&_process, SIGNAL(readyReadStandardError()), SLOT(processReadStderr())); + connect(&_process, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(processFinished(int, QProcess::ExitStatus))); + connect(&_process, SIGNAL(error(QProcess::ProcessError)), SLOT(processError(QProcess::ProcessError))); + + connect(this, SIGNAL(output(QString)), SLOT(postStdout(QString))); + connect(this, SIGNAL(error(QString)), SLOT(postStderr(QString))); } -void ExecWrapper::start(const BufferInfo &info, const QString &command) { - _bufferInfo = info; - QString params; - - QRegExp rx("^\\s*(\\S+)(\\s+(.*))?$"); - if(!rx.exactMatch(command)) { - emit error(tr("Invalid command string for /exec: %1").arg(command)); - } else { - _scriptName = rx.cap(1); - params = rx.cap(3); - } - - // Make sure we don't execute something outside a script dir - if(_scriptName.contains("../") || _scriptName.contains("..\\")) - emit error(tr("Name \"%1\" is invalid: ../ or ..\\ are not allowed!").arg(_scriptName)); - - else { - foreach(QString scriptDir, Quassel::scriptDirPaths()) { - QString fileName = scriptDir + _scriptName; - if(!QFile::exists(fileName)) - continue; - _process.setWorkingDirectory(scriptDir); - _process.start('"' + fileName + "\" " + params); - return; + +void ExecWrapper::start(const BufferInfo &info, const QString &command) +{ + _bufferInfo = info; + QString params; + + QRegExp rx("^\\s*(\\S+)(\\s+(.*))?$"); + if (!rx.exactMatch(command)) { + emit error(tr("Invalid command string for /exec: %1").arg(command)); + } + else { + _scriptName = rx.cap(1); + params = rx.cap(3); + } + + // Make sure we don't execute something outside a script dir + if (_scriptName.contains("../") || _scriptName.contains("..\\")) + emit error(tr("Name \"%1\" is invalid: ../ or ..\\ are not allowed!").arg(_scriptName)); + + else { + foreach(QString scriptDir, Quassel::scriptDirPaths()) { + QString fileName = scriptDir + _scriptName; + if (!QFile::exists(fileName)) + continue; + _process.setWorkingDirectory(scriptDir); + _process.start('"' + fileName + "\" " + params); + return; + } + emit error(tr("Could not find script \"%1\"").arg(_scriptName)); } - emit error(tr("Could not find script \"%1\"").arg(_scriptName)); - } - deleteLater(); // self-destruct + deleteLater(); // self-destruct } -void ExecWrapper::postStdout(const QString &msg) { - if(_bufferInfo.isValid()) - Client::userInput(_bufferInfo, msg); + +void ExecWrapper::postStdout(const QString &msg) +{ + if (_bufferInfo.isValid()) + Client::userInput(_bufferInfo, msg); } -void ExecWrapper::postStderr(const QString &msg) { - if(_bufferInfo.isValid()) - Client::messageModel()->insertErrorMessage(_bufferInfo, msg); + +void ExecWrapper::postStderr(const QString &msg) +{ + if (_bufferInfo.isValid()) + Client::messageModel()->insertErrorMessage(_bufferInfo, msg); } -void ExecWrapper::processFinished(int exitCode, QProcess::ExitStatus status) { - if(status == QProcess::CrashExit) { - emit error(tr("Script \"%1\" crashed with exit code %2.").arg(_scriptName).arg(exitCode)); - } - // empty buffers - if(!_stdoutBuffer.isEmpty()) - foreach(QString msg, _stdoutBuffer.split('\n')) - emit output(msg); - if(!_stderrBuffer.isEmpty()) - foreach(QString msg, _stderrBuffer.split('\n')) - emit error(msg); +void ExecWrapper::processFinished(int exitCode, QProcess::ExitStatus status) +{ + if (status == QProcess::CrashExit) { + emit error(tr("Script \"%1\" crashed with exit code %2.").arg(_scriptName).arg(exitCode)); + } + + // empty buffers + if (!_stdoutBuffer.isEmpty()) + foreach(QString msg, _stdoutBuffer.split('\n')) + emit output(msg); + if (!_stderrBuffer.isEmpty()) + foreach(QString msg, _stderrBuffer.split('\n')) + emit error(msg); - deleteLater(); + deleteLater(); } -void ExecWrapper::processError(QProcess::ProcessError err) { - if(err == QProcess::FailedToStart) - emit error(tr("Script \"%1\" could not start.").arg(_scriptName)); - else - emit error(tr("Script \"%1\" caused error %2.").arg(_scriptName).arg(err)); - if(_process.state() != QProcess::Running) - deleteLater(); +void ExecWrapper::processError(QProcess::ProcessError err) +{ + if (err == QProcess::FailedToStart) + emit error(tr("Script \"%1\" could not start.").arg(_scriptName)); + else + emit error(tr("Script \"%1\" caused error %2.").arg(_scriptName).arg(err)); + + if (_process.state() != QProcess::Running) + deleteLater(); } -void ExecWrapper::processReadStdout() { - QString str = QTextCodec::codecForLocale()->toUnicode(_process.readAllStandardOutput()); - str.replace(QRegExp("\r\n?"), "\n"); - _stdoutBuffer.append(str); - int idx; - while((idx = _stdoutBuffer.indexOf('\n')) >= 0) { - emit output(_stdoutBuffer.left(idx)); - _stdoutBuffer = _stdoutBuffer.mid(idx + 1); - } + +void ExecWrapper::processReadStdout() +{ + QString str = QTextCodec::codecForLocale()->toUnicode(_process.readAllStandardOutput()); + str.replace(QRegExp("\r\n?"), "\n"); + _stdoutBuffer.append(str); + int idx; + while ((idx = _stdoutBuffer.indexOf('\n')) >= 0) { + emit output(_stdoutBuffer.left(idx)); + _stdoutBuffer = _stdoutBuffer.mid(idx + 1); + } } -void ExecWrapper::processReadStderr() { - QString str = QTextCodec::codecForLocale()->toUnicode(_process.readAllStandardError()); - str.replace(QRegExp("\r\n?"), "\n"); - _stderrBuffer.append(str); - int idx; - while((idx = _stderrBuffer.indexOf('\n')) >= 0) { - emit error(_stderrBuffer.left(idx)); - _stderrBuffer = _stderrBuffer.mid(idx + 1); - } + +void ExecWrapper::processReadStderr() +{ + QString str = QTextCodec::codecForLocale()->toUnicode(_process.readAllStandardError()); + str.replace(QRegExp("\r\n?"), "\n"); + _stderrBuffer.append(str); + int idx; + while ((idx = _stderrBuffer.indexOf('\n')) >= 0) { + emit error(_stderrBuffer.left(idx)); + _stderrBuffer = _stderrBuffer.mid(idx + 1); + } } diff --git a/src/client/execwrapper.h b/src/client/execwrapper.h index e6d6dce0..b6106fde 100644 --- a/src/client/execwrapper.h +++ b/src/client/execwrapper.h @@ -25,34 +25,36 @@ #include "bufferinfo.h" -class ExecWrapper : public QObject { - Q_OBJECT +class ExecWrapper : public QObject +{ + Q_OBJECT public: - ExecWrapper(QObject *parent = 0); + ExecWrapper(QObject *parent = 0); public slots: - void start(const BufferInfo &info, const QString &command); + void start(const BufferInfo &info, const QString &command); signals: - void error(const QString &errorMsg); - void output(const QString &out); + void error(const QString &errorMsg); + void output(const QString &out); private slots: - void processReadStdout(); - void processReadStderr(); - void processFinished(int exitCode, QProcess::ExitStatus exitStatus); - void processError(QProcess::ProcessError); + void processReadStdout(); + void processReadStderr(); + void processFinished(int exitCode, QProcess::ExitStatus exitStatus); + void processError(QProcess::ProcessError); - void postStdout(const QString &); - void postStderr(const QString &); + void postStdout(const QString &); + void postStderr(const QString &); private: - QProcess _process; - BufferInfo _bufferInfo; - QString _scriptName; - QString _stdoutBuffer; - QString _stderrBuffer; + QProcess _process; + BufferInfo _bufferInfo; + QString _scriptName; + QString _stdoutBuffer; + QString _stderrBuffer; }; + #endif diff --git a/src/client/irclistmodel.cpp b/src/client/irclistmodel.cpp index 83dd7c16..baf9d42d 100644 --- a/src/client/irclistmodel.cpp +++ b/src/client/irclistmodel.cpp @@ -23,67 +23,77 @@ #include IrcListModel::IrcListModel(QObject *parent) - : QAbstractItemModel(parent) + : QAbstractItemModel(parent) { } -QVariant IrcListModel::data(const QModelIndex &index, int role) const { - if(!index.isValid() || index.row() >= rowCount() || index.column() >= columnCount() || role != Qt::DisplayRole) - return QVariant(); - IrcListHelper::ChannelDescription channel = _channelList[index.row()]; +QVariant IrcListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() >= rowCount() || index.column() >= columnCount() || role != Qt::DisplayRole) + return QVariant(); + + IrcListHelper::ChannelDescription channel = _channelList[index.row()]; - switch(index.column()) { - case 0: - return channel.channelName; - case 1: - return channel.userCount; - case 2: - return channel.topic; - default: - return QVariant(); - } + switch (index.column()) { + case 0: + return channel.channelName; + case 1: + return channel.userCount; + case 2: + return channel.topic; + default: + return QVariant(); + } } -Qt::ItemFlags IrcListModel::flags(const QModelIndex &index) const { - if(!index.isValid()) { - return Qt::ItemIsDropEnabled; - } else { - return Qt::ItemIsSelectable | Qt::ItemIsEnabled; - } + +Qt::ItemFlags IrcListModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) { + return Qt::ItemIsDropEnabled; + } + else { + return Qt::ItemIsSelectable | Qt::ItemIsEnabled; + } } -QVariant IrcListModel::headerData(int section, Qt::Orientation orientation, int role) const { - QStringList header; - header << tr("Channel") - << tr("Users") - << tr("Topic"); - - if(orientation == Qt::Horizontal && role == Qt::DisplayRole) - return header[section]; +QVariant IrcListModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + QStringList header; + header << tr("Channel") + << tr("Users") + << tr("Topic"); + + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) + return header[section]; - return QVariant(); + return QVariant(); } -QModelIndex IrcListModel::index(int row, int column, const QModelIndex &parent) const { - Q_UNUSED(parent); - if(row >= rowCount() || column >= columnCount()) - return QModelIndex(); - return createIndex(row, column); +QModelIndex IrcListModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + if (row >= rowCount() || column >= columnCount()) + return QModelIndex(); + + return createIndex(row, column); } -void IrcListModel::setChannelList(const QList &channelList) { - if(rowCount() > 0) { - beginRemoveRows(QModelIndex(), 0, _channelList.count() - 1); - _channelList.clear(); - endRemoveRows(); - } - - if(channelList.count() > 0) { - beginInsertRows(QModelIndex(), 0, channelList.count() - 1); - _channelList = channelList; - endInsertRows(); - } + +void IrcListModel::setChannelList(const QList &channelList) +{ + if (rowCount() > 0) { + beginRemoveRows(QModelIndex(), 0, _channelList.count() - 1); + _channelList.clear(); + endRemoveRows(); + } + + if (channelList.count() > 0) { + beginInsertRows(QModelIndex(), 0, channelList.count() - 1); + _channelList = channelList; + endInsertRows(); + } } diff --git a/src/client/irclistmodel.h b/src/client/irclistmodel.h index d8d99276..287dca07 100644 --- a/src/client/irclistmodel.h +++ b/src/client/irclistmodel.h @@ -25,29 +25,31 @@ #include -class IrcListModel : public QAbstractItemModel { - Q_OBJECT +class IrcListModel : public QAbstractItemModel +{ + Q_OBJECT public: - IrcListModel(QObject *parent = 0); + IrcListModel(QObject *parent = 0); - virtual QVariant data(const QModelIndex &index, int role) const; - virtual Qt::ItemFlags flags(const QModelIndex &index) const; + virtual QVariant data(const QModelIndex &index, int role) const; + virtual Qt::ItemFlags flags(const QModelIndex &index) const; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; - inline QModelIndex parent(const QModelIndex &) const { return QModelIndex(); } + inline QModelIndex parent(const QModelIndex &) const { return QModelIndex(); } - inline int rowCount(const QModelIndex &parent = QModelIndex()) const { Q_UNUSED(parent) return _channelList.count(); } - inline int columnCount(const QModelIndex &parent = QModelIndex()) const { Q_UNUSED(parent) return 3; } + inline int rowCount(const QModelIndex &parent = QModelIndex()) const { Q_UNUSED(parent) return _channelList.count(); } + inline int columnCount(const QModelIndex &parent = QModelIndex()) const { Q_UNUSED(parent) return 3; } public slots: - void setChannelList(const QList &channelList = QList()); + void setChannelList(const QList &channelList = QList()); private: - QList _channelList; + QList _channelList; }; + #endif //IRCLISTMODEL_H diff --git a/src/client/messagefilter.cpp b/src/client/messagefilter.cpp index 55f609c7..526145f1 100644 --- a/src/client/messagefilter.cpp +++ b/src/client/messagefilter.cpp @@ -28,205 +28,219 @@ #include "clientignorelistmanager.h" MessageFilter::MessageFilter(QAbstractItemModel *source, QObject *parent) - : QSortFilterProxyModel(parent), + : QSortFilterProxyModel(parent), _messageTypeFilter(0) { - init(); - setSourceModel(source); + init(); + setSourceModel(source); } + MessageFilter::MessageFilter(MessageModel *source, const QList &buffers, QObject *parent) - : QSortFilterProxyModel(parent), + : QSortFilterProxyModel(parent), _validBuffers(buffers.toSet()), _messageTypeFilter(0) { - init(); - setSourceModel(source); + init(); + setSourceModel(source); } -void MessageFilter::init() { - setDynamicSortFilter(true); - _userNoticesTarget = _serverNoticesTarget = _errorMsgsTarget = -1; +void MessageFilter::init() +{ + setDynamicSortFilter(true); + + _userNoticesTarget = _serverNoticesTarget = _errorMsgsTarget = -1; - BufferSettings defaultSettings; - defaultSettings.notify("UserNoticesTarget", this, SLOT(messageRedirectionChanged())); - defaultSettings.notify("ServerNoticesTarget", this, SLOT(messageRedirectionChanged())); - defaultSettings.notify("ErrorMsgsTarget", this, SLOT(messageRedirectionChanged())); - messageRedirectionChanged(); + BufferSettings defaultSettings; + defaultSettings.notify("UserNoticesTarget", this, SLOT(messageRedirectionChanged())); + defaultSettings.notify("ServerNoticesTarget", this, SLOT(messageRedirectionChanged())); + defaultSettings.notify("ErrorMsgsTarget", this, SLOT(messageRedirectionChanged())); + messageRedirectionChanged(); - _messageTypeFilter = defaultSettings.messageFilter(); - defaultSettings.notify("MessageTypeFilter", this, SLOT(messageTypeFilterChanged())); + _messageTypeFilter = defaultSettings.messageFilter(); + defaultSettings.notify("MessageTypeFilter", this, SLOT(messageTypeFilterChanged())); - BufferSettings mySettings(idString()); - if(mySettings.hasFilter()) - _messageTypeFilter = mySettings.messageFilter(); - mySettings.notify("MessageTypeFilter", this, SLOT(messageTypeFilterChanged())); - mySettings.notify("hasMessageTypeFilter", this, SLOT(messageTypeFilterChanged())); + BufferSettings mySettings(idString()); + if (mySettings.hasFilter()) + _messageTypeFilter = mySettings.messageFilter(); + mySettings.notify("MessageTypeFilter", this, SLOT(messageTypeFilterChanged())); + mySettings.notify("hasMessageTypeFilter", this, SLOT(messageTypeFilterChanged())); } -void MessageFilter::messageTypeFilterChanged() { - int newFilter; - BufferSettings defaultSettings; - newFilter = BufferSettings().messageFilter(); - - BufferSettings mySettings(idString()); - if(mySettings.hasFilter()) - newFilter = mySettings.messageFilter(); - if(_messageTypeFilter != newFilter) { - _messageTypeFilter = newFilter; - _filteredQuitMsgs.clear(); - invalidateFilter(); - } +void MessageFilter::messageTypeFilterChanged() +{ + int newFilter; + BufferSettings defaultSettings; + newFilter = BufferSettings().messageFilter(); + + BufferSettings mySettings(idString()); + if (mySettings.hasFilter()) + newFilter = mySettings.messageFilter(); + + if (_messageTypeFilter != newFilter) { + _messageTypeFilter = newFilter; + _filteredQuitMsgs.clear(); + invalidateFilter(); + } } -void MessageFilter::messageRedirectionChanged() { - BufferSettings bufferSettings; - bool changed = false; - if(_userNoticesTarget != bufferSettings.userNoticesTarget()) { - _userNoticesTarget = bufferSettings.userNoticesTarget(); - changed = true; - } +void MessageFilter::messageRedirectionChanged() +{ + BufferSettings bufferSettings; + bool changed = false; - if(_serverNoticesTarget != bufferSettings.serverNoticesTarget()) { - _serverNoticesTarget = bufferSettings.serverNoticesTarget(); - changed = true; - } + if (_userNoticesTarget != bufferSettings.userNoticesTarget()) { + _userNoticesTarget = bufferSettings.userNoticesTarget(); + changed = true; + } - if(_errorMsgsTarget != bufferSettings.errorMsgsTarget()) { - _errorMsgsTarget = bufferSettings.errorMsgsTarget(); - changed = true; - } + if (_serverNoticesTarget != bufferSettings.serverNoticesTarget()) { + _serverNoticesTarget = bufferSettings.serverNoticesTarget(); + changed = true; + } + + if (_errorMsgsTarget != bufferSettings.errorMsgsTarget()) { + _errorMsgsTarget = bufferSettings.errorMsgsTarget(); + changed = true; + } - if(changed) - invalidateFilter(); + if (changed) + invalidateFilter(); } -QString MessageFilter::idString() const { - if(_validBuffers.isEmpty()) - return "*"; - QList bufferIds = _validBuffers.toList(); - qSort(bufferIds); +QString MessageFilter::idString() const +{ + if (_validBuffers.isEmpty()) + return "*"; - QStringList bufferIdStrings; - foreach(BufferId id, bufferIds) + QList bufferIds = _validBuffers.toList(); + qSort(bufferIds); + + QStringList bufferIdStrings; + foreach(BufferId id, bufferIds) bufferIdStrings << QString::number(id.toInt()); - return bufferIdStrings.join("|"); + return bufferIdStrings.join("|"); } -bool MessageFilter::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { - Q_UNUSED(sourceParent); - QModelIndex sourceIdx = sourceModel()->index(sourceRow, 2); - Message::Type messageType = (Message::Type)sourceIdx.data(MessageModel::TypeRole).toInt(); - - // apply message type filter - if(_messageTypeFilter & messageType) - return false; - - if(_validBuffers.isEmpty()) - return true; - - BufferId bufferId = sourceIdx.data(MessageModel::BufferIdRole).value(); - if(!bufferId.isValid()) { - return true; - } - - // MsgId msgId = sourceIdx.data(MessageModel::MsgIdRole).value(); - Message::Flags flags = (Message::Flags)sourceIdx.data(MessageModel::FlagsRole).toInt(); - - NetworkId myNetworkId = networkId(); - NetworkId msgNetworkId = Client::networkModel()->networkId(bufferId); - if(myNetworkId != msgNetworkId) - return false; - - // ignorelist handling - // only match if message is not flagged as server msg - if(!(flags & Message::ServerMsg) && Client::ignoreListManager() - && Client::ignoreListManager()->match(sourceIdx.data(MessageModel::MessageRole).value(), Client::networkModel()->networkName(bufferId))) - return false; - - if(flags & Message::Redirected) { - int redirectionTarget = 0; - switch(messageType) { - case Message::Notice: - if(Client::networkModel()->bufferType(bufferId) != BufferInfo::ChannelBuffer) { - if(flags & Message::ServerMsg) { - // server notice - redirectionTarget = _serverNoticesTarget; - } else { - redirectionTarget = _userNoticesTarget; - } - } - break; - case Message::Error: - redirectionTarget = _errorMsgsTarget; - break; - default: - break; - } - if(redirectionTarget & BufferSettings::DefaultBuffer && _validBuffers.contains(bufferId)) - return true; +bool MessageFilter::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +{ + Q_UNUSED(sourceParent); + QModelIndex sourceIdx = sourceModel()->index(sourceRow, 2); + Message::Type messageType = (Message::Type)sourceIdx.data(MessageModel::TypeRole).toInt(); - if(redirectionTarget & BufferSettings::CurrentBuffer && !(flags & Message::Backlog)) { - BufferId redirectedTo = sourceModel()->data(sourceIdx, MessageModel::RedirectedToRole).value(); - if(!redirectedTo.isValid()) { - BufferId redirectedTo = Client::bufferModel()->currentIndex().data(NetworkModel::BufferIdRole).value(); - if(redirectedTo.isValid()) - sourceModel()->setData(sourceIdx, QVariant::fromValue(redirectedTo), MessageModel::RedirectedToRole); - } + // apply message type filter + if (_messageTypeFilter & messageType) + return false; - if(_validBuffers.contains(redirectedTo)) + if (_validBuffers.isEmpty()) return true; - } - if(redirectionTarget & BufferSettings::StatusBuffer) { - QSet::const_iterator idIter = _validBuffers.constBegin(); - while(idIter != _validBuffers.constEnd()) { - if(Client::networkModel()->bufferType(*idIter) == BufferInfo::StatusBuffer) - return true; - idIter++; - } + BufferId bufferId = sourceIdx.data(MessageModel::BufferIdRole).value(); + if (!bufferId.isValid()) { + return true; } - return false; - } + // MsgId msgId = sourceIdx.data(MessageModel::MsgIdRole).value(); + Message::Flags flags = (Message::Flags)sourceIdx.data(MessageModel::FlagsRole).toInt(); + + NetworkId myNetworkId = networkId(); + NetworkId msgNetworkId = Client::networkModel()->networkId(bufferId); + if (myNetworkId != msgNetworkId) + return false; + + // ignorelist handling + // only match if message is not flagged as server msg + if (!(flags & Message::ServerMsg) && Client::ignoreListManager() + && Client::ignoreListManager()->match(sourceIdx.data(MessageModel::MessageRole).value(), Client::networkModel()->networkName(bufferId))) + return false; + + if (flags & Message::Redirected) { + int redirectionTarget = 0; + switch (messageType) { + case Message::Notice: + if (Client::networkModel()->bufferType(bufferId) != BufferInfo::ChannelBuffer) { + if (flags & Message::ServerMsg) { + // server notice + redirectionTarget = _serverNoticesTarget; + } + else { + redirectionTarget = _userNoticesTarget; + } + } + break; + case Message::Error: + redirectionTarget = _errorMsgsTarget; + break; + default: + break; + } + if (redirectionTarget & BufferSettings::DefaultBuffer && _validBuffers.contains(bufferId)) + return true; - if(_validBuffers.contains(bufferId)) { - return true; - } else { - // show Quit messages in Query buffers: - if(bufferType() != BufferInfo::QueryBuffer) - return false; - if(!(messageType & Message::Quit)) - return false; + if (redirectionTarget & BufferSettings::CurrentBuffer && !(flags & Message::Backlog)) { + BufferId redirectedTo = sourceModel()->data(sourceIdx, MessageModel::RedirectedToRole).value(); + if (!redirectedTo.isValid()) { + BufferId redirectedTo = Client::bufferModel()->currentIndex().data(NetworkModel::BufferIdRole).value(); + if (redirectedTo.isValid()) + sourceModel()->setData(sourceIdx, QVariant::fromValue(redirectedTo), MessageModel::RedirectedToRole); + } - if(myNetworkId != msgNetworkId) - return false; + if (_validBuffers.contains(redirectedTo)) + return true; + } - uint messageTimestamp = sourceModel()->data(sourceIdx, MessageModel::TimestampRole).value().toTime_t(); - QString quiter = sourceModel()->data(sourceIdx, Qt::DisplayRole).toString().section(' ', 0, 0, QString::SectionSkipEmpty).toLower(); - if(quiter != bufferName().toLower()) - return false; + if (redirectionTarget & BufferSettings::StatusBuffer) { + QSet::const_iterator idIter = _validBuffers.constBegin(); + while (idIter != _validBuffers.constEnd()) { + if (Client::networkModel()->bufferType(*idIter) == BufferInfo::StatusBuffer) + return true; + idIter++; + } + } - if(_filteredQuitMsgs.contains(quiter, messageTimestamp)) - return false; + return false; + } - MessageFilter *that = const_cast(this); - that->_filteredQuitMsgs.insert(quiter, messageTimestamp); - return true; - } + if (_validBuffers.contains(bufferId)) { + return true; + } + else { + // show Quit messages in Query buffers: + if (bufferType() != BufferInfo::QueryBuffer) + return false; + if (!(messageType & Message::Quit)) + return false; + + if (myNetworkId != msgNetworkId) + return false; + + uint messageTimestamp = sourceModel()->data(sourceIdx, MessageModel::TimestampRole).value().toTime_t(); + QString quiter = sourceModel()->data(sourceIdx, Qt::DisplayRole).toString().section(' ', 0, 0, QString::SectionSkipEmpty).toLower(); + if (quiter != bufferName().toLower()) + return false; + + if (_filteredQuitMsgs.contains(quiter, messageTimestamp)) + return false; + + MessageFilter *that = const_cast(this); + that->_filteredQuitMsgs.insert(quiter, messageTimestamp); + return true; + } } -void MessageFilter::requestBacklog() { - QSet::const_iterator bufferIdIter = _validBuffers.constBegin(); - while(bufferIdIter != _validBuffers.constEnd()) { - Client::messageModel()->requestBacklog(*bufferIdIter); - bufferIdIter++; - } + +void MessageFilter::requestBacklog() +{ + QSet::const_iterator bufferIdIter = _validBuffers.constBegin(); + while (bufferIdIter != _validBuffers.constEnd()) { + Client::messageModel()->requestBacklog(*bufferIdIter); + bufferIdIter++; + } } diff --git a/src/client/messagefilter.h b/src/client/messagefilter.h index f8e85a55..5354feb0 100644 --- a/src/client/messagefilter.h +++ b/src/client/messagefilter.h @@ -29,44 +29,46 @@ #include "networkmodel.h" #include "types.h" -class MessageFilter : public QSortFilterProxyModel { - Q_OBJECT +class MessageFilter : public QSortFilterProxyModel +{ + Q_OBJECT protected: - MessageFilter(QAbstractItemModel *source, QObject *parent = 0); + MessageFilter(QAbstractItemModel *source, QObject *parent = 0); public: - MessageFilter(MessageModel *, const QList &buffers = QList(), QObject *parent = 0); + MessageFilter(MessageModel *, const QList &buffers = QList(), QObject *parent = 0); - virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; - virtual QString idString() const; - inline bool isSingleBufferFilter() const { return _validBuffers.count() == 1; } - BufferId singleBufferId() const { return *(_validBuffers.constBegin()); } - inline bool containsBuffer(const BufferId &id) const { return _validBuffers.contains(id); } - inline QSet containedBuffers() const { return _validBuffers; } + virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; + virtual QString idString() const; + inline bool isSingleBufferFilter() const { return _validBuffers.count() == 1; } + BufferId singleBufferId() const { return *(_validBuffers.constBegin()); } + inline bool containsBuffer(const BufferId &id) const { return _validBuffers.contains(id); } + inline QSet containedBuffers() const { return _validBuffers; } public slots: - void messageTypeFilterChanged(); - void messageRedirectionChanged(); - void requestBacklog(); - // redefined as public slot - void invalidateFilter() { QSortFilterProxyModel::invalidateFilter(); } + void messageTypeFilterChanged(); + void messageRedirectionChanged(); + void requestBacklog(); + // redefined as public slot + void invalidateFilter() { QSortFilterProxyModel::invalidateFilter(); } protected: - QString bufferName() const { return Client::networkModel()->bufferName(singleBufferId()); } - BufferInfo::Type bufferType() const { return Client::networkModel()->bufferType(singleBufferId()); } - NetworkId networkId() const { return Client::networkModel()->networkId(singleBufferId()); } + QString bufferName() const { return Client::networkModel()->bufferName(singleBufferId()); } + BufferInfo::Type bufferType() const { return Client::networkModel()->bufferType(singleBufferId()); } + NetworkId networkId() const { return Client::networkModel()->networkId(singleBufferId()); } private: - void init(); + void init(); - QSet _validBuffers; - QMultiHash _filteredQuitMsgs; - int _messageTypeFilter; + QSet _validBuffers; + QMultiHash _filteredQuitMsgs; + int _messageTypeFilter; - int _userNoticesTarget; - int _serverNoticesTarget; - int _errorMsgsTarget; + int _userNoticesTarget; + int _serverNoticesTarget; + int _errorMsgsTarget; }; + #endif diff --git a/src/client/messagemodel.cpp b/src/client/messagemodel.cpp index 0cc31a18..54985662 100644 --- a/src/client/messagemodel.cpp +++ b/src/client/messagemodel.cpp @@ -28,434 +28,489 @@ #include "message.h" #include "networkmodel.h" -class ProcessBufferEvent : public QEvent { +class ProcessBufferEvent : public QEvent +{ public: - inline ProcessBufferEvent() : QEvent(QEvent::User) {} + inline ProcessBufferEvent() : QEvent(QEvent::User) {} }; + MessageModel::MessageModel(QObject *parent) - : QAbstractItemModel(parent) + : QAbstractItemModel(parent) { - QDateTime now = QDateTime::currentDateTime(); - now.setTimeSpec(Qt::UTC); - _nextDayChange.setTimeSpec(Qt::UTC); - _nextDayChange.setTime_t(((now.toTime_t() / 86400) + 1) * 86400); - _nextDayChange.setTimeSpec(Qt::LocalTime); - _dayChangeTimer.setInterval(QDateTime::currentDateTime().secsTo(_nextDayChange) * 1000); - _dayChangeTimer.start(); - connect(&_dayChangeTimer, SIGNAL(timeout()), this, SLOT(changeOfDay())); + QDateTime now = QDateTime::currentDateTime(); + now.setTimeSpec(Qt::UTC); + _nextDayChange.setTimeSpec(Qt::UTC); + _nextDayChange.setTime_t(((now.toTime_t() / 86400) + 1) * 86400); + _nextDayChange.setTimeSpec(Qt::LocalTime); + _dayChangeTimer.setInterval(QDateTime::currentDateTime().secsTo(_nextDayChange) * 1000); + _dayChangeTimer.start(); + connect(&_dayChangeTimer, SIGNAL(timeout()), this, SLOT(changeOfDay())); } -QVariant MessageModel::data(const QModelIndex &index, int role) const { - int row = index.row(); int column = index.column(); - if(row < 0 || row >= messageCount() || column < 0) - return QVariant(); - if(role == ColumnTypeRole) - return column; +QVariant MessageModel::data(const QModelIndex &index, int role) const +{ + int row = index.row(); int column = index.column(); + if (row < 0 || row >= messageCount() || column < 0) + return QVariant(); - return messageItemAt(row)->data(index.column(), role); - // return _messageList[row]->data(index.column(), role); + if (role == ColumnTypeRole) + return column; + + return messageItemAt(row)->data(index.column(), role); + // return _messageList[row]->data(index.column(), role); } -bool MessageModel::setData(const QModelIndex &index, const QVariant &value, int role) { - int row = index.row(); - if(row < 0 || row >= messageCount()) - return false; - if(messageItemAt(row)->setData(index.column(), value, role)) { - emit dataChanged(index, index); - return true; - } - return false; +bool MessageModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + int row = index.row(); + if (row < 0 || row >= messageCount()) + return false; + + if (messageItemAt(row)->setData(index.column(), value, role)) { + emit dataChanged(index, index); + return true; + } + return false; } -bool MessageModel::insertMessage(const Message &msg, bool fakeMsg) { - MsgId id = msg.msgId(); - int idx = indexForId(id); - if(!fakeMsg && idx < messageCount()) { // check for duplicate - if(messageItemAt(idx)->msgId() == id) - return false; - } - insertMessageGroup(QList() << msg); - return true; +bool MessageModel::insertMessage(const Message &msg, bool fakeMsg) +{ + MsgId id = msg.msgId(); + int idx = indexForId(id); + if (!fakeMsg && idx < messageCount()) { // check for duplicate + if (messageItemAt(idx)->msgId() == id) + return false; + } + + insertMessageGroup(QList() << msg); + return true; } -void MessageModel::insertMessages(const QList &msglist) { - if(msglist.isEmpty()) - return; - - if(_messageBuffer.isEmpty()) { - int processedMsgs = insertMessagesGracefully(msglist); - int remainingMsgs = msglist.count() - processedMsgs; - if(remainingMsgs > 0) { - if(msglist.first().msgId() < msglist.last().msgId()) { - // in Order - we have just successfully processed "processedMsg" messages from the end of the list - _messageBuffer = msglist.mid(0, remainingMsgs); - } else { - _messageBuffer = msglist.mid(processedMsgs); - } - qSort(_messageBuffer); - QCoreApplication::postEvent(this, new ProcessBufferEvent()); + +void MessageModel::insertMessages(const QList &msglist) +{ + if (msglist.isEmpty()) + return; + + if (_messageBuffer.isEmpty()) { + int processedMsgs = insertMessagesGracefully(msglist); + int remainingMsgs = msglist.count() - processedMsgs; + if (remainingMsgs > 0) { + if (msglist.first().msgId() < msglist.last().msgId()) { + // in Order - we have just successfully processed "processedMsg" messages from the end of the list + _messageBuffer = msglist.mid(0, remainingMsgs); + } + else { + _messageBuffer = msglist.mid(processedMsgs); + } + qSort(_messageBuffer); + QCoreApplication::postEvent(this, new ProcessBufferEvent()); + } + } + else { + _messageBuffer << msglist; + qSort(_messageBuffer); } - } else { - _messageBuffer << msglist; - qSort(_messageBuffer); - } } -void MessageModel::insertMessageGroup(const QList &msglist) { - Q_ASSERT(!msglist.isEmpty()); // the msglist can be assumed to be non empty + +void MessageModel::insertMessageGroup(const QList &msglist) +{ + Q_ASSERT(!msglist.isEmpty()); // the msglist can be assumed to be non empty // int last = msglist.count() - 1; // Q_ASSERT(0 == last || msglist.at(0).msgId() != msglist.at(last).msgId() || msglist.at(last).type() == Message::DayChange); - int start = indexForId(msglist.first().msgId()); - int end = start + msglist.count() - 1; - Message dayChangeMsg; - - if(start > 0) { - // check if the preceeding msg is a daychange message and if so if - // we have to drop or relocate it at the end of this chunk - int prevIdx = start - 1; - if(messageItemAt(prevIdx)->msgType() == Message::DayChange - && messageItemAt(prevIdx)->timestamp() > msglist.at(0).timestamp()) { - - beginRemoveRows(QModelIndex(), prevIdx, prevIdx); - Message oldDayChangeMsg = takeMessageAt(prevIdx); - if(msglist.last().timestamp() < oldDayChangeMsg.timestamp()) { - // we have to reinsert it with a changed msgId - dayChangeMsg = oldDayChangeMsg; - dayChangeMsg.setMsgId(msglist.last().msgId()); - } - endRemoveRows(); - - start--; - end--; + int start = indexForId(msglist.first().msgId()); + int end = start + msglist.count() - 1; + Message dayChangeMsg; + + if (start > 0) { + // check if the preceeding msg is a daychange message and if so if + // we have to drop or relocate it at the end of this chunk + int prevIdx = start - 1; + if (messageItemAt(prevIdx)->msgType() == Message::DayChange + && messageItemAt(prevIdx)->timestamp() > msglist.at(0).timestamp()) { + beginRemoveRows(QModelIndex(), prevIdx, prevIdx); + Message oldDayChangeMsg = takeMessageAt(prevIdx); + if (msglist.last().timestamp() < oldDayChangeMsg.timestamp()) { + // we have to reinsert it with a changed msgId + dayChangeMsg = oldDayChangeMsg; + dayChangeMsg.setMsgId(msglist.last().msgId()); + } + endRemoveRows(); + + start--; + end--; + } } - } - - if(!dayChangeMsg.isValid() && start < messageCount()) { - // if(!dayChangeItem && start < _messageList.count()) { - // check if we need to insert a daychange message at the end of the this group - - // if this assert triggers then indexForId() would have found a spot right before a DayChangeMsg - // this should never happen as daychange messages share the msgId with the preceeding message - Q_ASSERT(messageItemAt(start)->msgType() != Message::DayChange); - QDateTime nextTs = messageItemAt(start)->timestamp(); - QDateTime prevTs = msglist.last().timestamp(); - nextTs.setTimeSpec(Qt::UTC); - prevTs.setTimeSpec(Qt::UTC); - uint nextDay = nextTs.toTime_t() / 86400; - uint prevDay = prevTs.toTime_t() / 86400; - if(nextDay != prevDay) { - nextTs.setTime_t(nextDay * 86400); - nextTs.setTimeSpec(Qt::LocalTime); - dayChangeMsg = Message::ChangeOfDay(nextTs); - dayChangeMsg.setMsgId(msglist.last().msgId()); + + if (!dayChangeMsg.isValid() && start < messageCount()) { + // if(!dayChangeItem && start < _messageList.count()) { + // check if we need to insert a daychange message at the end of the this group + + // if this assert triggers then indexForId() would have found a spot right before a DayChangeMsg + // this should never happen as daychange messages share the msgId with the preceeding message + Q_ASSERT(messageItemAt(start)->msgType() != Message::DayChange); + QDateTime nextTs = messageItemAt(start)->timestamp(); + QDateTime prevTs = msglist.last().timestamp(); + nextTs.setTimeSpec(Qt::UTC); + prevTs.setTimeSpec(Qt::UTC); + uint nextDay = nextTs.toTime_t() / 86400; + uint prevDay = prevTs.toTime_t() / 86400; + if (nextDay != prevDay) { + nextTs.setTime_t(nextDay * 86400); + nextTs.setTimeSpec(Qt::LocalTime); + dayChangeMsg = Message::ChangeOfDay(nextTs); + dayChangeMsg.setMsgId(msglist.last().msgId()); + } } - } - - if(dayChangeMsg.isValid()) - end++; - - Q_ASSERT(start == 0 || messageItemAt(start - 1)->msgId() < msglist.first().msgId()); - Q_ASSERT(start == messageCount() || messageItemAt(start)->msgId() > msglist.last().msgId()); - beginInsertRows(QModelIndex(), start, end); - insertMessages__(start, msglist); - if(dayChangeMsg.isValid()) - insertMessage__(start + msglist.count(), dayChangeMsg); - endInsertRows(); - - Q_ASSERT(start == end || messageItemAt(start)->msgId() != messageItemAt(end)->msgId() || messageItemAt(end)->msgType() == Message::DayChange); - Q_ASSERT(start == 0 || messageItemAt(start - 1)->msgId() < messageItemAt(start)->msgId()); - Q_ASSERT(end + 1 == messageCount() || messageItemAt(end)->msgId() < messageItemAt(end + 1)->msgId()); + + if (dayChangeMsg.isValid()) + end++; + + Q_ASSERT(start == 0 || messageItemAt(start - 1)->msgId() < msglist.first().msgId()); + Q_ASSERT(start == messageCount() || messageItemAt(start)->msgId() > msglist.last().msgId()); + beginInsertRows(QModelIndex(), start, end); + insertMessages__(start, msglist); + if (dayChangeMsg.isValid()) + insertMessage__(start + msglist.count(), dayChangeMsg); + endInsertRows(); + + Q_ASSERT(start == end || messageItemAt(start)->msgId() != messageItemAt(end)->msgId() || messageItemAt(end)->msgType() == Message::DayChange); + Q_ASSERT(start == 0 || messageItemAt(start - 1)->msgId() < messageItemAt(start)->msgId()); + Q_ASSERT(end + 1 == messageCount() || messageItemAt(end)->msgId() < messageItemAt(end + 1)->msgId()); } -int MessageModel::insertMessagesGracefully(const QList &msglist) { - /* short description: - * 1) first we check where the message with the highest msgId from msglist would be inserted - * 2) check that position for dupe - * 3) determine the messageId of the preceeding msg - * 4) insert as many msgs from msglist with with msgId larger then the just determined id - * those messages are automatically less then the msg of the position we just determined in 1) - */ - bool inOrder = (msglist.first().msgId() < msglist.last().msgId()); - // depending on the order we have to traverse from the front to the back or vice versa - - QList grouplist; - MsgId minId; - MsgId dupeId; - int processedMsgs = 1; // we know the list isn't empty, so we at least process one message - int idx; - bool fastForward = false; - QList::const_iterator iter; - if(inOrder) { - iter = msglist.constEnd(); - iter--; // this op is safe as we've allready passed an empty check - } else { - iter = msglist.constBegin(); - } - - idx = indexForId((*iter).msgId()); - if(idx < messageCount()) - dupeId = messageItemAt(idx)->msgId(); - - // we always compare to the previous entry... - // if there isn't, we can fastforward to the top - if(idx - 1 >= 0) - minId = messageItemAt(idx - 1)->msgId(); - else - fastForward = true; - - if((*iter).msgId() != dupeId) { - grouplist << *iter; - dupeId = (*iter).msgId(); - } - - if(!inOrder) - iter++; - - if(inOrder) { - while(iter != msglist.constBegin()) { - iter--; - - if(!fastForward && (*iter).msgId() <= minId) - break; - processedMsgs++; - - if(grouplist.isEmpty()) { // as long as we don't have a starting point, we have to update the dupeId - idx = indexForId((*iter).msgId()); - if(idx >= 0 && !messagesIsEmpty()) - dupeId = messageItemAt(idx)->msgId(); - } - if((*iter).msgId() != dupeId) { - if(!grouplist.isEmpty()) { - QDateTime nextTs = grouplist.value(0).timestamp(); - QDateTime prevTs = (*iter).timestamp(); - nextTs.setTimeSpec(Qt::UTC); - prevTs.setTimeSpec(Qt::UTC); - uint nextDay = nextTs.toTime_t() / 86400; - uint prevDay = prevTs.toTime_t() / 86400; - if(nextDay != prevDay) { - nextTs.setTime_t(nextDay * 86400); - nextTs.setTimeSpec(Qt::LocalTime); - Message dayChangeMsg = Message::ChangeOfDay(nextTs); - dayChangeMsg.setMsgId((*iter).msgId()); - grouplist.prepend(dayChangeMsg); - } - } - dupeId = (*iter).msgId(); - grouplist.prepend(*iter); - } + +int MessageModel::insertMessagesGracefully(const QList &msglist) +{ + /* short description: + * 1) first we check where the message with the highest msgId from msglist would be inserted + * 2) check that position for dupe + * 3) determine the messageId of the preceeding msg + * 4) insert as many msgs from msglist with with msgId larger then the just determined id + * those messages are automatically less then the msg of the position we just determined in 1) + */ + bool inOrder = (msglist.first().msgId() < msglist.last().msgId()); + // depending on the order we have to traverse from the front to the back or vice versa + + QList grouplist; + MsgId minId; + MsgId dupeId; + int processedMsgs = 1; // we know the list isn't empty, so we at least process one message + int idx; + bool fastForward = false; + QList::const_iterator iter; + if (inOrder) { + iter = msglist.constEnd(); + iter--; // this op is safe as we've allready passed an empty check + } + else { + iter = msglist.constBegin(); + } + + idx = indexForId((*iter).msgId()); + if (idx < messageCount()) + dupeId = messageItemAt(idx)->msgId(); + + // we always compare to the previous entry... + // if there isn't, we can fastforward to the top + if (idx - 1 >= 0) + minId = messageItemAt(idx - 1)->msgId(); + else + fastForward = true; + + if ((*iter).msgId() != dupeId) { + grouplist << *iter; + dupeId = (*iter).msgId(); + } + + if (!inOrder) + iter++; + + if (inOrder) { + while (iter != msglist.constBegin()) { + iter--; + + if (!fastForward && (*iter).msgId() <= minId) + break; + processedMsgs++; + + if (grouplist.isEmpty()) { // as long as we don't have a starting point, we have to update the dupeId + idx = indexForId((*iter).msgId()); + if (idx >= 0 && !messagesIsEmpty()) + dupeId = messageItemAt(idx)->msgId(); + } + if ((*iter).msgId() != dupeId) { + if (!grouplist.isEmpty()) { + QDateTime nextTs = grouplist.value(0).timestamp(); + QDateTime prevTs = (*iter).timestamp(); + nextTs.setTimeSpec(Qt::UTC); + prevTs.setTimeSpec(Qt::UTC); + uint nextDay = nextTs.toTime_t() / 86400; + uint prevDay = prevTs.toTime_t() / 86400; + if (nextDay != prevDay) { + nextTs.setTime_t(nextDay * 86400); + nextTs.setTimeSpec(Qt::LocalTime); + Message dayChangeMsg = Message::ChangeOfDay(nextTs); + dayChangeMsg.setMsgId((*iter).msgId()); + grouplist.prepend(dayChangeMsg); + } + } + dupeId = (*iter).msgId(); + grouplist.prepend(*iter); + } + } } - } else { - while(iter != msglist.constEnd()) { - if(!fastForward && (*iter).msgId() <= minId) - break; - processedMsgs++; - - if(grouplist.isEmpty()) { // as long as we don't have a starting point, we have to update the dupeId - idx = indexForId((*iter).msgId()); - if(idx >= 0 && !messagesIsEmpty()) - dupeId = messageItemAt(idx)->msgId(); - } - if((*iter).msgId() != dupeId) { - if(!grouplist.isEmpty()) { - QDateTime nextTs = grouplist.value(0).timestamp(); - QDateTime prevTs = (*iter).timestamp(); - nextTs.setTimeSpec(Qt::UTC); - prevTs.setTimeSpec(Qt::UTC); - uint nextDay = nextTs.toTime_t() / 86400; - uint prevDay = prevTs.toTime_t() / 86400; - if(nextDay != prevDay) { - nextTs.setTime_t(nextDay * 86400); - nextTs.setTimeSpec(Qt::LocalTime); - Message dayChangeMsg = Message::ChangeOfDay(nextTs); - dayChangeMsg.setMsgId((*iter).msgId()); - grouplist.prepend(dayChangeMsg); - } - } - dupeId = (*iter).msgId(); - grouplist.prepend(*iter); - } - iter++; + else { + while (iter != msglist.constEnd()) { + if (!fastForward && (*iter).msgId() <= minId) + break; + processedMsgs++; + + if (grouplist.isEmpty()) { // as long as we don't have a starting point, we have to update the dupeId + idx = indexForId((*iter).msgId()); + if (idx >= 0 && !messagesIsEmpty()) + dupeId = messageItemAt(idx)->msgId(); + } + if ((*iter).msgId() != dupeId) { + if (!grouplist.isEmpty()) { + QDateTime nextTs = grouplist.value(0).timestamp(); + QDateTime prevTs = (*iter).timestamp(); + nextTs.setTimeSpec(Qt::UTC); + prevTs.setTimeSpec(Qt::UTC); + uint nextDay = nextTs.toTime_t() / 86400; + uint prevDay = prevTs.toTime_t() / 86400; + if (nextDay != prevDay) { + nextTs.setTime_t(nextDay * 86400); + nextTs.setTimeSpec(Qt::LocalTime); + Message dayChangeMsg = Message::ChangeOfDay(nextTs); + dayChangeMsg.setMsgId((*iter).msgId()); + grouplist.prepend(dayChangeMsg); + } + } + dupeId = (*iter).msgId(); + grouplist.prepend(*iter); + } + iter++; + } } - } - if(!grouplist.isEmpty()) - insertMessageGroup(grouplist); - return processedMsgs; + if (!grouplist.isEmpty()) + insertMessageGroup(grouplist); + return processedMsgs; } -void MessageModel::customEvent(QEvent *event) { - if(event->type() != QEvent::User) - return; - event->accept(); +void MessageModel::customEvent(QEvent *event) +{ + if (event->type() != QEvent::User) + return; + + event->accept(); - if(_messageBuffer.isEmpty()) - return; + if (_messageBuffer.isEmpty()) + return; - int processedMsgs = insertMessagesGracefully(_messageBuffer); - int remainingMsgs = _messageBuffer.count() - processedMsgs; + int processedMsgs = insertMessagesGracefully(_messageBuffer); + int remainingMsgs = _messageBuffer.count() - processedMsgs; - QList::iterator removeStart = _messageBuffer.begin() + remainingMsgs; - QList::iterator removeEnd = _messageBuffer.end(); - _messageBuffer.erase(removeStart, removeEnd); - if(!_messageBuffer.isEmpty()) - QCoreApplication::postEvent(this, new ProcessBufferEvent()); + QList::iterator removeStart = _messageBuffer.begin() + remainingMsgs; + QList::iterator removeEnd = _messageBuffer.end(); + _messageBuffer.erase(removeStart, removeEnd); + if (!_messageBuffer.isEmpty()) + QCoreApplication::postEvent(this, new ProcessBufferEvent()); } -void MessageModel::clear() { - _messagesWaiting.clear(); - if (rowCount() > 0) { - beginRemoveRows(QModelIndex(), 0, rowCount() - 1); - removeAllMessages(); - endRemoveRows(); - } + +void MessageModel::clear() +{ + _messagesWaiting.clear(); + if (rowCount() > 0) { + beginRemoveRows(QModelIndex(), 0, rowCount() - 1); + removeAllMessages(); + endRemoveRows(); + } } + // returns index of msg with given Id or of the next message after that (i.e., the index where we'd insert this msg) -int MessageModel::indexForId(MsgId id) { - if(messagesIsEmpty() || id <= messageItemAt(0)->msgId()) - return 0; - - if(id > lastMessageItem()->msgId()) - return messageCount(); - - // binary search - int start = 0; int end = messageCount() - 1; - while(1) { - if(end - start == 1) - return end; - int pivot = (end + start) / 2; - if(id <= messageItemAt(pivot)->msgId()) end = pivot; - else start = pivot; - } +int MessageModel::indexForId(MsgId id) +{ + if (messagesIsEmpty() || id <= messageItemAt(0)->msgId()) + return 0; + + if (id > lastMessageItem()->msgId()) + return messageCount(); + + // binary search + int start = 0; int end = messageCount() - 1; + while (1) { + if (end - start == 1) + return end; + int pivot = (end + start) / 2; + if (id <= messageItemAt(pivot)->msgId()) end = pivot; + else start = pivot; + } } -void MessageModel::changeOfDay() { - _dayChangeTimer.setInterval(86400000); - if(!messagesIsEmpty()) { - int idx = messageCount(); - while(idx > 0 && messageItemAt(idx - 1)->timestamp() > _nextDayChange) { - idx--; + +void MessageModel::changeOfDay() +{ + _dayChangeTimer.setInterval(86400000); + if (!messagesIsEmpty()) { + int idx = messageCount(); + while (idx > 0 && messageItemAt(idx - 1)->timestamp() > _nextDayChange) { + idx--; + } + beginInsertRows(QModelIndex(), idx, idx); + Message dayChangeMsg = Message::ChangeOfDay(_nextDayChange); + dayChangeMsg.setMsgId(messageItemAt(idx - 1)->msgId()); + insertMessage__(idx, dayChangeMsg); + endInsertRows(); } + _nextDayChange = _nextDayChange.addSecs(86400); +} + + +void MessageModel::insertErrorMessage(BufferInfo bufferInfo, const QString &errorString) +{ + int idx = messageCount(); beginInsertRows(QModelIndex(), idx, idx); - Message dayChangeMsg = Message::ChangeOfDay(_nextDayChange); - dayChangeMsg.setMsgId(messageItemAt(idx - 1)->msgId()); - insertMessage__(idx, dayChangeMsg); + Message msg(bufferInfo, Message::Error, errorString); + if (!messagesIsEmpty()) + msg.setMsgId(messageItemAt(idx-1)->msgId()); + else + msg.setMsgId(0); + insertMessage__(idx, msg); endInsertRows(); - } - _nextDayChange = _nextDayChange.addSecs(86400); } -void MessageModel::insertErrorMessage(BufferInfo bufferInfo, const QString &errorString) { - int idx = messageCount(); - beginInsertRows(QModelIndex(), idx, idx); - Message msg(bufferInfo, Message::Error, errorString); - if(!messagesIsEmpty()) - msg.setMsgId(messageItemAt(idx-1)->msgId()); - else - msg.setMsgId(0); - insertMessage__(idx, msg); - endInsertRows(); -} -void MessageModel::requestBacklog(BufferId bufferId) { - if(_messagesWaiting.contains(bufferId)) - return; - - BacklogSettings backlogSettings; - int requestCount = backlogSettings.dynamicBacklogAmount(); - - for(int i = 0; i < messageCount(); i++) { - if(messageItemAt(i)->bufferId() == bufferId) { - _messagesWaiting[bufferId] = requestCount; - Client::backlogManager()->emitMessagesRequested(tr("Requesting %1 messages from backlog for buffer %2:%3") - .arg(requestCount) - .arg(Client::networkModel()->networkName(bufferId)) - .arg(Client::networkModel()->bufferName(bufferId))); - Client::backlogManager()->requestBacklog(bufferId, -1, messageItemAt(i)->msgId(), requestCount); - return; +void MessageModel::requestBacklog(BufferId bufferId) +{ + if (_messagesWaiting.contains(bufferId)) + return; + + BacklogSettings backlogSettings; + int requestCount = backlogSettings.dynamicBacklogAmount(); + + for (int i = 0; i < messageCount(); i++) { + if (messageItemAt(i)->bufferId() == bufferId) { + _messagesWaiting[bufferId] = requestCount; + Client::backlogManager()->emitMessagesRequested(tr("Requesting %1 messages from backlog for buffer %2:%3") + .arg(requestCount) + .arg(Client::networkModel()->networkName(bufferId)) + .arg(Client::networkModel()->bufferName(bufferId))); + Client::backlogManager()->requestBacklog(bufferId, -1, messageItemAt(i)->msgId(), requestCount); + return; + } } - } } -void MessageModel::messagesReceived(BufferId bufferId, int count) { - if(!_messagesWaiting.contains(bufferId)) - return; - _messagesWaiting[bufferId] -= count; - if(_messagesWaiting[bufferId] <= 0) { - _messagesWaiting.remove(bufferId); - emit finishedBacklogFetch(bufferId); - } +void MessageModel::messagesReceived(BufferId bufferId, int count) +{ + if (!_messagesWaiting.contains(bufferId)) + return; + + _messagesWaiting[bufferId] -= count; + if (_messagesWaiting[bufferId] <= 0) { + _messagesWaiting.remove(bufferId); + emit finishedBacklogFetch(bufferId); + } } -void MessageModel::buffersPermanentlyMerged(BufferId bufferId1, BufferId bufferId2) { - for(int i = 0; i < messageCount(); i++) { - if(messageItemAt(i)->bufferId() == bufferId2) { - messageItemAt(i)->setBufferId(bufferId1); - QModelIndex idx = index(i, 0); - emit dataChanged(idx, idx); + +void MessageModel::buffersPermanentlyMerged(BufferId bufferId1, BufferId bufferId2) +{ + for (int i = 0; i < messageCount(); i++) { + if (messageItemAt(i)->bufferId() == bufferId2) { + messageItemAt(i)->setBufferId(bufferId1); + QModelIndex idx = index(i, 0); + emit dataChanged(idx, idx); + } } - } } + // ======================================== // MessageModelItem // ======================================== -QVariant MessageModelItem::data(int column, int role) const { - if(column < MessageModel::TimestampColumn || column > MessageModel::ContentsColumn) - return QVariant(); - - switch(role) { - case MessageModel::MessageRole: return QVariant::fromValue(message()); - case MessageModel::MsgIdRole: return QVariant::fromValue(msgId()); - case MessageModel::BufferIdRole: return QVariant::fromValue(bufferId()); - case MessageModel::TypeRole: return msgType(); - case MessageModel::FlagsRole: return (int)msgFlags(); - case MessageModel::TimestampRole: return timestamp(); - case MessageModel::RedirectedToRole: return qVariantFromValue(_redirectedTo); - default: return QVariant(); - } +QVariant MessageModelItem::data(int column, int role) const +{ + if (column < MessageModel::TimestampColumn || column > MessageModel::ContentsColumn) + return QVariant(); + + switch (role) { + case MessageModel::MessageRole: + return QVariant::fromValue(message()); + case MessageModel::MsgIdRole: + return QVariant::fromValue(msgId()); + case MessageModel::BufferIdRole: + return QVariant::fromValue(bufferId()); + case MessageModel::TypeRole: + return msgType(); + case MessageModel::FlagsRole: + return (int)msgFlags(); + case MessageModel::TimestampRole: + return timestamp(); + case MessageModel::RedirectedToRole: + return qVariantFromValue(_redirectedTo); + default: + return QVariant(); + } } -bool MessageModelItem::setData(int column, const QVariant &value, int role) { - Q_UNUSED(column); - switch(role) { - case MessageModel::RedirectedToRole: - _redirectedTo = value.value(); - return true; - default: - return false; - } +bool MessageModelItem::setData(int column, const QVariant &value, int role) +{ + Q_UNUSED(column); + + switch (role) { + case MessageModel::RedirectedToRole: + _redirectedTo = value.value(); + return true; + default: + return false; + } } + // Stuff for later -bool MessageModelItem::lessThan(const MessageModelItem *m1, const MessageModelItem *m2){ - return (*m1) < (*m2); +bool MessageModelItem::lessThan(const MessageModelItem *m1, const MessageModelItem *m2) +{ + return (*m1) < (*m2); } -bool MessageModelItem::operator<(const MessageModelItem &other) const { - return msgId() < other.msgId(); + +bool MessageModelItem::operator<(const MessageModelItem &other) const +{ + return msgId() < other.msgId(); } -bool MessageModelItem::operator==(const MessageModelItem &other) const { - return msgId() == other.msgId(); + +bool MessageModelItem::operator==(const MessageModelItem &other) const +{ + return msgId() == other.msgId(); } -bool MessageModelItem::operator>(const MessageModelItem &other) const { - return msgId() > other.msgId(); + +bool MessageModelItem::operator>(const MessageModelItem &other) const +{ + return msgId() > other.msgId(); } -QDebug operator<<(QDebug dbg, const MessageModelItem &msgItem) { - dbg.nospace() << qPrintable(QString("MessageModelItem(MsgId:")) << msgItem.msgId() - << qPrintable(QString(",")) << msgItem.timestamp() - << qPrintable(QString(", Type:")) << msgItem.msgType() - << qPrintable(QString(", Flags:")) << msgItem.msgFlags() << qPrintable(QString(")")) - << msgItem.data(1, Qt::DisplayRole).toString() << ":" << msgItem.data(2, Qt::DisplayRole).toString(); - return dbg; + +QDebug operator<<(QDebug dbg, const MessageModelItem &msgItem) +{ + dbg.nospace() << qPrintable(QString("MessageModelItem(MsgId:")) << msgItem.msgId() + << qPrintable(QString(",")) << msgItem.timestamp() + << qPrintable(QString(", Type:")) << msgItem.msgType() + << qPrintable(QString(", Flags:")) << msgItem.msgFlags() << qPrintable(QString(")")) + << msgItem.data(1, Qt::DisplayRole).toString() << ":" << msgItem.data(2, Qt::DisplayRole).toString(); + return dbg; } diff --git a/src/client/messagemodel.h b/src/client/messagemodel.h index 4ffeeb42..dba767d8 100644 --- a/src/client/messagemodel.h +++ b/src/client/messagemodel.h @@ -31,132 +31,138 @@ class MessageModelItem; struct MsgId; -class MessageModel : public QAbstractItemModel { - Q_OBJECT +class MessageModel : public QAbstractItemModel +{ + Q_OBJECT public: - enum MessageModelRole { - DisplayRole = Qt::DisplayRole, - EditRole = Qt::EditRole, - BackgroundRole = Qt::BackgroundRole, - MessageRole = Qt::UserRole, - MsgIdRole, - BufferIdRole, - TypeRole, - FlagsRole, - TimestampRole, - FormatRole, - ColumnTypeRole, - RedirectedToRole, - UserRole - }; - - enum ColumnType { - TimestampColumn, SenderColumn, ContentsColumn, UserColumnType - }; - - MessageModel(QObject *parent); - - inline 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 { return parent.isValid() ? 0 : messageCount(); } - inline int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const { return 3; } - - virtual QVariant data(const QModelIndex &index, int role) const; - virtual bool setData(const QModelIndex &index, const QVariant &value, int role); - - //virtual Qt::ItemFlags flags(const QModelIndex &index) const; - - bool insertMessage(const Message &, bool fakeMsg = false); - void insertMessages(const QList &); - - void clear(); + enum MessageModelRole { + DisplayRole = Qt::DisplayRole, + EditRole = Qt::EditRole, + BackgroundRole = Qt::BackgroundRole, + MessageRole = Qt::UserRole, + MsgIdRole, + BufferIdRole, + TypeRole, + FlagsRole, + TimestampRole, + FormatRole, + ColumnTypeRole, + RedirectedToRole, + UserRole + }; + + enum ColumnType { + TimestampColumn, SenderColumn, ContentsColumn, UserColumnType + }; + + MessageModel(QObject *parent); + + inline 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 { return parent.isValid() ? 0 : messageCount(); } + inline int columnCount(const QModelIndex & /*parent*/ = QModelIndex()) const { return 3; } + + virtual QVariant data(const QModelIndex &index, int role) const; + virtual bool setData(const QModelIndex &index, const QVariant &value, int role); + + //virtual Qt::ItemFlags flags(const QModelIndex &index) const; + + bool insertMessage(const Message &, bool fakeMsg = false); + void insertMessages(const QList &); + + void clear(); signals: - void finishedBacklogFetch(BufferId bufferId); + void finishedBacklogFetch(BufferId bufferId); public slots: - void requestBacklog(BufferId bufferId); - void messagesReceived(BufferId bufferId, int count); - void buffersPermanentlyMerged(BufferId bufferId1, BufferId bufferId2); - void insertErrorMessage(BufferInfo bufferInfo, const QString &errorString); + void requestBacklog(BufferId bufferId); + void messagesReceived(BufferId bufferId, int count); + void buffersPermanentlyMerged(BufferId bufferId1, BufferId bufferId2); + void insertErrorMessage(BufferInfo bufferInfo, const QString &errorString); protected: // virtual MessageModelItem *createMessageModelItem(const Message &) = 0; - virtual int messageCount() const = 0; - virtual bool messagesIsEmpty() const = 0; - virtual const MessageModelItem *messageItemAt(int i) const = 0; - virtual MessageModelItem *messageItemAt(int i) = 0; - virtual const MessageModelItem *firstMessageItem() const= 0; - virtual MessageModelItem *firstMessageItem() = 0; - virtual const MessageModelItem *lastMessageItem() const= 0; - virtual MessageModelItem *lastMessageItem() = 0; - virtual void insertMessage__(int pos, const Message &) = 0; - virtual void insertMessages__(int pos, const QList &) = 0; - virtual void removeMessageAt(int i) = 0; - virtual void removeAllMessages() = 0; - virtual Message takeMessageAt(int i) = 0; - - virtual void customEvent(QEvent *event); + virtual int messageCount() const = 0; + virtual bool messagesIsEmpty() const = 0; + virtual const MessageModelItem *messageItemAt(int i) const = 0; + virtual MessageModelItem *messageItemAt(int i) = 0; + virtual const MessageModelItem *firstMessageItem() const = 0; + virtual MessageModelItem *firstMessageItem() = 0; + virtual const MessageModelItem *lastMessageItem() const = 0; + virtual MessageModelItem *lastMessageItem() = 0; + virtual void insertMessage__(int pos, const Message &) = 0; + virtual void insertMessages__(int pos, const QList &) = 0; + virtual void removeMessageAt(int i) = 0; + virtual void removeAllMessages() = 0; + virtual Message takeMessageAt(int i) = 0; + + virtual void customEvent(QEvent *event); private slots: - void changeOfDay(); + void changeOfDay(); private: - void insertMessageGroup(const QList &); - int insertMessagesGracefully(const QList &); // inserts as many contiguous msgs as possible. returns numer of inserted msgs. - int indexForId(MsgId); - - // QList _messageList; - QList _messageBuffer; - QTimer _dayChangeTimer; - QDateTime _nextDayChange; - QHash _messagesWaiting; + void insertMessageGroup(const QList &); + int insertMessagesGracefully(const QList &); // inserts as many contiguous msgs as possible. returns numer of inserted msgs. + int indexForId(MsgId); + + // QList _messageList; + QList _messageBuffer; + QTimer _dayChangeTimer; + QDateTime _nextDayChange; + QHash _messagesWaiting; }; + // inlines -QModelIndex MessageModel::index(int row, int column, const QModelIndex &parent) const { - if(row < 0 || row >= rowCount(parent) || column < 0 || column >= columnCount(parent)) - return QModelIndex(); +QModelIndex MessageModel::index(int row, int column, const QModelIndex &parent) const +{ + if (row < 0 || row >= rowCount(parent) || column < 0 || column >= columnCount(parent)) + return QModelIndex(); - return createIndex(row, column); + return createIndex(row, column); } + // ************************************************** // MessageModelItem // ************************************************** -class MessageModelItem { +class MessageModelItem +{ public: - //! Creates a MessageModelItem from a Message object. - /** This baseclass implementation takes care of all Message data *except* the stylable strings. - * Subclasses need to provide Qt::DisplayRole at least, which should describe the plaintext - * strings without formattings (e.g. for searching purposes). - */ - MessageModelItem() {} - inline virtual ~MessageModelItem() {} - - virtual QVariant data(int column, int role) const; - virtual bool setData(int column, const QVariant &value, int role); - - virtual const Message &message() const = 0; - virtual const QDateTime ×tamp() const = 0; - virtual const MsgId &msgId() const = 0; - virtual const BufferId &bufferId() const = 0; - virtual void setBufferId(BufferId bufferId) = 0; - virtual Message::Type msgType() const = 0; - virtual Message::Flags msgFlags() const = 0; - - // For sorting - bool operator<(const MessageModelItem &) const; - bool operator==(const MessageModelItem &) const; - bool operator>(const MessageModelItem &) const; - static bool lessThan(const MessageModelItem *m1, const MessageModelItem *m2); + //! Creates a MessageModelItem from a Message object. + /** This baseclass implementation takes care of all Message data *except* the stylable strings. + * Subclasses need to provide Qt::DisplayRole at least, which should describe the plaintext + * strings without formattings (e.g. for searching purposes). + */ + MessageModelItem() {} + inline virtual ~MessageModelItem() {} + + virtual QVariant data(int column, int role) const; + virtual bool setData(int column, const QVariant &value, int role); + + virtual const Message &message() const = 0; + virtual const QDateTime ×tamp() const = 0; + virtual const MsgId &msgId() const = 0; + virtual const BufferId &bufferId() const = 0; + virtual void setBufferId(BufferId bufferId) = 0; + virtual Message::Type msgType() const = 0; + virtual Message::Flags msgFlags() const = 0; + + // For sorting + bool operator<(const MessageModelItem &) const; + bool operator==(const MessageModelItem &) const; + bool operator>(const MessageModelItem &) const; + static bool lessThan(const MessageModelItem *m1, const MessageModelItem *m2); private: - BufferId _redirectedTo; + BufferId _redirectedTo; }; + QDebug operator<<(QDebug dbg, const MessageModelItem &msgItem); #endif diff --git a/src/client/networkmodel.cpp b/src/client/networkmodel.cpp index d713d330..a38ed11d 100644 --- a/src/client/networkmodel.cpp +++ b/src/client/networkmodel.cpp @@ -22,7 +22,7 @@ #include #include -#include // for Qt::escape() +#include // for Qt::escape() #include "buffermodel.h" #include "buffersettings.h" @@ -37,644 +37,726 @@ * Network Items *****************************************/ NetworkItem::NetworkItem(const NetworkId &netid, AbstractTreeItem *parent) - : PropertyMapItem(QList() << "networkName" << "currentServer" << "nickCount", parent), + : PropertyMapItem(QList() << "networkName" << "currentServer" << "nickCount", parent), _networkId(netid), _statusBufferItem(0) { - // DO NOT EMIT dataChanged() DIRECTLY IN NetworkItem - // use networkDataChanged() instead. Otherwise you will end up in a infinite loop - // as we "sync" the dataChanged() signals of NetworkItem and StatusBufferItem - setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); - connect(this, SIGNAL(networkDataChanged(int)), this, SIGNAL(dataChanged(int))); - connect(this, SIGNAL(beginRemoveChilds(int, int)), this, SLOT(onBeginRemoveChilds(int, int))); -} - -QVariant NetworkItem::data(int column, int role) const { - switch(role) { - case NetworkModel::BufferIdRole: - case NetworkModel::BufferInfoRole: - case NetworkModel::BufferTypeRole: - case NetworkModel::BufferActivityRole: - if(_statusBufferItem) - return _statusBufferItem->data(column, role); - else - return QVariant(); - case NetworkModel::NetworkIdRole: - return qVariantFromValue(_networkId); - case NetworkModel::ItemTypeRole: - return NetworkModel::NetworkItemType; - case NetworkModel::ItemActiveRole: - return isActive(); - default: - return PropertyMapItem::data(column, role); - } + // DO NOT EMIT dataChanged() DIRECTLY IN NetworkItem + // use networkDataChanged() instead. Otherwise you will end up in a infinite loop + // as we "sync" the dataChanged() signals of NetworkItem and StatusBufferItem + setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); + connect(this, SIGNAL(networkDataChanged(int)), this, SIGNAL(dataChanged(int))); + connect(this, SIGNAL(beginRemoveChilds(int, int)), this, SLOT(onBeginRemoveChilds(int, int))); } -// FIXME shouldn't we check the bufferItemCache here? -BufferItem *NetworkItem::findBufferItem(BufferId bufferId) { - BufferItem *bufferItem = 0; - for(int i = 0; i < childCount(); i++) { - bufferItem = qobject_cast(child(i)); - if(!bufferItem) - continue; - if(bufferItem->bufferId() == bufferId) - return bufferItem; - } - return 0; +QVariant NetworkItem::data(int column, int role) const +{ + switch (role) { + case NetworkModel::BufferIdRole: + case NetworkModel::BufferInfoRole: + case NetworkModel::BufferTypeRole: + case NetworkModel::BufferActivityRole: + if (_statusBufferItem) + return _statusBufferItem->data(column, role); + else + return QVariant(); + case NetworkModel::NetworkIdRole: + return qVariantFromValue(_networkId); + case NetworkModel::ItemTypeRole: + return NetworkModel::NetworkItemType; + case NetworkModel::ItemActiveRole: + return isActive(); + default: + return PropertyMapItem::data(column, role); + } } -BufferItem *NetworkItem::bufferItem(const BufferInfo &bufferInfo) { - BufferItem *bufferItem = findBufferItem(bufferInfo); - if(bufferItem) - return bufferItem; +// FIXME shouldn't we check the bufferItemCache here? +BufferItem *NetworkItem::findBufferItem(BufferId bufferId) +{ + BufferItem *bufferItem = 0; + + for (int i = 0; i < childCount(); i++) { + bufferItem = qobject_cast(child(i)); + if (!bufferItem) + continue; + if (bufferItem->bufferId() == bufferId) + return bufferItem; + } + return 0; +} - switch(bufferInfo.type()) { - case BufferInfo::StatusBuffer: - _statusBufferItem = new StatusBufferItem(bufferInfo, this); - bufferItem = _statusBufferItem; - disconnect(this, SIGNAL(networkDataChanged(int)), this, SIGNAL(dataChanged(int))); - connect(this, SIGNAL(networkDataChanged(int)), bufferItem, SIGNAL(dataChanged(int))); - connect(bufferItem, SIGNAL(dataChanged(int)), this, SIGNAL(dataChanged(int))); - break; - case BufferInfo::ChannelBuffer: - bufferItem = new ChannelBufferItem(bufferInfo, this); - break; - case BufferInfo::QueryBuffer: - bufferItem = new QueryBufferItem(bufferInfo, this); - break; - default: - bufferItem = new BufferItem(bufferInfo, this); - } - newChild(bufferItem); +BufferItem *NetworkItem::bufferItem(const BufferInfo &bufferInfo) +{ + BufferItem *bufferItem = findBufferItem(bufferInfo); + if (bufferItem) + return bufferItem; + + switch (bufferInfo.type()) { + case BufferInfo::StatusBuffer: + _statusBufferItem = new StatusBufferItem(bufferInfo, this); + bufferItem = _statusBufferItem; + disconnect(this, SIGNAL(networkDataChanged(int)), this, SIGNAL(dataChanged(int))); + connect(this, SIGNAL(networkDataChanged(int)), bufferItem, SIGNAL(dataChanged(int))); + connect(bufferItem, SIGNAL(dataChanged(int)), this, SIGNAL(dataChanged(int))); + break; + case BufferInfo::ChannelBuffer: + bufferItem = new ChannelBufferItem(bufferInfo, this); + break; + case BufferInfo::QueryBuffer: + bufferItem = new QueryBufferItem(bufferInfo, this); + break; + default: + bufferItem = new BufferItem(bufferInfo, this); + } - // postprocess... this is necessary because Qt doesn't seem to like adding children which already have children on their own - switch(bufferInfo.type()) { - case BufferInfo::ChannelBuffer: + newChild(bufferItem); + + // postprocess... this is necessary because Qt doesn't seem to like adding children which already have children on their own + switch (bufferInfo.type()) { + case BufferInfo::ChannelBuffer: { - ChannelBufferItem *channelBufferItem = static_cast(bufferItem); - if(_network) { - IrcChannel *ircChannel = _network->ircChannel(bufferInfo.bufferName()); - if(ircChannel) - channelBufferItem->attachIrcChannel(ircChannel); - } + ChannelBufferItem *channelBufferItem = static_cast(bufferItem); + if (_network) { + IrcChannel *ircChannel = _network->ircChannel(bufferInfo.bufferName()); + if (ircChannel) + channelBufferItem->attachIrcChannel(ircChannel); + } } break; - default: - break; - } + default: + break; + } - return bufferItem; + return bufferItem; } -void NetworkItem::attachNetwork(Network *network) { - if(!network) - return; - _network = network; +void NetworkItem::attachNetwork(Network *network) +{ + if (!network) + return; + + _network = network; - connect(network, SIGNAL(networkNameSet(QString)), - this, SLOT(setNetworkName(QString))); - connect(network, SIGNAL(currentServerSet(QString)), - this, SLOT(setCurrentServer(QString))); - connect(network, SIGNAL(ircChannelAdded(IrcChannel *)), - this, SLOT(attachIrcChannel(IrcChannel *))); - connect(network, SIGNAL(ircUserAdded(IrcUser *)), - this, SLOT(attachIrcUser(IrcUser *))); - connect(network, SIGNAL(connectedSet(bool)), - this, SIGNAL(networkDataChanged())); - connect(network, SIGNAL(destroyed()), - this, SIGNAL(networkDataChanged())); + connect(network, SIGNAL(networkNameSet(QString)), + this, SLOT(setNetworkName(QString))); + connect(network, SIGNAL(currentServerSet(QString)), + this, SLOT(setCurrentServer(QString))); + connect(network, SIGNAL(ircChannelAdded(IrcChannel *)), + this, SLOT(attachIrcChannel(IrcChannel *))); + connect(network, SIGNAL(ircUserAdded(IrcUser *)), + this, SLOT(attachIrcUser(IrcUser *))); + connect(network, SIGNAL(connectedSet(bool)), + this, SIGNAL(networkDataChanged())); + connect(network, SIGNAL(destroyed()), + this, SIGNAL(networkDataChanged())); - emit networkDataChanged(); + emit networkDataChanged(); } -void NetworkItem::attachIrcChannel(IrcChannel *ircChannel) { - ChannelBufferItem *channelItem; - for(int i = 0; i < childCount(); i++) { - channelItem = qobject_cast(child(i)); - if(!channelItem) - continue; - if(channelItem->bufferName().toLower() == ircChannel->name().toLower()) { - channelItem->attachIrcChannel(ircChannel); - return; +void NetworkItem::attachIrcChannel(IrcChannel *ircChannel) +{ + ChannelBufferItem *channelItem; + for (int i = 0; i < childCount(); i++) { + channelItem = qobject_cast(child(i)); + if (!channelItem) + continue; + + if (channelItem->bufferName().toLower() == ircChannel->name().toLower()) { + channelItem->attachIrcChannel(ircChannel); + return; + } } - } } -void NetworkItem::attachIrcUser(IrcUser *ircUser) { - QueryBufferItem *queryItem = 0; - for(int i = 0; i < childCount(); i++) { - queryItem = qobject_cast(child(i)); - if(!queryItem) - continue; - if(queryItem->bufferName().toLower() == ircUser->nick().toLower()) { - queryItem->setIrcUser(ircUser); - break; +void NetworkItem::attachIrcUser(IrcUser *ircUser) +{ + QueryBufferItem *queryItem = 0; + for (int i = 0; i < childCount(); i++) { + queryItem = qobject_cast(child(i)); + if (!queryItem) + continue; + + if (queryItem->bufferName().toLower() == ircUser->nick().toLower()) { + queryItem->setIrcUser(ircUser); + break; + } } - } } -void NetworkItem::setNetworkName(const QString &networkName) { - Q_UNUSED(networkName); - emit networkDataChanged(0); + +void NetworkItem::setNetworkName(const QString &networkName) +{ + Q_UNUSED(networkName); + emit networkDataChanged(0); } -void NetworkItem::setCurrentServer(const QString &serverName) { - Q_UNUSED(serverName); - emit networkDataChanged(1); + +void NetworkItem::setCurrentServer(const QString &serverName) +{ + Q_UNUSED(serverName); + emit networkDataChanged(1); } -QString NetworkItem::toolTip(int column) const { - Q_UNUSED(column); +QString NetworkItem::toolTip(int column) const +{ + Q_UNUSED(column); - QStringList toolTip(QString("%1").arg(Qt::escape(networkName()))); - toolTip.append(tr("Server: %1").arg(Qt::escape(currentServer()))); - toolTip.append(tr("Users: %1").arg(nickCount())); + QStringList toolTip(QString("%1").arg(Qt::escape(networkName()))); + toolTip.append(tr("Server: %1").arg(Qt::escape(currentServer()))); + toolTip.append(tr("Users: %1").arg(nickCount())); - if(_network) { - toolTip.append(tr("Lag: %1 msecs").arg(_network->latency())); - } + if (_network) { + toolTip.append(tr("Lag: %1 msecs").arg(_network->latency())); + } - return QString("

%1

").arg(toolTip.join("
")); + return QString("

%1

").arg(toolTip.join("
")); } -void NetworkItem::onBeginRemoveChilds(int start, int end) { - for(int i = start; i <= end; i++) { - StatusBufferItem *statusBufferItem = qobject_cast(child(i)); - if(statusBufferItem) { - _statusBufferItem = 0; - break; + +void NetworkItem::onBeginRemoveChilds(int start, int end) +{ + for (int i = start; i <= end; i++) { + StatusBufferItem *statusBufferItem = qobject_cast(child(i)); + if (statusBufferItem) { + _statusBufferItem = 0; + break; + } } - } } + /***************************************** * Fancy Buffer Items *****************************************/ BufferItem::BufferItem(const BufferInfo &bufferInfo, AbstractTreeItem *parent) - : PropertyMapItem(QStringList() << "bufferName" << "topic" << "nickCount", parent), + : PropertyMapItem(QStringList() << "bufferName" << "topic" << "nickCount", parent), _bufferInfo(bufferInfo), _activity(BufferInfo::NoActivity) { - setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); + setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); } -void BufferItem::setActivityLevel(BufferInfo::ActivityLevel level) { - if(_activity != level) { - _activity = level; - emit dataChanged(); - } + +void BufferItem::setActivityLevel(BufferInfo::ActivityLevel level) +{ + if (_activity != level) { + _activity = level; + emit dataChanged(); + } } -void BufferItem::clearActivityLevel() { - _activity = BufferInfo::NoActivity; - _firstUnreadMsgId = MsgId(); - // FIXME remove with core proto v11 - if(!(Client::coreFeatures() & Quassel::SynchronizedMarkerLine)) { - _markerLineMsgId = _lastSeenMsgId; - } +void BufferItem::clearActivityLevel() +{ + _activity = BufferInfo::NoActivity; + _firstUnreadMsgId = MsgId(); - emit dataChanged(); + // FIXME remove with core proto v11 + if (!(Client::coreFeatures() & Quassel::SynchronizedMarkerLine)) { + _markerLineMsgId = _lastSeenMsgId; + } + + emit dataChanged(); } -void BufferItem::updateActivityLevel(const Message &msg) { - if(isCurrentBuffer()) { - return; - } - if(msg.flags() & Message::Self) // don't update activity for our own messages - return; +void BufferItem::updateActivityLevel(const Message &msg) +{ + if (isCurrentBuffer()) { + return; + } - if (Client::ignoreListManager() - && Client::ignoreListManager()->match(msg, qobject_cast(parent())->networkName())) - return; + if (msg.flags() & Message::Self) // don't update activity for our own messages + return; - if(msg.msgId() <= lastSeenMsgId()) - return; + if (Client::ignoreListManager() + && Client::ignoreListManager()->match(msg, qobject_cast(parent())->networkName())) + return; - bool stateChanged = false; - if(!firstUnreadMsgId().isValid() || msg.msgId() < firstUnreadMsgId()) { - stateChanged = true; - _firstUnreadMsgId = msg.msgId(); - } + if (msg.msgId() <= lastSeenMsgId()) + return; - BufferInfo::ActivityLevel oldLevel = activityLevel(); + bool stateChanged = false; + if (!firstUnreadMsgId().isValid() || msg.msgId() < firstUnreadMsgId()) { + stateChanged = true; + _firstUnreadMsgId = msg.msgId(); + } - _activity |= BufferInfo::OtherActivity; - if(msg.type() & (Message::Plain | Message::Notice | Message::Action)) - _activity |= BufferInfo::NewMessage; + BufferInfo::ActivityLevel oldLevel = activityLevel(); - if(msg.flags() & Message::Highlight) - _activity |= BufferInfo::Highlight; + _activity |= BufferInfo::OtherActivity; + if (msg.type() & (Message::Plain | Message::Notice | Message::Action)) + _activity |= BufferInfo::NewMessage; - stateChanged |= (oldLevel != _activity); + if (msg.flags() & Message::Highlight) + _activity |= BufferInfo::Highlight; - if(stateChanged) - emit dataChanged(); + stateChanged |= (oldLevel != _activity); + + if (stateChanged) + emit dataChanged(); } -QVariant BufferItem::data(int column, int role) const { - switch(role) { - case NetworkModel::ItemTypeRole: - return NetworkModel::BufferItemType; - case NetworkModel::BufferIdRole: - return qVariantFromValue(bufferInfo().bufferId()); - case NetworkModel::NetworkIdRole: - return qVariantFromValue(bufferInfo().networkId()); - case NetworkModel::BufferInfoRole: - return qVariantFromValue(bufferInfo()); - case NetworkModel::BufferTypeRole: - return int(bufferType()); - case NetworkModel::ItemActiveRole: - return isActive(); - case NetworkModel::BufferActivityRole: - return (int)activityLevel(); - case NetworkModel::BufferFirstUnreadMsgIdRole: - return qVariantFromValue(firstUnreadMsgId()); - case NetworkModel::MarkerLineMsgIdRole: - return qVariantFromValue(markerLineMsgId()); - default: - return PropertyMapItem::data(column, role); - } -} - -bool BufferItem::setData(int column, const QVariant &value, int role) { - switch(role) { - case NetworkModel::BufferActivityRole: - setActivityLevel((BufferInfo::ActivityLevel)value.toInt()); + +QVariant BufferItem::data(int column, int role) const +{ + switch (role) { + case NetworkModel::ItemTypeRole: + return NetworkModel::BufferItemType; + case NetworkModel::BufferIdRole: + return qVariantFromValue(bufferInfo().bufferId()); + case NetworkModel::NetworkIdRole: + return qVariantFromValue(bufferInfo().networkId()); + case NetworkModel::BufferInfoRole: + return qVariantFromValue(bufferInfo()); + case NetworkModel::BufferTypeRole: + return int(bufferType()); + case NetworkModel::ItemActiveRole: + return isActive(); + case NetworkModel::BufferActivityRole: + return (int)activityLevel(); + case NetworkModel::BufferFirstUnreadMsgIdRole: + return qVariantFromValue(firstUnreadMsgId()); + case NetworkModel::MarkerLineMsgIdRole: + return qVariantFromValue(markerLineMsgId()); + default: + return PropertyMapItem::data(column, role); + } +} + + +bool BufferItem::setData(int column, const QVariant &value, int role) +{ + switch (role) { + case NetworkModel::BufferActivityRole: + setActivityLevel((BufferInfo::ActivityLevel)value.toInt()); + return true; + default: + return PropertyMapItem::setData(column, value, role); + } return true; - default: - return PropertyMapItem::setData(column, value, role); - } - return true; } -void BufferItem::setBufferName(const QString &name) { - _bufferInfo = BufferInfo(_bufferInfo.bufferId(), _bufferInfo.networkId(), _bufferInfo.type(), _bufferInfo.groupId(), name); - emit dataChanged(0); + +void BufferItem::setBufferName(const QString &name) +{ + _bufferInfo = BufferInfo(_bufferInfo.bufferId(), _bufferInfo.networkId(), _bufferInfo.type(), _bufferInfo.groupId(), name); + emit dataChanged(0); } -void BufferItem::setLastSeenMsgId(MsgId msgId) { - _lastSeenMsgId = msgId; - // FIXME remove with core protocol v11 - if(!(Client::coreFeatures() & Quassel::SynchronizedMarkerLine)) { - if(!isCurrentBuffer()) - _markerLineMsgId = msgId; - } +void BufferItem::setLastSeenMsgId(MsgId msgId) +{ + _lastSeenMsgId = msgId; + + // FIXME remove with core protocol v11 + if (!(Client::coreFeatures() & Quassel::SynchronizedMarkerLine)) { + if (!isCurrentBuffer()) + _markerLineMsgId = msgId; + } - setActivityLevel(BufferInfo::NoActivity); + setActivityLevel(BufferInfo::NoActivity); } -void BufferItem::setMarkerLineMsgId(MsgId msgId) { - _markerLineMsgId = msgId; - emit dataChanged(); + +void BufferItem::setMarkerLineMsgId(MsgId msgId) +{ + _markerLineMsgId = msgId; + emit dataChanged(); } -bool BufferItem::isCurrentBuffer() const { - return _bufferInfo.bufferId() == Client::bufferModel()->currentIndex().data(NetworkModel::BufferIdRole).value(); + +bool BufferItem::isCurrentBuffer() const +{ + return _bufferInfo.bufferId() == Client::bufferModel()->currentIndex().data(NetworkModel::BufferIdRole).value(); } -QString BufferItem::toolTip(int column) const { - Q_UNUSED(column); - return tr("

%1 - %2

").arg(bufferInfo().bufferId().toInt()).arg(bufferName()); + +QString BufferItem::toolTip(int column) const +{ + Q_UNUSED(column); + return tr("

%1 - %2

").arg(bufferInfo().bufferId().toInt()).arg(bufferName()); } + /***************************************** * StatusBufferItem *****************************************/ StatusBufferItem::StatusBufferItem(const BufferInfo &bufferInfo, NetworkItem *parent) - : BufferItem(bufferInfo, parent) + : BufferItem(bufferInfo, parent) { } -QString StatusBufferItem::toolTip(int column) const { - NetworkItem *networkItem = qobject_cast(parent()); - if(networkItem) - return networkItem->toolTip(column); - else - return QString(); + +QString StatusBufferItem::toolTip(int column) const +{ + NetworkItem *networkItem = qobject_cast(parent()); + if (networkItem) + return networkItem->toolTip(column); + else + return QString(); } + /***************************************** * QueryBufferItem *****************************************/ QueryBufferItem::QueryBufferItem(const BufferInfo &bufferInfo, NetworkItem *parent) - : BufferItem(bufferInfo, parent), + : BufferItem(bufferInfo, parent), _ircUser(0) { - setFlags(flags() | Qt::ItemIsDropEnabled | Qt::ItemIsEditable); + setFlags(flags() | Qt::ItemIsDropEnabled | Qt::ItemIsEditable); - const Network *net = Client::network(bufferInfo.networkId()); - if(!net) - return; + const Network *net = Client::network(bufferInfo.networkId()); + if (!net) + return; - IrcUser *ircUser = net->ircUser(bufferInfo.bufferName()); - setIrcUser(ircUser); + IrcUser *ircUser = net->ircUser(bufferInfo.bufferName()); + setIrcUser(ircUser); } -QVariant QueryBufferItem::data(int column, int role) const { - switch(role) { - case Qt::EditRole: - return BufferItem::data(column, Qt::DisplayRole); - case NetworkModel::IrcUserRole: - return QVariant::fromValue(_ircUser); - case NetworkModel::UserAwayRole: - return (bool)_ircUser ? _ircUser->isAway() : false; - default: - return BufferItem::data(column, role); - } + +QVariant QueryBufferItem::data(int column, int role) const +{ + switch (role) { + case Qt::EditRole: + return BufferItem::data(column, Qt::DisplayRole); + case NetworkModel::IrcUserRole: + return QVariant::fromValue(_ircUser); + case NetworkModel::UserAwayRole: + return (bool)_ircUser ? _ircUser->isAway() : false; + default: + return BufferItem::data(column, role); + } } -bool QueryBufferItem::setData(int column, const QVariant &value, int role) { - if(column != 0) - return BufferItem::setData(column, value, role); - switch(role) { - case Qt::EditRole: +bool QueryBufferItem::setData(int column, const QVariant &value, int role) +{ + if (column != 0) + return BufferItem::setData(column, value, role); + + switch (role) { + case Qt::EditRole: { - QString newName = value.toString(); - if(!newName.isEmpty()) { - Client::renameBuffer(bufferId(), newName); - return true; - } else { - return false; - } + QString newName = value.toString(); + if (!newName.isEmpty()) { + Client::renameBuffer(bufferId(), newName); + return true; + } + else { + return false; + } } break; - default: - return BufferItem::setData(column, value, role); - } + default: + return BufferItem::setData(column, value, role); + } } -void QueryBufferItem::setBufferName(const QString &name) { - BufferItem::setBufferName(name); - NetworkId netId = data(0, NetworkModel::NetworkIdRole).value(); - const Network *net = Client::network(netId); - if(net) - setIrcUser(net->ircUser(name)); -} -QString QueryBufferItem::toolTip(int column) const { - // pretty much code duplication of IrcUserItem::toolTip() but inheritance won't solve this... - Q_UNUSED(column); - QStringList toolTip; +void QueryBufferItem::setBufferName(const QString &name) +{ + BufferItem::setBufferName(name); + NetworkId netId = data(0, NetworkModel::NetworkIdRole).value(); + const Network *net = Client::network(netId); + if (net) + setIrcUser(net->ircUser(name)); +} - toolTip.append(tr("Query with %1").arg(bufferName())); - if(_ircUser) { - if(_ircUser->userModes() != "") toolTip[0].append(QString(" (+%1)").arg(_ircUser->userModes())); - if(_ircUser->isAway()) { - toolTip[0].append(QString(" (away%1)").arg(!_ircUser->awayMessage().isEmpty() ? (QString(" ") + _ircUser->awayMessage()) : QString())); +QString QueryBufferItem::toolTip(int column) const +{ + // pretty much code duplication of IrcUserItem::toolTip() but inheritance won't solve this... + Q_UNUSED(column); + QStringList toolTip; + + toolTip.append(tr("Query with %1").arg(bufferName())); + + if (_ircUser) { + if (_ircUser->userModes() != "") toolTip[0].append(QString(" (+%1)").arg(_ircUser->userModes())); + if (_ircUser->isAway()) { + toolTip[0].append(QString(" (away%1)").arg(!_ircUser->awayMessage().isEmpty() ? (QString(" ") + _ircUser->awayMessage()) : QString())); + } + if (!_ircUser->realName().isEmpty()) toolTip.append(_ircUser->realName()); + if (!_ircUser->ircOperator().isEmpty()) toolTip.append(QString("%1 %2").arg(_ircUser->nick()).arg(_ircUser->ircOperator())); + if (!_ircUser->suserHost().isEmpty()) toolTip.append(_ircUser->suserHost()); + if (!_ircUser->whoisServiceReply().isEmpty()) toolTip.append(_ircUser->whoisServiceReply()); + + toolTip.append(_ircUser->hostmask().remove(0, _ircUser->hostmask().indexOf("!")+1)); + + if (_ircUser->idleTime().isValid()) { + QDateTime now = QDateTime::currentDateTime(); + QDateTime idle = _ircUser->idleTime(); + int idleTime = idle.secsTo(now); + toolTip.append(tr("idling since %1").arg(secondsToString(idleTime))); + } + if (_ircUser->loginTime().isValid()) { + toolTip.append(tr("login time: %1").arg(_ircUser->loginTime().toString())); + } + + if (!_ircUser->server().isEmpty()) toolTip.append(tr("server: %1").arg(_ircUser->server())); } - if(!_ircUser->realName().isEmpty()) toolTip.append(_ircUser->realName()); - if(!_ircUser->ircOperator().isEmpty()) toolTip.append(QString("%1 %2").arg(_ircUser->nick()).arg(_ircUser->ircOperator())); - if(!_ircUser->suserHost().isEmpty()) toolTip.append(_ircUser->suserHost()); - if(!_ircUser->whoisServiceReply().isEmpty()) toolTip.append(_ircUser->whoisServiceReply()); - toolTip.append(_ircUser->hostmask().remove(0, _ircUser->hostmask().indexOf("!")+1)); + return QString("

%1

").arg(toolTip.join("
")); +} - if(_ircUser->idleTime().isValid()) { - QDateTime now = QDateTime::currentDateTime(); - QDateTime idle = _ircUser->idleTime(); - int idleTime = idle.secsTo(now); - toolTip.append(tr("idling since %1").arg(secondsToString(idleTime))); - } - if(_ircUser->loginTime().isValid()) { - toolTip.append(tr("login time: %1").arg(_ircUser->loginTime().toString())); - } - if(!_ircUser->server().isEmpty()) toolTip.append(tr("server: %1").arg(_ircUser->server())); - } +void QueryBufferItem::setIrcUser(IrcUser *ircUser) +{ + if (_ircUser == ircUser) + return; - return QString("

%1

").arg(toolTip.join("
")); -} + if (_ircUser) { + disconnect(_ircUser, 0, this, 0); + } -void QueryBufferItem::setIrcUser(IrcUser *ircUser) { - if(_ircUser == ircUser) - return; + if (ircUser) { + connect(ircUser, SIGNAL(quited()), this, SLOT(removeIrcUser())); + connect(ircUser, SIGNAL(awaySet(bool)), this, SIGNAL(dataChanged())); + } - if(_ircUser) { - disconnect(_ircUser, 0, this, 0); - } + _ircUser = ircUser; + emit dataChanged(); +} - if(ircUser) { - connect(ircUser, SIGNAL(quited()), this, SLOT(removeIrcUser())); - connect(ircUser, SIGNAL(awaySet(bool)), this, SIGNAL(dataChanged())); - } - _ircUser = ircUser; - emit dataChanged(); +void QueryBufferItem::removeIrcUser() +{ + _ircUser = 0; + emit dataChanged(); } -void QueryBufferItem::removeIrcUser() { - _ircUser = 0; - emit dataChanged(); -} /***************************************** * ChannelBufferItem *****************************************/ ChannelBufferItem::ChannelBufferItem(const BufferInfo &bufferInfo, AbstractTreeItem *parent) - : BufferItem(bufferInfo, parent), + : BufferItem(bufferInfo, parent), _ircChannel(0) { } -QVariant ChannelBufferItem::data(int column, int role) const { - switch(role) { + +QVariant ChannelBufferItem::data(int column, int role) const +{ + switch (role) { case NetworkModel::IrcChannelRole: - return QVariant::fromValue(_ircChannel); + return QVariant::fromValue(_ircChannel); default: - return BufferItem::data(column, role); - } -} - -QString ChannelBufferItem::toolTip(int column) const { - Q_UNUSED(column); - QStringList toolTip; - - toolTip.append(tr("Channel %1").arg(Qt::escape(bufferName()))); - if(isActive()) { - //TODO: add channel modes - toolTip.append(tr("Users: %1").arg(nickCount())); - if(_ircChannel) { - QString channelMode = _ircChannel->channelModeString(); // channelModeString is compiled on the fly -> thus cache the result - if(!channelMode.isEmpty()) - toolTip.append(tr("Mode: %1").arg(channelMode)); + return BufferItem::data(column, role); } +} + - ItemViewSettings s; - bool showTopic = s.displayTopicInTooltip(); - if(showTopic) { - QString _topic = topic(); - if(_topic != "") { - _topic = stripFormatCodes(_topic); - _topic = Qt::escape(_topic); - toolTip.append(QString(" ")); - toolTip.append(tr("Topic: %1").arg(_topic)); - } +QString ChannelBufferItem::toolTip(int column) const +{ + Q_UNUSED(column); + QStringList toolTip; + + toolTip.append(tr("Channel %1").arg(Qt::escape(bufferName()))); + if (isActive()) { + //TODO: add channel modes + toolTip.append(tr("Users: %1").arg(nickCount())); + if (_ircChannel) { + QString channelMode = _ircChannel->channelModeString(); // channelModeString is compiled on the fly -> thus cache the result + if (!channelMode.isEmpty()) + toolTip.append(tr("Mode: %1").arg(channelMode)); + } + + ItemViewSettings s; + bool showTopic = s.displayTopicInTooltip(); + if (showTopic) { + QString _topic = topic(); + if (_topic != "") { + _topic = stripFormatCodes(_topic); + _topic = Qt::escape(_topic); + toolTip.append(QString(" ")); + toolTip.append(tr("Topic: %1").arg(_topic)); + } + } + } + else { + toolTip.append(tr("Not active
Double-click to join")); } - } else { - toolTip.append(tr("Not active
Double-click to join")); - } - return tr("

%1

").arg(toolTip.join("
")); + return tr("

%1

").arg(toolTip.join("
")); } -void ChannelBufferItem::attachIrcChannel(IrcChannel *ircChannel) { - Q_ASSERT(!_ircChannel && ircChannel); - _ircChannel = ircChannel; +void ChannelBufferItem::attachIrcChannel(IrcChannel *ircChannel) +{ + Q_ASSERT(!_ircChannel && ircChannel); + + _ircChannel = ircChannel; + + connect(ircChannel, SIGNAL(topicSet(QString)), + this, SLOT(setTopic(QString))); + connect(ircChannel, SIGNAL(ircUsersJoined(QList )), + this, SLOT(join(QList ))); + connect(ircChannel, SIGNAL(ircUserParted(IrcUser *)), + this, SLOT(part(IrcUser *))); + connect(ircChannel, SIGNAL(parted()), + this, SLOT(ircChannelParted())); + connect(ircChannel, SIGNAL(ircUserModesSet(IrcUser *, QString)), + this, SLOT(userModeChanged(IrcUser *))); + connect(ircChannel, SIGNAL(ircUserModeAdded(IrcUser *, QString)), + this, SLOT(userModeChanged(IrcUser *))); + connect(ircChannel, SIGNAL(ircUserModeRemoved(IrcUser *, QString)), + this, SLOT(userModeChanged(IrcUser *))); + + if (!ircChannel->ircUsers().isEmpty()) + join(ircChannel->ircUsers()); - connect(ircChannel, SIGNAL(topicSet(QString)), - this, SLOT(setTopic(QString))); - connect(ircChannel, SIGNAL(ircUsersJoined(QList)), - this, SLOT(join(QList))); - connect(ircChannel, SIGNAL(ircUserParted(IrcUser *)), - this, SLOT(part(IrcUser *))); - connect(ircChannel, SIGNAL(parted()), - this, SLOT(ircChannelParted())); - connect(ircChannel, SIGNAL(ircUserModesSet(IrcUser *, QString)), - this, SLOT(userModeChanged(IrcUser *))); - connect(ircChannel, SIGNAL(ircUserModeAdded(IrcUser *, QString)), - this, SLOT(userModeChanged(IrcUser *))); - connect(ircChannel, SIGNAL(ircUserModeRemoved(IrcUser *, QString)), - this, SLOT(userModeChanged(IrcUser *))); + emit dataChanged(); +} - if(!ircChannel->ircUsers().isEmpty()) - join(ircChannel->ircUsers()); - emit dataChanged(); +void ChannelBufferItem::ircChannelParted() +{ + Q_CHECK_PTR(_ircChannel); + disconnect(_ircChannel, 0, this, 0); + _ircChannel = 0; + emit dataChanged(); + removeAllChilds(); } -void ChannelBufferItem::ircChannelParted() { - Q_CHECK_PTR(_ircChannel); - disconnect(_ircChannel, 0, this, 0); - _ircChannel = 0; - emit dataChanged(); - removeAllChilds(); + +void ChannelBufferItem::join(const QList &ircUsers) +{ + addUsersToCategory(ircUsers); + emit dataChanged(2); } -void ChannelBufferItem::join(const QList &ircUsers) { - addUsersToCategory(ircUsers); - emit dataChanged(2); + +UserCategoryItem *ChannelBufferItem::findCategoryItem(int categoryId) +{ + UserCategoryItem *categoryItem = 0; + + for (int i = 0; i < childCount(); i++) { + categoryItem = qobject_cast(child(i)); + if (!categoryItem) + continue; + if (categoryItem->categoryId() == categoryId) + return categoryItem; + } + return 0; } -UserCategoryItem *ChannelBufferItem::findCategoryItem(int categoryId) { - UserCategoryItem *categoryItem = 0; - for(int i = 0; i < childCount(); i++) { - categoryItem = qobject_cast(child(i)); - if(!categoryItem) - continue; - if(categoryItem->categoryId() == categoryId) - return categoryItem; - } - return 0; +void ChannelBufferItem::addUserToCategory(IrcUser *ircUser) +{ + addUsersToCategory(QList() << ircUser); } -void ChannelBufferItem::addUserToCategory(IrcUser *ircUser) { - addUsersToCategory(QList() << ircUser); + +void ChannelBufferItem::addUsersToCategory(const QList &ircUsers) +{ + Q_ASSERT(_ircChannel); + + QHash > categories; + + int categoryId = -1; + UserCategoryItem *categoryItem = 0; + + foreach(IrcUser *ircUser, ircUsers) { + categoryId = UserCategoryItem::categoryFromModes(_ircChannel->userModes(ircUser)); + categoryItem = findCategoryItem(categoryId); + if (!categoryItem) { + categoryItem = new UserCategoryItem(categoryId, this); + categories[categoryItem] = QList(); + newChild(categoryItem); + } + categories[categoryItem] << ircUser; + } + + QHash >::const_iterator catIter = categories.constBegin(); + while (catIter != categories.constEnd()) { + catIter.key()->addUsers(catIter.value()); + catIter++; + } } -void ChannelBufferItem::addUsersToCategory(const QList &ircUsers) { - Q_ASSERT(_ircChannel); - QHash > categories; +void ChannelBufferItem::part(IrcUser *ircUser) +{ + if (!ircUser) { + qWarning() << bufferName() << "ChannelBufferItem::part(): unknown User" << ircUser; + return; + } + + disconnect(ircUser, 0, this, 0); + removeUserFromCategory(ircUser); + emit dataChanged(2); +} - int categoryId = -1; - UserCategoryItem *categoryItem = 0; - foreach(IrcUser *ircUser, ircUsers) { - categoryId = UserCategoryItem::categoryFromModes(_ircChannel->userModes(ircUser)); - categoryItem = findCategoryItem(categoryId); - if(!categoryItem) { - categoryItem = new UserCategoryItem(categoryId, this); - categories[categoryItem] = QList(); - newChild(categoryItem); +void ChannelBufferItem::removeUserFromCategory(IrcUser *ircUser) +{ + if (!_ircChannel) { + // If we parted the channel there might still be some ircUsers connected. + // in that case we just ignore the call + Q_ASSERT(childCount() == 0); + return; } - categories[categoryItem] << ircUser; - } - - QHash >::const_iterator catIter = categories.constBegin(); - while(catIter != categories.constEnd()) { - catIter.key()->addUsers(catIter.value()); - catIter++; - } -} - -void ChannelBufferItem::part(IrcUser *ircUser) { - if(!ircUser) { - qWarning() << bufferName() << "ChannelBufferItem::part(): unknown User" << ircUser; - return; - } - - disconnect(ircUser, 0, this, 0); - removeUserFromCategory(ircUser); - emit dataChanged(2); -} - -void ChannelBufferItem::removeUserFromCategory(IrcUser *ircUser) { - if(!_ircChannel) { - // If we parted the channel there might still be some ircUsers connected. - // in that case we just ignore the call - Q_ASSERT(childCount() == 0); - return; - } - - UserCategoryItem *categoryItem = 0; - for(int i = 0; i < childCount(); i++) { - categoryItem = qobject_cast(child(i)); - if(categoryItem->removeUser(ircUser)) { - if(categoryItem->childCount() == 0) - removeChild(i); - break; + + UserCategoryItem *categoryItem = 0; + for (int i = 0; i < childCount(); i++) { + categoryItem = qobject_cast(child(i)); + if (categoryItem->removeUser(ircUser)) { + if (categoryItem->childCount() == 0) + removeChild(i); + break; + } } - } } -void ChannelBufferItem::userModeChanged(IrcUser *ircUser) { - Q_ASSERT(_ircChannel); - int categoryId = UserCategoryItem::categoryFromModes(_ircChannel->userModes(ircUser)); - UserCategoryItem *categoryItem = findCategoryItem(categoryId); +void ChannelBufferItem::userModeChanged(IrcUser *ircUser) +{ + Q_ASSERT(_ircChannel); + + int categoryId = UserCategoryItem::categoryFromModes(_ircChannel->userModes(ircUser)); + UserCategoryItem *categoryItem = findCategoryItem(categoryId); - if(categoryItem) { - if(categoryItem->findIrcUser(ircUser)) { - return; // already in the right category; + if (categoryItem) { + if (categoryItem->findIrcUser(ircUser)) { + return; // already in the right category; + } } - } else { - categoryItem = new UserCategoryItem(categoryId, this); - newChild(categoryItem); - } - - // find the item that needs reparenting - IrcUserItem *ircUserItem = 0; - for(int i = 0; i < childCount(); i++) { - UserCategoryItem *oldCategoryItem = qobject_cast(child(i)); - Q_ASSERT(oldCategoryItem); - IrcUserItem *userItem = oldCategoryItem->findIrcUser(ircUser); - if(userItem) { - ircUserItem = userItem; - break; + else { + categoryItem = new UserCategoryItem(categoryId, this); + newChild(categoryItem); } - } - if(!ircUserItem) { - qWarning() << "ChannelBufferItem::userModeChanged(IrcUser *): unable to determine old category of" << ircUser; - return; - } - ircUserItem->reParent(categoryItem); + // find the item that needs reparenting + IrcUserItem *ircUserItem = 0; + for (int i = 0; i < childCount(); i++) { + UserCategoryItem *oldCategoryItem = qobject_cast(child(i)); + Q_ASSERT(oldCategoryItem); + IrcUserItem *userItem = oldCategoryItem->findIrcUser(ircUser); + if (userItem) { + ircUserItem = userItem; + break; + } + } + + if (!ircUserItem) { + qWarning() << "ChannelBufferItem::userModeChanged(IrcUser *): unable to determine old category of" << ircUser; + return; + } + ircUserItem->reParent(categoryItem); } + /***************************************** * User Category Items (like @vh etc.) *****************************************/ @@ -683,83 +765,101 @@ void ChannelBufferItem::userModeChanged(IrcUser *ircUser) { const QList UserCategoryItem::categories = QList() << 'q' << 'a' << 'o' << 'h' << 'v'; UserCategoryItem::UserCategoryItem(int category, AbstractTreeItem *parent) - : PropertyMapItem(QStringList() << "categoryName", parent), + : PropertyMapItem(QStringList() << "categoryName", parent), _category(category) { - setFlags(Qt::ItemIsEnabled); - setTreeItemFlags(AbstractTreeItem::DeleteOnLastChildRemoved); - setObjectName(parent->data(0, Qt::DisplayRole).toString() + "/" + QString::number(category)); + setFlags(Qt::ItemIsEnabled); + setTreeItemFlags(AbstractTreeItem::DeleteOnLastChildRemoved); + setObjectName(parent->data(0, Qt::DisplayRole).toString() + "/" + QString::number(category)); } + // caching this makes no sense, since we display the user number dynamically -QString UserCategoryItem::categoryName() const { - int n = childCount(); - switch(_category) { - case 0: return tr("%n Owner(s)", 0, n); - case 1: return tr("%n Admin(s)", 0, n); - case 2: return tr("%n Operator(s)", 0, n); - case 3: return tr("%n Half-Op(s)", 0, n); - case 4: return tr("%n Voiced", 0, n); - default: return tr("%n User(s)", 0, n); - } -} - -IrcUserItem *UserCategoryItem::findIrcUser(IrcUser *ircUser) { - IrcUserItem *userItem = 0; - - for(int i = 0; i < childCount(); i++) { - userItem = qobject_cast(child(i)); - if(!userItem) - continue; - if(userItem->ircUser() == ircUser) - return userItem; - } - return 0; -} - -void UserCategoryItem::addUsers(const QList &ircUsers) { - QList userItems; - foreach(IrcUser *ircUser, ircUsers) - userItems << new IrcUserItem(ircUser, this); - newChilds(userItems); - emit dataChanged(0); +QString UserCategoryItem::categoryName() const +{ + int n = childCount(); + switch (_category) { + case 0: + return tr("%n Owner(s)", 0, n); + case 1: + return tr("%n Admin(s)", 0, n); + case 2: + return tr("%n Operator(s)", 0, n); + case 3: + return tr("%n Half-Op(s)", 0, n); + case 4: + return tr("%n Voiced", 0, n); + default: + return tr("%n User(s)", 0, n); + } } -bool UserCategoryItem::removeUser(IrcUser *ircUser) { - IrcUserItem *userItem = findIrcUser(ircUser); - bool success = (bool)userItem; - if(success) { - removeChild(userItem); + +IrcUserItem *UserCategoryItem::findIrcUser(IrcUser *ircUser) +{ + IrcUserItem *userItem = 0; + + for (int i = 0; i < childCount(); i++) { + userItem = qobject_cast(child(i)); + if (!userItem) + continue; + if (userItem->ircUser() == ircUser) + return userItem; + } + return 0; +} + + +void UserCategoryItem::addUsers(const QList &ircUsers) +{ + QList userItems; + foreach(IrcUser *ircUser, ircUsers) + userItems << new IrcUserItem(ircUser, this); + newChilds(userItems); emit dataChanged(0); - } - return success; } -int UserCategoryItem::categoryFromModes(const QString &modes) { - for(int i = 0; i < categories.count(); i++) { - if(modes.contains(categories[i])) - return i; - } - return categories.count(); + +bool UserCategoryItem::removeUser(IrcUser *ircUser) +{ + IrcUserItem *userItem = findIrcUser(ircUser); + bool success = (bool)userItem; + if (success) { + removeChild(userItem); + emit dataChanged(0); + } + return success; } -QVariant UserCategoryItem::data(int column, int role) const { - switch(role) { - case TreeModel::SortRole: - return _category; - case NetworkModel::ItemActiveRole: - return true; - case NetworkModel::ItemTypeRole: - return NetworkModel::UserCategoryItemType; - case NetworkModel::BufferIdRole: - return parent()->data(column, role); - case NetworkModel::NetworkIdRole: - return parent()->data(column, role); - case NetworkModel::BufferInfoRole: - return parent()->data(column, role); - default: - return PropertyMapItem::data(column, role); - } + +int UserCategoryItem::categoryFromModes(const QString &modes) +{ + for (int i = 0; i < categories.count(); i++) { + if (modes.contains(categories[i])) + return i; + } + return categories.count(); +} + + +QVariant UserCategoryItem::data(int column, int role) const +{ + switch (role) { + case TreeModel::SortRole: + return _category; + case NetworkModel::ItemActiveRole: + return true; + case NetworkModel::ItemTypeRole: + return NetworkModel::UserCategoryItemType; + case NetworkModel::BufferIdRole: + return parent()->data(column, role); + case NetworkModel::NetworkIdRole: + return parent()->data(column, role); + case NetworkModel::BufferInfoRole: + return parent()->data(column, role); + default: + return PropertyMapItem::data(column, role); + } } @@ -767,474 +867,558 @@ QVariant UserCategoryItem::data(int column, int role) const { * Irc User Items *****************************************/ IrcUserItem::IrcUserItem(IrcUser *ircUser, AbstractTreeItem *parent) - : PropertyMapItem(QStringList() << "nickName", parent), + : PropertyMapItem(QStringList() << "nickName", parent), _ircUser(ircUser) { - setObjectName(ircUser->nick()); - connect(ircUser, SIGNAL(quited()), this, SLOT(ircUserQuited())); - connect(ircUser, SIGNAL(nickSet(QString)), this, SIGNAL(dataChanged())); - connect(ircUser, SIGNAL(awaySet(bool)), this, SIGNAL(dataChanged())); -} - -QVariant IrcUserItem::data(int column, int role) const { - switch(role) { - case NetworkModel::ItemActiveRole: - return isActive(); - case NetworkModel::ItemTypeRole: - return NetworkModel::IrcUserItemType; - case NetworkModel::BufferIdRole: - return parent()->data(column, role); - case NetworkModel::NetworkIdRole: - return parent()->data(column, role); - case NetworkModel::BufferInfoRole: - return parent()->data(column, role); - case NetworkModel::IrcChannelRole: - return parent()->data(column, role); - case NetworkModel::IrcUserRole: - return QVariant::fromValue(_ircUser.data()); - case NetworkModel::UserAwayRole: - return (bool)_ircUser ? _ircUser->isAway() : false; - default: - return PropertyMapItem::data(column, role); - } -} - -QString IrcUserItem::toolTip(int column) const { - Q_UNUSED(column); - QStringList toolTip(QString("%1").arg(nickName())); - if(_ircUser->userModes() != "") toolTip[0].append(QString(" (%1)").arg(_ircUser->userModes())); - if(_ircUser->isAway()) { - toolTip[0].append(tr(" is away")); - if(!_ircUser->awayMessage().isEmpty()) - toolTip[0].append(QString(" (%1)").arg(_ircUser->awayMessage())); - } - if(!_ircUser->realName().isEmpty()) toolTip.append(_ircUser->realName()); - if(!_ircUser->ircOperator().isEmpty()) toolTip.append(QString("%1 %2").arg(nickName()).arg(_ircUser->ircOperator())); - if(!_ircUser->suserHost().isEmpty()) toolTip.append(_ircUser->suserHost()); - if(!_ircUser->whoisServiceReply().isEmpty()) toolTip.append(_ircUser->whoisServiceReply()); - - toolTip.append(_ircUser->hostmask().remove(0, _ircUser->hostmask().indexOf("!")+1)); - - if(_ircUser->idleTime().isValid()) { - QDateTime now = QDateTime::currentDateTime(); - QDateTime idle = _ircUser->idleTime(); - int idleTime = idle.secsTo(now); - toolTip.append(tr("idling since %1").arg(secondsToString(idleTime))); - } - if(_ircUser->loginTime().isValid()) { - toolTip.append(tr("login time: %1").arg(_ircUser->loginTime().toString())); - } - - if(!_ircUser->server().isEmpty()) toolTip.append(tr("server: %1").arg(_ircUser->server())); - - return QString("

%1

").arg(toolTip.join("
")); + setObjectName(ircUser->nick()); + connect(ircUser, SIGNAL(quited()), this, SLOT(ircUserQuited())); + connect(ircUser, SIGNAL(nickSet(QString)), this, SIGNAL(dataChanged())); + connect(ircUser, SIGNAL(awaySet(bool)), this, SIGNAL(dataChanged())); +} + + +QVariant IrcUserItem::data(int column, int role) const +{ + switch (role) { + case NetworkModel::ItemActiveRole: + return isActive(); + case NetworkModel::ItemTypeRole: + return NetworkModel::IrcUserItemType; + case NetworkModel::BufferIdRole: + return parent()->data(column, role); + case NetworkModel::NetworkIdRole: + return parent()->data(column, role); + case NetworkModel::BufferInfoRole: + return parent()->data(column, role); + case NetworkModel::IrcChannelRole: + return parent()->data(column, role); + case NetworkModel::IrcUserRole: + return QVariant::fromValue(_ircUser.data()); + case NetworkModel::UserAwayRole: + return (bool)_ircUser ? _ircUser->isAway() : false; + default: + return PropertyMapItem::data(column, role); + } } + +QString IrcUserItem::toolTip(int column) const +{ + Q_UNUSED(column); + QStringList toolTip(QString("%1").arg(nickName())); + if (_ircUser->userModes() != "") toolTip[0].append(QString(" (%1)").arg(_ircUser->userModes())); + if (_ircUser->isAway()) { + toolTip[0].append(tr(" is away")); + if (!_ircUser->awayMessage().isEmpty()) + toolTip[0].append(QString(" (%1)").arg(_ircUser->awayMessage())); + } + if (!_ircUser->realName().isEmpty()) toolTip.append(_ircUser->realName()); + if (!_ircUser->ircOperator().isEmpty()) toolTip.append(QString("%1 %2").arg(nickName()).arg(_ircUser->ircOperator())); + if (!_ircUser->suserHost().isEmpty()) toolTip.append(_ircUser->suserHost()); + if (!_ircUser->whoisServiceReply().isEmpty()) toolTip.append(_ircUser->whoisServiceReply()); + + toolTip.append(_ircUser->hostmask().remove(0, _ircUser->hostmask().indexOf("!")+1)); + + if (_ircUser->idleTime().isValid()) { + QDateTime now = QDateTime::currentDateTime(); + QDateTime idle = _ircUser->idleTime(); + int idleTime = idle.secsTo(now); + toolTip.append(tr("idling since %1").arg(secondsToString(idleTime))); + } + if (_ircUser->loginTime().isValid()) { + toolTip.append(tr("login time: %1").arg(_ircUser->loginTime().toString())); + } + + if (!_ircUser->server().isEmpty()) toolTip.append(tr("server: %1").arg(_ircUser->server())); + + return QString("

%1

").arg(toolTip.join("
")); +} + + /***************************************** * NetworkModel *****************************************/ NetworkModel::NetworkModel(QObject *parent) - : TreeModel(NetworkModel::defaultHeader(), parent) + : TreeModel(NetworkModel::defaultHeader(), parent) { - connect(this, SIGNAL(rowsInserted(const QModelIndex &, int, int)), - this, SLOT(checkForNewBuffers(const QModelIndex &, int, int))); - connect(this, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)), - this, SLOT(checkForRemovedBuffers(const QModelIndex &, int, int))); + connect(this, SIGNAL(rowsInserted(const QModelIndex &, int, int)), + this, SLOT(checkForNewBuffers(const QModelIndex &, int, int))); + connect(this, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)), + this, SLOT(checkForRemovedBuffers(const QModelIndex &, int, int))); - BufferSettings defaultSettings; - defaultSettings.notify("UserNoticesTarget", this, SLOT(messageRedirectionSettingsChanged())); - defaultSettings.notify("ServerNoticesTarget", this, SLOT(messageRedirectionSettingsChanged())); - defaultSettings.notify("ErrorMsgsTarget", this, SLOT(messageRedirectionSettingsChanged())); - messageRedirectionSettingsChanged(); + BufferSettings defaultSettings; + defaultSettings.notify("UserNoticesTarget", this, SLOT(messageRedirectionSettingsChanged())); + defaultSettings.notify("ServerNoticesTarget", this, SLOT(messageRedirectionSettingsChanged())); + defaultSettings.notify("ErrorMsgsTarget", this, SLOT(messageRedirectionSettingsChanged())); + messageRedirectionSettingsChanged(); } -QListNetworkModel::defaultHeader() { - QList data; - data << tr("Chat") << tr("Topic") << tr("Nick Count"); - return data; + +QList NetworkModel::defaultHeader() +{ + QList data; + data << tr("Chat") << tr("Topic") << tr("Nick Count"); + return data; } -bool NetworkModel::isBufferIndex(const QModelIndex &index) const { - return index.data(NetworkModel::ItemTypeRole) == NetworkModel::BufferItemType; + +bool NetworkModel::isBufferIndex(const QModelIndex &index) const +{ + return index.data(NetworkModel::ItemTypeRole) == NetworkModel::BufferItemType; } -int NetworkModel::networkRow(NetworkId networkId) const { - NetworkItem *netItem = 0; - for(int i = 0; i < rootItem->childCount(); i++) { - netItem = qobject_cast(rootItem->child(i)); - if(!netItem) - continue; - if(netItem->networkId() == networkId) - return i; - } - return -1; + +int NetworkModel::networkRow(NetworkId networkId) const +{ + NetworkItem *netItem = 0; + for (int i = 0; i < rootItem->childCount(); i++) { + netItem = qobject_cast(rootItem->child(i)); + if (!netItem) + continue; + if (netItem->networkId() == networkId) + return i; + } + return -1; } -QModelIndex NetworkModel::networkIndex(NetworkId networkId) { - int netRow = networkRow(networkId); - if(netRow == -1) - return QModelIndex(); - else - return indexByItem(qobject_cast(rootItem->child(netRow))); + +QModelIndex NetworkModel::networkIndex(NetworkId networkId) +{ + int netRow = networkRow(networkId); + if (netRow == -1) + return QModelIndex(); + else + return indexByItem(qobject_cast(rootItem->child(netRow))); } -NetworkItem *NetworkModel::findNetworkItem(NetworkId networkId) const { - int netRow = networkRow(networkId); - if(netRow == -1) - return 0; - else - return qobject_cast(rootItem->child(netRow)); + +NetworkItem *NetworkModel::findNetworkItem(NetworkId networkId) const +{ + int netRow = networkRow(networkId); + if (netRow == -1) + return 0; + else + return qobject_cast(rootItem->child(netRow)); } -NetworkItem *NetworkModel::networkItem(NetworkId networkId) { - NetworkItem *netItem = findNetworkItem(networkId); - if(netItem == 0) { - netItem = new NetworkItem(networkId, rootItem); - rootItem->newChild(netItem); - } - return netItem; +NetworkItem *NetworkModel::networkItem(NetworkId networkId) +{ + NetworkItem *netItem = findNetworkItem(networkId); + + if (netItem == 0) { + netItem = new NetworkItem(networkId, rootItem); + rootItem->newChild(netItem); + } + return netItem; } -void NetworkModel::networkRemoved(const NetworkId &networkId) { - int netRow = networkRow(networkId); - if(netRow != -1) { - rootItem->removeChild(netRow); - } + +void NetworkModel::networkRemoved(const NetworkId &networkId) +{ + int netRow = networkRow(networkId); + if (netRow != -1) { + rootItem->removeChild(netRow); + } } -QModelIndex NetworkModel::bufferIndex(BufferId bufferId) { - if(!_bufferItemCache.contains(bufferId)) - return QModelIndex(); - return indexByItem(_bufferItemCache[bufferId]); +QModelIndex NetworkModel::bufferIndex(BufferId bufferId) +{ + if (!_bufferItemCache.contains(bufferId)) + return QModelIndex(); + + return indexByItem(_bufferItemCache[bufferId]); } -BufferItem *NetworkModel::findBufferItem(BufferId bufferId) const { - if(_bufferItemCache.contains(bufferId)) - return _bufferItemCache[bufferId]; - else - return 0; + +BufferItem *NetworkModel::findBufferItem(BufferId bufferId) const +{ + if (_bufferItemCache.contains(bufferId)) + return _bufferItemCache[bufferId]; + else + return 0; } -BufferItem *NetworkModel::bufferItem(const BufferInfo &bufferInfo) { - if(_bufferItemCache.contains(bufferInfo.bufferId())) - return _bufferItemCache[bufferInfo.bufferId()]; - NetworkItem *netItem = networkItem(bufferInfo.networkId()); - return netItem->bufferItem(bufferInfo); +BufferItem *NetworkModel::bufferItem(const BufferInfo &bufferInfo) +{ + if (_bufferItemCache.contains(bufferInfo.bufferId())) + return _bufferItemCache[bufferInfo.bufferId()]; + + NetworkItem *netItem = networkItem(bufferInfo.networkId()); + return netItem->bufferItem(bufferInfo); } -QStringList NetworkModel::mimeTypes() const { - // mimetypes we accept for drops - QStringList types; - // comma separated list of colon separated pairs of networkid and bufferid - // example: 0:1,0:2,1:4 - types << "application/Quassel/BufferItemList"; - return types; + +QStringList NetworkModel::mimeTypes() const +{ + // mimetypes we accept for drops + QStringList types; + // comma separated list of colon separated pairs of networkid and bufferid + // example: 0:1,0:2,1:4 + types << "application/Quassel/BufferItemList"; + return types; } -bool NetworkModel::mimeContainsBufferList(const QMimeData *mimeData) { - return mimeData->hasFormat("application/Quassel/BufferItemList"); + +bool NetworkModel::mimeContainsBufferList(const QMimeData *mimeData) +{ + return mimeData->hasFormat("application/Quassel/BufferItemList"); } -QList< QPair > NetworkModel::mimeDataToBufferList(const QMimeData *mimeData) { - QList< QPair > bufferList; - if(!mimeContainsBufferList(mimeData)) +QList > NetworkModel::mimeDataToBufferList(const QMimeData *mimeData) +{ + QList > bufferList; + + if (!mimeContainsBufferList(mimeData)) + return bufferList; + + QStringList rawBufferList = QString::fromAscii(mimeData->data("application/Quassel/BufferItemList")).split(","); + NetworkId networkId; + BufferId bufferUid; + foreach(QString rawBuffer, rawBufferList) { + if (!rawBuffer.contains(":")) + continue; + networkId = rawBuffer.section(":", 0, 0).toInt(); + bufferUid = rawBuffer.section(":", 1, 1).toInt(); + bufferList.append(qMakePair(networkId, bufferUid)); + } return bufferList; - - QStringList rawBufferList = QString::fromAscii(mimeData->data("application/Quassel/BufferItemList")).split(","); - NetworkId networkId; - BufferId bufferUid; - foreach(QString rawBuffer, rawBufferList) { - if(!rawBuffer.contains(":")) - continue; - networkId = rawBuffer.section(":", 0, 0).toInt(); - bufferUid = rawBuffer.section(":", 1, 1).toInt(); - bufferList.append(qMakePair(networkId, bufferUid)); - } - return bufferList; } -QMimeData *NetworkModel::mimeData(const QModelIndexList &indexes) const { - QMimeData *mimeData = new QMimeData(); - - QStringList bufferlist; - QString netid, uid, bufferid; - foreach(QModelIndex index, indexes) { - netid = QString::number(index.data(NetworkIdRole).value().toInt()); - uid = QString::number(index.data(BufferIdRole).value().toInt()); - bufferid = QString("%1:%2").arg(netid).arg(uid); - if(!bufferlist.contains(bufferid)) - bufferlist << bufferid; - } +QMimeData *NetworkModel::mimeData(const QModelIndexList &indexes) const +{ + QMimeData *mimeData = new QMimeData(); + + QStringList bufferlist; + QString netid, uid, bufferid; + foreach(QModelIndex index, indexes) { + netid = QString::number(index.data(NetworkIdRole).value().toInt()); + uid = QString::number(index.data(BufferIdRole).value().toInt()); + bufferid = QString("%1:%2").arg(netid).arg(uid); + if (!bufferlist.contains(bufferid)) + bufferlist << bufferid; + } - mimeData->setData("application/Quassel/BufferItemList", bufferlist.join(",").toAscii()); + mimeData->setData("application/Quassel/BufferItemList", bufferlist.join(",").toAscii()); - return mimeData; + return mimeData; } -void NetworkModel::attachNetwork(Network *net) { - NetworkItem *netItem = networkItem(net->networkId()); - netItem->attachNetwork(net); + +void NetworkModel::attachNetwork(Network *net) +{ + NetworkItem *netItem = networkItem(net->networkId()); + netItem->attachNetwork(net); } -void NetworkModel::bufferUpdated(BufferInfo bufferInfo) { - BufferItem *bufItem = bufferItem(bufferInfo); - QModelIndex itemindex = indexByItem(bufItem); - emit dataChanged(itemindex, itemindex); + +void NetworkModel::bufferUpdated(BufferInfo bufferInfo) +{ + BufferItem *bufItem = bufferItem(bufferInfo); + QModelIndex itemindex = indexByItem(bufItem); + emit dataChanged(itemindex, itemindex); } -void NetworkModel::removeBuffer(BufferId bufferId) { - BufferItem *buffItem = findBufferItem(bufferId); - if(!buffItem) - return; - buffItem->parent()->removeChild(buffItem); +void NetworkModel::removeBuffer(BufferId bufferId) +{ + BufferItem *buffItem = findBufferItem(bufferId); + if (!buffItem) + return; + + buffItem->parent()->removeChild(buffItem); } -MsgId NetworkModel::lastSeenMsgId(BufferId bufferId) const { - if(!_bufferItemCache.contains(bufferId)) - return MsgId(); - return _bufferItemCache[bufferId]->lastSeenMsgId(); +MsgId NetworkModel::lastSeenMsgId(BufferId bufferId) const +{ + if (!_bufferItemCache.contains(bufferId)) + return MsgId(); + + return _bufferItemCache[bufferId]->lastSeenMsgId(); } -MsgId NetworkModel::markerLineMsgId(BufferId bufferId) const { - if(!_bufferItemCache.contains(bufferId)) - return MsgId(); - return _bufferItemCache[bufferId]->markerLineMsgId(); +MsgId NetworkModel::markerLineMsgId(BufferId bufferId) const +{ + if (!_bufferItemCache.contains(bufferId)) + return MsgId(); + + return _bufferItemCache[bufferId]->markerLineMsgId(); } + // FIXME we always seem to use this (expensive) non-const version -MsgId NetworkModel::lastSeenMsgId(const BufferId &bufferId) { - BufferItem *bufferItem = findBufferItem(bufferId); - if(!bufferItem) { - qDebug() << "NetworkModel::lastSeenMsgId(): buffer is unknown:" << bufferId; - Client::purgeKnownBufferIds(); - return MsgId(); - } - return bufferItem->lastSeenMsgId(); -} - -void NetworkModel::setLastSeenMsgId(const BufferId &bufferId, const MsgId &msgId) { - BufferItem *bufferItem = findBufferItem(bufferId); - if(!bufferItem) { - qDebug() << "NetworkModel::setLastSeenMsgId(): buffer is unknown:" << bufferId; - Client::purgeKnownBufferIds(); - return; - } - bufferItem->setLastSeenMsgId(msgId); - emit lastSeenMsgSet(bufferId, msgId); -} - -void NetworkModel::setMarkerLineMsgId(const BufferId &bufferId, const MsgId &msgId) { - BufferItem *bufferItem = findBufferItem(bufferId); - if(!bufferItem) { - qDebug() << "NetworkModel::setMarkerLineMsgId(): buffer is unknown:" << bufferId; - Client::purgeKnownBufferIds(); - return; - } - bufferItem->setMarkerLineMsgId(msgId); - emit markerLineSet(bufferId, msgId); -} - -void NetworkModel::updateBufferActivity(Message &msg) { - int redirectionTarget = 0; - switch(msg.type()) { - case Message::Notice: - if(bufferType(msg.bufferId()) != BufferInfo::ChannelBuffer) { - msg.setFlags(msg.flags() | Message::Redirected); - if(msg.flags() & Message::ServerMsg) { - // server notice - redirectionTarget = _serverNoticesTarget; - } else { - redirectionTarget = _userNoticesTarget; - } +MsgId NetworkModel::lastSeenMsgId(const BufferId &bufferId) +{ + BufferItem *bufferItem = findBufferItem(bufferId); + if (!bufferItem) { + qDebug() << "NetworkModel::lastSeenMsgId(): buffer is unknown:" << bufferId; + Client::purgeKnownBufferIds(); + return MsgId(); } - break; - case Message::Error: - msg.setFlags(msg.flags() | Message::Redirected); - redirectionTarget = _errorMsgsTarget; - break; - // Update IrcUser's last activity - case Message::Plain: - case Message::Action: - if(bufferType(msg.bufferId()) == BufferInfo::ChannelBuffer) { - const Network *net = Client::network(msg.bufferInfo().networkId()); - IrcUser *user = net ? net->ircUser(nickFromMask(msg.sender())) : 0; - if(user) - user->setLastChannelActivity(msg.bufferId(), msg.timestamp()); + return bufferItem->lastSeenMsgId(); +} + + +void NetworkModel::setLastSeenMsgId(const BufferId &bufferId, const MsgId &msgId) +{ + BufferItem *bufferItem = findBufferItem(bufferId); + if (!bufferItem) { + qDebug() << "NetworkModel::setLastSeenMsgId(): buffer is unknown:" << bufferId; + Client::purgeKnownBufferIds(); + return; } - break; - default: - break; - } + bufferItem->setLastSeenMsgId(msgId); + emit lastSeenMsgSet(bufferId, msgId); +} - if(msg.flags() & Message::Redirected) { - if(redirectionTarget & BufferSettings::DefaultBuffer) - updateBufferActivity(bufferItem(msg.bufferInfo()), msg); - if(redirectionTarget & BufferSettings::StatusBuffer) { - const NetworkItem *netItem = findNetworkItem(msg.bufferInfo().networkId()); - if(netItem) { - updateBufferActivity(netItem->statusBufferItem(), msg); - } +void NetworkModel::setMarkerLineMsgId(const BufferId &bufferId, const MsgId &msgId) +{ + BufferItem *bufferItem = findBufferItem(bufferId); + if (!bufferItem) { + qDebug() << "NetworkModel::setMarkerLineMsgId(): buffer is unknown:" << bufferId; + Client::purgeKnownBufferIds(); + return; } - } else { - updateBufferActivity(bufferItem(msg.bufferInfo()), msg); - } + bufferItem->setMarkerLineMsgId(msgId); + emit markerLineSet(bufferId, msgId); } -void NetworkModel::updateBufferActivity(BufferItem *bufferItem, const Message &msg) { - if(!bufferItem) - return; - bufferItem->updateActivityLevel(msg); - if(bufferItem->isCurrentBuffer()) - emit requestSetLastSeenMsg(bufferItem->bufferId(), msg.msgId()); +void NetworkModel::updateBufferActivity(Message &msg) +{ + int redirectionTarget = 0; + switch (msg.type()) { + case Message::Notice: + if (bufferType(msg.bufferId()) != BufferInfo::ChannelBuffer) { + msg.setFlags(msg.flags() | Message::Redirected); + if (msg.flags() & Message::ServerMsg) { + // server notice + redirectionTarget = _serverNoticesTarget; + } + else { + redirectionTarget = _userNoticesTarget; + } + } + break; + case Message::Error: + msg.setFlags(msg.flags() | Message::Redirected); + redirectionTarget = _errorMsgsTarget; + break; + // Update IrcUser's last activity + case Message::Plain: + case Message::Action: + if (bufferType(msg.bufferId()) == BufferInfo::ChannelBuffer) { + const Network *net = Client::network(msg.bufferInfo().networkId()); + IrcUser *user = net ? net->ircUser(nickFromMask(msg.sender())) : 0; + if (user) + user->setLastChannelActivity(msg.bufferId(), msg.timestamp()); + } + break; + default: + break; + } + + if (msg.flags() & Message::Redirected) { + if (redirectionTarget & BufferSettings::DefaultBuffer) + updateBufferActivity(bufferItem(msg.bufferInfo()), msg); + + if (redirectionTarget & BufferSettings::StatusBuffer) { + const NetworkItem *netItem = findNetworkItem(msg.bufferInfo().networkId()); + if (netItem) { + updateBufferActivity(netItem->statusBufferItem(), msg); + } + } + } + else { + updateBufferActivity(bufferItem(msg.bufferInfo()), msg); + } } -void NetworkModel::setBufferActivity(const BufferId &bufferId, BufferInfo::ActivityLevel level) { - BufferItem *bufferItem = findBufferItem(bufferId); - if(!bufferItem) { - qDebug() << "NetworkModel::setBufferActivity(): buffer is unknown:" << bufferId; - return; - } - bufferItem->setActivityLevel(level); + +void NetworkModel::updateBufferActivity(BufferItem *bufferItem, const Message &msg) +{ + if (!bufferItem) + return; + + bufferItem->updateActivityLevel(msg); + if (bufferItem->isCurrentBuffer()) + emit requestSetLastSeenMsg(bufferItem->bufferId(), msg.msgId()); } -void NetworkModel::clearBufferActivity(const BufferId &bufferId) { - BufferItem *bufferItem = findBufferItem(bufferId); - if(!bufferItem) { - qDebug() << "NetworkModel::clearBufferActivity(): buffer is unknown:" << bufferId; - return; - } - bufferItem->clearActivityLevel(); + +void NetworkModel::setBufferActivity(const BufferId &bufferId, BufferInfo::ActivityLevel level) +{ + BufferItem *bufferItem = findBufferItem(bufferId); + if (!bufferItem) { + qDebug() << "NetworkModel::setBufferActivity(): buffer is unknown:" << bufferId; + return; + } + bufferItem->setActivityLevel(level); } -const Network *NetworkModel::networkByIndex(const QModelIndex &index) const { - QVariant netVariant = index.data(NetworkIdRole); - if(!netVariant.isValid()) - return 0; - NetworkId networkId = netVariant.value(); - return Client::network(networkId); +void NetworkModel::clearBufferActivity(const BufferId &bufferId) +{ + BufferItem *bufferItem = findBufferItem(bufferId); + if (!bufferItem) { + qDebug() << "NetworkModel::clearBufferActivity(): buffer is unknown:" << bufferId; + return; + } + bufferItem->clearActivityLevel(); } -void NetworkModel::checkForRemovedBuffers(const QModelIndex &parent, int start, int end) { - if(parent.data(ItemTypeRole) != NetworkItemType) - return; - for(int row = start; row <= end; row++) { - _bufferItemCache.remove(parent.child(row, 0).data(BufferIdRole).value()); - } +const Network *NetworkModel::networkByIndex(const QModelIndex &index) const +{ + QVariant netVariant = index.data(NetworkIdRole); + if (!netVariant.isValid()) + return 0; + + NetworkId networkId = netVariant.value(); + return Client::network(networkId); } -void NetworkModel::checkForNewBuffers(const QModelIndex &parent, int start, int end) { - if(parent.data(ItemTypeRole) != NetworkItemType) - return; - for(int row = start; row <= end; row++) { - QModelIndex child = parent.child(row, 0); - _bufferItemCache[child.data(BufferIdRole).value()] = static_cast(child.internalPointer()); - } +void NetworkModel::checkForRemovedBuffers(const QModelIndex &parent, int start, int end) +{ + if (parent.data(ItemTypeRole) != NetworkItemType) + return; + + for (int row = start; row <= end; row++) { + _bufferItemCache.remove(parent.child(row, 0).data(BufferIdRole).value()); + } } -QString NetworkModel::bufferName(BufferId bufferId) const { - if(!_bufferItemCache.contains(bufferId)) - return QString(); - return _bufferItemCache[bufferId]->bufferName(); +void NetworkModel::checkForNewBuffers(const QModelIndex &parent, int start, int end) +{ + if (parent.data(ItemTypeRole) != NetworkItemType) + return; + + for (int row = start; row <= end; row++) { + QModelIndex child = parent.child(row, 0); + _bufferItemCache[child.data(BufferIdRole).value < BufferId > ()] = static_cast(child.internalPointer()); + } } -BufferInfo::Type NetworkModel::bufferType(BufferId bufferId) const { - if(!_bufferItemCache.contains(bufferId)) - return BufferInfo::InvalidBuffer; - return _bufferItemCache[bufferId]->bufferType(); +QString NetworkModel::bufferName(BufferId bufferId) const +{ + if (!_bufferItemCache.contains(bufferId)) + return QString(); + + return _bufferItemCache[bufferId]->bufferName(); } -BufferInfo NetworkModel::bufferInfo(BufferId bufferId) const { - if(!_bufferItemCache.contains(bufferId)) - return BufferInfo(); - return _bufferItemCache[bufferId]->bufferInfo(); +BufferInfo::Type NetworkModel::bufferType(BufferId bufferId) const +{ + if (!_bufferItemCache.contains(bufferId)) + return BufferInfo::InvalidBuffer; + + return _bufferItemCache[bufferId]->bufferType(); } -NetworkId NetworkModel::networkId(BufferId bufferId) const { - if(!_bufferItemCache.contains(bufferId)) - return NetworkId(); - NetworkItem *netItem = qobject_cast(_bufferItemCache[bufferId]->parent()); - if(netItem) - return netItem->networkId(); - else - return NetworkId(); +BufferInfo NetworkModel::bufferInfo(BufferId bufferId) const +{ + if (!_bufferItemCache.contains(bufferId)) + return BufferInfo(); + + return _bufferItemCache[bufferId]->bufferInfo(); } -QString NetworkModel::networkName(BufferId bufferId) const { - if(!_bufferItemCache.contains(bufferId)) - return QString(); - NetworkItem *netItem = qobject_cast(_bufferItemCache[bufferId]->parent()); - if(netItem) - return netItem->networkName(); - else - return QString(); +NetworkId NetworkModel::networkId(BufferId bufferId) const +{ + if (!_bufferItemCache.contains(bufferId)) + return NetworkId(); + + NetworkItem *netItem = qobject_cast(_bufferItemCache[bufferId]->parent()); + if (netItem) + return netItem->networkId(); + else + return NetworkId(); } -BufferId NetworkModel::bufferId(NetworkId networkId, const QString &bufferName, Qt::CaseSensitivity cs) const { - const NetworkItem *netItem = findNetworkItem(networkId); - if(!netItem) - return BufferId(); - for(int i = 0; i < netItem->childCount(); i++) { - BufferItem *bufferItem = qobject_cast(netItem->child(i)); - if(bufferItem && !bufferItem->bufferName().compare(bufferName, cs)) - return bufferItem->bufferId(); - } - return BufferId(); +QString NetworkModel::networkName(BufferId bufferId) const +{ + if (!_bufferItemCache.contains(bufferId)) + return QString(); + + NetworkItem *netItem = qobject_cast(_bufferItemCache[bufferId]->parent()); + if (netItem) + return netItem->networkName(); + else + return QString(); } -void NetworkModel::sortBufferIds(QList &bufferIds) const { - QList bufferItems; - foreach(BufferId bufferId, bufferIds) { - if(_bufferItemCache.contains(bufferId)) - bufferItems << _bufferItemCache[bufferId]; - } - qSort(bufferItems.begin(), bufferItems.end(), bufferItemLessThan); +BufferId NetworkModel::bufferId(NetworkId networkId, const QString &bufferName, Qt::CaseSensitivity cs) const +{ + const NetworkItem *netItem = findNetworkItem(networkId); + if (!netItem) + return BufferId(); + + for (int i = 0; i < netItem->childCount(); i++) { + BufferItem *bufferItem = qobject_cast(netItem->child(i)); + if (bufferItem && !bufferItem->bufferName().compare(bufferName, cs)) + return bufferItem->bufferId(); + } + return BufferId(); +} + + +void NetworkModel::sortBufferIds(QList &bufferIds) const +{ + QList bufferItems; + foreach(BufferId bufferId, bufferIds) { + if (_bufferItemCache.contains(bufferId)) + bufferItems << _bufferItemCache[bufferId]; + } + + qSort(bufferItems.begin(), bufferItems.end(), bufferItemLessThan); - bufferIds.clear(); - foreach(BufferItem *bufferItem, bufferItems) { - bufferIds << bufferItem->bufferId(); - } + bufferIds.clear(); + foreach(BufferItem *bufferItem, bufferItems) { + bufferIds << bufferItem->bufferId(); + } } -QList NetworkModel::allBufferIdsSorted() const { - QList bufferIds = allBufferIds(); - sortBufferIds(bufferIds); - return bufferIds; + +QList NetworkModel::allBufferIdsSorted() const +{ + QList bufferIds = allBufferIds(); + sortBufferIds(bufferIds); + return bufferIds; } -bool NetworkModel::bufferItemLessThan(const BufferItem *left, const BufferItem *right) { - int leftType = left->bufferType(); - int rightType = right->bufferType(); - if(leftType != rightType) - return leftType < rightType; - else - return QString::compare(left->bufferName(), right->bufferName(), Qt::CaseInsensitive) < 0; +bool NetworkModel::bufferItemLessThan(const BufferItem *left, const BufferItem *right) +{ + int leftType = left->bufferType(); + int rightType = right->bufferType(); + + if (leftType != rightType) + return leftType < rightType; + else + return QString::compare(left->bufferName(), right->bufferName(), Qt::CaseInsensitive) < 0; } -void NetworkModel::messageRedirectionSettingsChanged() { - BufferSettings bufferSettings; - _userNoticesTarget = bufferSettings.userNoticesTarget(); - _serverNoticesTarget = bufferSettings.serverNoticesTarget(); - _errorMsgsTarget = bufferSettings.errorMsgsTarget(); +void NetworkModel::messageRedirectionSettingsChanged() +{ + BufferSettings bufferSettings; + + _userNoticesTarget = bufferSettings.userNoticesTarget(); + _serverNoticesTarget = bufferSettings.serverNoticesTarget(); + _errorMsgsTarget = bufferSettings.errorMsgsTarget(); } diff --git a/src/client/networkmodel.h b/src/client/networkmodel.h index daf82435..8c9e83ee 100644 --- a/src/client/networkmodel.h +++ b/src/client/networkmodel.h @@ -33,340 +33,356 @@ class StatusBufferItem; /***************************************** * Network Items *****************************************/ -class NetworkItem : public PropertyMapItem { - Q_OBJECT - Q_PROPERTY(QString networkName READ networkName) - Q_PROPERTY(QString currentServer READ currentServer) - Q_PROPERTY(int nickCount READ nickCount) +class NetworkItem : public PropertyMapItem +{ + Q_OBJECT + Q_PROPERTY(QString networkName READ networkName) + Q_PROPERTY(QString currentServer READ currentServer) + Q_PROPERTY(int nickCount READ nickCount) -public: - NetworkItem(const NetworkId &netid, AbstractTreeItem *parent = 0); +public : + NetworkItem(const NetworkId &netid, AbstractTreeItem *parent = 0); - virtual QVariant data(int column, int row) const; + virtual QVariant data(int column, int row) const; - inline bool isActive() const { return (bool)_network ? _network->isConnected() : false; } + inline bool isActive() const { return (bool)_network ? _network->isConnected() : false; } - inline const NetworkId &networkId() const { return _networkId; } - inline QString networkName() const { return (bool)_network ? _network->networkName() : QString(); } - inline QString currentServer() const { return (bool)_network ? _network->currentServer() : QString(); } - inline int nickCount() const { return (bool)_network ? _network->ircUsers().count() : 0; } + inline const NetworkId &networkId() const { return _networkId; } + inline QString networkName() const { return (bool)_network ? _network->networkName() : QString(); } + inline QString currentServer() const { return (bool)_network ? _network->currentServer() : QString(); } + inline int nickCount() const { return (bool)_network ? _network->ircUsers().count() : 0; } - virtual QString toolTip(int column) const; + virtual QString toolTip(int column) const; - BufferItem *findBufferItem(BufferId bufferId); - inline BufferItem *findBufferItem(const BufferInfo &bufferInfo) { return findBufferItem(bufferInfo.bufferId()); } - BufferItem *bufferItem(const BufferInfo &bufferInfo); - inline StatusBufferItem *statusBufferItem() const { return _statusBufferItem; } + BufferItem *findBufferItem(BufferId bufferId); + inline BufferItem *findBufferItem(const BufferInfo &bufferInfo) { return findBufferItem(bufferInfo.bufferId()); } + BufferItem *bufferItem(const BufferInfo &bufferInfo); + inline StatusBufferItem *statusBufferItem() const { return _statusBufferItem; } public slots: - void setNetworkName(const QString &networkName); - void setCurrentServer(const QString &serverName); + void setNetworkName(const QString &networkName); + void setCurrentServer(const QString &serverName); - void attachNetwork(Network *network); - void attachIrcChannel(IrcChannel *channel); - void attachIrcUser(IrcUser *ircUser); + void attachNetwork(Network *network); + void attachIrcChannel(IrcChannel *channel); + void attachIrcUser(IrcUser *ircUser); signals: - void networkDataChanged(int column = -1); + void networkDataChanged(int column = -1); private slots: - void onBeginRemoveChilds(int start, int end); + void onBeginRemoveChilds(int start, int end); private: - NetworkId _networkId; - StatusBufferItem *_statusBufferItem; + NetworkId _networkId; + StatusBufferItem *_statusBufferItem; - QPointer _network; + QPointer _network; }; + /***************************************** * Fancy Buffer Items *****************************************/ -class BufferItem : public PropertyMapItem { - Q_OBJECT - Q_PROPERTY(QString bufferName READ bufferName WRITE setBufferName) - Q_PROPERTY(QString topic READ topic) - Q_PROPERTY(int nickCount READ nickCount) +class BufferItem : public PropertyMapItem +{ + Q_OBJECT + Q_PROPERTY(QString bufferName READ bufferName WRITE setBufferName) + Q_PROPERTY(QString topic READ topic) + Q_PROPERTY(int nickCount READ nickCount) -public: - BufferItem(const BufferInfo &bufferInfo, AbstractTreeItem *parent = 0); +public : + BufferItem(const BufferInfo &bufferInfo, AbstractTreeItem *parent = 0); - inline const BufferInfo &bufferInfo() const { return _bufferInfo; } - virtual QVariant data(int column, int role) const; - virtual bool setData(int column, const QVariant &value, int role); + inline const BufferInfo &bufferInfo() const { return _bufferInfo; } + virtual QVariant data(int column, int role) const; + virtual bool setData(int column, const QVariant &value, int role); - inline BufferId bufferId() const { return _bufferInfo.bufferId(); } - inline BufferInfo::Type bufferType() const { return _bufferInfo.type(); } + inline BufferId bufferId() const { return _bufferInfo.bufferId(); } + inline BufferInfo::Type bufferType() const { return _bufferInfo.type(); } - virtual void setBufferName(const QString &name); - virtual inline QString bufferName() const { return _bufferInfo.bufferName(); } - virtual inline QString topic() const { return QString(); } - virtual inline int nickCount() const { return 0; } + virtual void setBufferName(const QString &name); + virtual inline QString bufferName() const { return _bufferInfo.bufferName(); } + virtual inline QString topic() const { return QString(); } + virtual inline int nickCount() const { return 0; } - virtual inline bool isActive() const { return qobject_cast(parent())->isActive(); } + virtual inline bool isActive() const { return qobject_cast(parent())->isActive(); } - inline MsgId lastSeenMsgId() const { return _lastSeenMsgId; } - inline MsgId markerLineMsgId() const { return _markerLineMsgId; } - void setLastSeenMsgId(MsgId msgId); - void setMarkerLineMsgId(MsgId msgId); + inline MsgId lastSeenMsgId() const { return _lastSeenMsgId; } + inline MsgId markerLineMsgId() const { return _markerLineMsgId; } + void setLastSeenMsgId(MsgId msgId); + void setMarkerLineMsgId(MsgId msgId); - inline BufferInfo::ActivityLevel activityLevel() const { return _activity; } - void setActivityLevel(BufferInfo::ActivityLevel level); - void clearActivityLevel(); - void updateActivityLevel(const Message &msg); + inline BufferInfo::ActivityLevel activityLevel() const { return _activity; } + void setActivityLevel(BufferInfo::ActivityLevel level); + void clearActivityLevel(); + void updateActivityLevel(const Message &msg); - inline const MsgId &firstUnreadMsgId() const { return _firstUnreadMsgId; } + inline const MsgId &firstUnreadMsgId() const { return _firstUnreadMsgId; } - bool isCurrentBuffer() const; - virtual QString toolTip(int column) const; + bool isCurrentBuffer() const; + virtual QString toolTip(int column) const; public slots: - virtual inline void setTopic(const QString &) { emit dataChanged(1); } + virtual inline void setTopic(const QString &) { emit dataChanged(1); } private: - BufferInfo _bufferInfo; - BufferInfo::ActivityLevel _activity; - MsgId _lastSeenMsgId; - MsgId _markerLineMsgId; - MsgId _firstUnreadMsgId; + BufferInfo _bufferInfo; + BufferInfo::ActivityLevel _activity; + MsgId _lastSeenMsgId; + MsgId _markerLineMsgId; + MsgId _firstUnreadMsgId; }; + /***************************************** * StatusBufferItem *****************************************/ -class StatusBufferItem : public BufferItem { - Q_OBJECT +class StatusBufferItem : public BufferItem +{ + Q_OBJECT public: - StatusBufferItem(const BufferInfo &bufferInfo, NetworkItem *parent); + StatusBufferItem(const BufferInfo &bufferInfo, NetworkItem *parent); - virtual QString toolTip(int column) const; - virtual inline QString bufferName() const { return tr("Status Buffer"); } + virtual QString toolTip(int column) const; + virtual inline QString bufferName() const { return tr("Status Buffer"); } }; + /***************************************** * QueryBufferItem *****************************************/ -class QueryBufferItem : public BufferItem { - Q_OBJECT +class QueryBufferItem : public BufferItem +{ + Q_OBJECT public: - QueryBufferItem(const BufferInfo &bufferInfo, NetworkItem *parent); + QueryBufferItem(const BufferInfo &bufferInfo, NetworkItem *parent); - virtual QVariant data(int column, int role) const; - virtual bool setData(int column, const QVariant &value, int role); + virtual QVariant data(int column, int role) const; + virtual bool setData(int column, const QVariant &value, int role); - virtual inline bool isActive() const { return (bool)_ircUser; } - virtual QString toolTip(int column) const; + virtual inline bool isActive() const { return (bool)_ircUser; } + virtual QString toolTip(int column) const; - virtual void setBufferName(const QString &name); + virtual void setBufferName(const QString &name); public slots: - void setIrcUser(IrcUser *ircUser); - void removeIrcUser(); + void setIrcUser(IrcUser *ircUser); + void removeIrcUser(); private: - IrcUser *_ircUser; + IrcUser *_ircUser; }; + /***************************************** * ChannelBufferItem *****************************************/ class UserCategoryItem; -class ChannelBufferItem : public BufferItem { - Q_OBJECT +class ChannelBufferItem : public BufferItem +{ + Q_OBJECT public: - ChannelBufferItem(const BufferInfo &bufferInfo, AbstractTreeItem *parent); + ChannelBufferItem(const BufferInfo &bufferInfo, AbstractTreeItem *parent); - virtual QVariant data(int column, int role) const; - virtual inline bool isActive() const { return (bool)_ircChannel; } - virtual QString toolTip(int column) const; + virtual QVariant data(int column, int role) const; + virtual inline bool isActive() const { return (bool)_ircChannel; } + virtual QString toolTip(int column) const; - virtual inline QString topic() const { return (bool)_ircChannel ? _ircChannel->topic() : QString(); } - virtual inline int nickCount() const { return (bool)_ircChannel ? _ircChannel->ircUsers().count() : 0; } + virtual inline QString topic() const { return (bool)_ircChannel ? _ircChannel->topic() : QString(); } + virtual inline int nickCount() const { return (bool)_ircChannel ? _ircChannel->ircUsers().count() : 0; } - void attachIrcChannel(IrcChannel *ircChannel); + void attachIrcChannel(IrcChannel *ircChannel); public slots: - void join(const QList &ircUsers); - void part(IrcUser *ircUser); + void join(const QList &ircUsers); + void part(IrcUser *ircUser); - UserCategoryItem *findCategoryItem(int categoryId); - void addUserToCategory(IrcUser *ircUser); - void addUsersToCategory(const QList &ircUser); - void removeUserFromCategory(IrcUser *ircUser); - void userModeChanged(IrcUser *ircUser); + UserCategoryItem *findCategoryItem(int categoryId); + void addUserToCategory(IrcUser *ircUser); + void addUsersToCategory(const QList &ircUser); + void removeUserFromCategory(IrcUser *ircUser); + void userModeChanged(IrcUser *ircUser); private slots: - void ircChannelParted(); + void ircChannelParted(); private: - IrcChannel *_ircChannel; + IrcChannel *_ircChannel; }; + /***************************************** * User Category Items (like @vh etc.) *****************************************/ class IrcUserItem; -class UserCategoryItem : public PropertyMapItem { - Q_OBJECT - Q_PROPERTY(QString categoryName READ categoryName) +class UserCategoryItem : public PropertyMapItem +{ + Q_OBJECT + Q_PROPERTY(QString categoryName READ categoryName) -public: - UserCategoryItem(int category, AbstractTreeItem *parent); +public : + UserCategoryItem(int category, AbstractTreeItem *parent); - QString categoryName() const; - inline int categoryId() const { return _category; } - virtual QVariant data(int column, int role) const; + QString categoryName() const; + inline int categoryId() const { return _category; } + virtual QVariant data(int column, int role) const; - IrcUserItem *findIrcUser(IrcUser *ircUser); - void addUsers(const QList &ircUser); - bool removeUser(IrcUser *ircUser); + IrcUserItem *findIrcUser(IrcUser *ircUser); + void addUsers(const QList &ircUser); + bool removeUser(IrcUser *ircUser); - static int categoryFromModes(const QString &modes); + static int categoryFromModes(const QString &modes); private: - int _category; + int _category; - static const QList categories; + static const QList categories; }; + /***************************************** * Irc User Items *****************************************/ -class IrcUserItem : public PropertyMapItem { - Q_OBJECT - Q_PROPERTY(QString nickName READ nickName) +class IrcUserItem : public PropertyMapItem +{ + Q_OBJECT + Q_PROPERTY(QString nickName READ nickName) -public: - IrcUserItem(IrcUser *ircUser, AbstractTreeItem *parent); +public : + IrcUserItem(IrcUser *ircUser, AbstractTreeItem *parent); - inline QString nickName() const { return _ircUser ? _ircUser->nick() : QString(); } - inline bool isActive() const { return _ircUser ? !_ircUser->isAway() : false; } + inline QString nickName() const { return _ircUser ? _ircUser->nick() : QString(); } + inline bool isActive() const { return _ircUser ? !_ircUser->isAway() : false; } - inline IrcUser *ircUser() { return _ircUser; } - virtual QVariant data(int column, int role) const; - virtual QString toolTip(int column) const; + inline IrcUser *ircUser() { return _ircUser; } + virtual QVariant data(int column, int role) const; + virtual QString toolTip(int column) const; private slots: - inline void ircUserQuited() { parent()->removeChild(this); } + inline void ircUserQuited() { parent()->removeChild(this); } private: - QPointer _ircUser; + QPointer _ircUser; }; /***************************************** * NetworkModel *****************************************/ -class NetworkModel : public TreeModel { - Q_OBJECT +class NetworkModel : public TreeModel +{ + Q_OBJECT public: - enum Role { - BufferTypeRole = TreeModel::UserRole, - ItemActiveRole, - BufferActivityRole, - BufferIdRole, - NetworkIdRole, - BufferInfoRole, - ItemTypeRole, - UserAwayRole, - IrcUserRole, - IrcChannelRole, - BufferFirstUnreadMsgIdRole, - MarkerLineMsgIdRole, - }; - - enum ItemType { - NetworkItemType = 0x01, - BufferItemType = 0x02, - UserCategoryItemType = 0x04, - IrcUserItemType = 0x08 - }; - Q_DECLARE_FLAGS(ItemTypes, ItemType) - - NetworkModel(QObject *parent = 0); - static QList defaultHeader(); - - static bool mimeContainsBufferList(const QMimeData *mimeData); - static QList< QPair > mimeDataToBufferList(const QMimeData *mimeData); - - virtual QStringList mimeTypes() const; - virtual QMimeData *mimeData(const QModelIndexList &) const; - - void attachNetwork(Network *network); - - bool isBufferIndex(const QModelIndex &) const; - //Buffer *getBufferByIndex(const QModelIndex &) const; - QModelIndex networkIndex(NetworkId networkId); - QModelIndex bufferIndex(BufferId bufferId); - - const Network *networkByIndex(const QModelIndex &index) const; - - BufferInfo::ActivityLevel bufferActivity(const BufferInfo &buffer) const; - - //! Finds a buffer with a given name in a given network - /** This performs a linear search through all BufferItems, hence it is expensive. - * @param networkId The network which we search in - * @param bufferName The bufferName we look for - * @return The id of the buffer if found, an invalid one else - */ - BufferId bufferId(NetworkId networkId, const QString &bufferName, Qt::CaseSensitivity cs = Qt::CaseInsensitive) const; - - QString bufferName(BufferId bufferId) const; - BufferInfo::Type bufferType(BufferId bufferId) const; - BufferInfo bufferInfo(BufferId bufferId) const; - MsgId lastSeenMsgId(BufferId bufferId) const; - MsgId markerLineMsgId(BufferId bufferId) const; - NetworkId networkId(BufferId bufferId) const; - QString networkName(BufferId bufferId) const; - - inline QList allBufferIds() const { return _bufferItemCache.keys(); } - QList allBufferIdsSorted() const; - void sortBufferIds(QList &bufferIds) const; + enum Role { + BufferTypeRole = TreeModel::UserRole, + ItemActiveRole, + BufferActivityRole, + BufferIdRole, + NetworkIdRole, + BufferInfoRole, + ItemTypeRole, + UserAwayRole, + IrcUserRole, + IrcChannelRole, + BufferFirstUnreadMsgIdRole, + MarkerLineMsgIdRole, + }; + + enum ItemType { + NetworkItemType = 0x01, + BufferItemType = 0x02, + UserCategoryItemType = 0x04, + IrcUserItemType = 0x08 + }; + Q_DECLARE_FLAGS(ItemTypes, ItemType) + + NetworkModel(QObject *parent = 0); + static QList defaultHeader(); + + static bool mimeContainsBufferList(const QMimeData *mimeData); + static QList > mimeDataToBufferList(const QMimeData *mimeData); + + virtual QStringList mimeTypes() const; + virtual QMimeData *mimeData(const QModelIndexList &) const; + + void attachNetwork(Network *network); + + bool isBufferIndex(const QModelIndex &) const; + //Buffer *getBufferByIndex(const QModelIndex &) const; + QModelIndex networkIndex(NetworkId networkId); + QModelIndex bufferIndex(BufferId bufferId); + + const Network *networkByIndex(const QModelIndex &index) const; + + BufferInfo::ActivityLevel bufferActivity(const BufferInfo &buffer) const; + + //! Finds a buffer with a given name in a given network + /** This performs a linear search through all BufferItems, hence it is expensive. + * @param networkId The network which we search in + * @param bufferName The bufferName we look for + * @return The id of the buffer if found, an invalid one else + */ + BufferId bufferId(NetworkId networkId, const QString &bufferName, Qt::CaseSensitivity cs = Qt::CaseInsensitive) const; + + QString bufferName(BufferId bufferId) const; + BufferInfo::Type bufferType(BufferId bufferId) const; + BufferInfo bufferInfo(BufferId bufferId) const; + MsgId lastSeenMsgId(BufferId bufferId) const; + MsgId markerLineMsgId(BufferId bufferId) const; + NetworkId networkId(BufferId bufferId) const; + QString networkName(BufferId bufferId) const; + + inline QList allBufferIds() const { return _bufferItemCache.keys(); } + QList allBufferIdsSorted() const; + void sortBufferIds(QList &bufferIds) const; public slots: - void bufferUpdated(BufferInfo bufferInfo); - void removeBuffer(BufferId bufferId); - MsgId lastSeenMsgId(const BufferId &bufferId); - void setLastSeenMsgId(const BufferId &bufferId, const MsgId &msgId); - void setMarkerLineMsgId(const BufferId &bufferId, const MsgId &msgId); - void setBufferActivity(const BufferId &bufferId, BufferInfo::ActivityLevel activity); - void clearBufferActivity(const BufferId &bufferId); - void updateBufferActivity(Message &msg); - void networkRemoved(const NetworkId &networkId); + void bufferUpdated(BufferInfo bufferInfo); + void removeBuffer(BufferId bufferId); + MsgId lastSeenMsgId(const BufferId &bufferId); + void setLastSeenMsgId(const BufferId &bufferId, const MsgId &msgId); + void setMarkerLineMsgId(const BufferId &bufferId, const MsgId &msgId); + void setBufferActivity(const BufferId &bufferId, BufferInfo::ActivityLevel activity); + void clearBufferActivity(const BufferId &bufferId); + void updateBufferActivity(Message &msg); + void networkRemoved(const NetworkId &networkId); signals: - void requestSetLastSeenMsg(BufferId buffer, MsgId msg); - void lastSeenMsgSet(BufferId buffer, MsgId msg); - void markerLineSet(BufferId buffer, MsgId msg); + void requestSetLastSeenMsg(BufferId buffer, MsgId msg); + void lastSeenMsgSet(BufferId buffer, MsgId msg); + void markerLineSet(BufferId buffer, MsgId msg); private slots: - void checkForRemovedBuffers(const QModelIndex &parent, int start, int end); - void checkForNewBuffers(const QModelIndex &parent, int start, int end); - void messageRedirectionSettingsChanged(); + void checkForRemovedBuffers(const QModelIndex &parent, int start, int end); + void checkForNewBuffers(const QModelIndex &parent, int start, int end); + void messageRedirectionSettingsChanged(); private: - int networkRow(NetworkId networkId) const; - NetworkItem *findNetworkItem(NetworkId networkId) const; - NetworkItem *networkItem(NetworkId networkId); - inline BufferItem *findBufferItem(const BufferInfo &bufferInfo) const { return findBufferItem(bufferInfo.bufferId()); } - BufferItem *findBufferItem(BufferId bufferId) const; - BufferItem *bufferItem(const BufferInfo &bufferInfo); + int networkRow(NetworkId networkId) const; + NetworkItem *findNetworkItem(NetworkId networkId) const; + NetworkItem *networkItem(NetworkId networkId); + inline BufferItem *findBufferItem(const BufferInfo &bufferInfo) const { return findBufferItem(bufferInfo.bufferId()); } + BufferItem *findBufferItem(BufferId bufferId) const; + BufferItem *bufferItem(const BufferInfo &bufferInfo); - void updateBufferActivity(BufferItem *bufferItem, const Message &msg); + void updateBufferActivity(BufferItem *bufferItem, const Message &msg); - static bool bufferItemLessThan(const BufferItem *left, const BufferItem *right); + static bool bufferItemLessThan(const BufferItem *left, const BufferItem *right); - QHash _bufferItemCache; + QHash _bufferItemCache; - int _userNoticesTarget; - int _serverNoticesTarget; - int _errorMsgsTarget; + int _userNoticesTarget; + int _serverNoticesTarget; + int _errorMsgsTarget; }; + + Q_DECLARE_OPERATORS_FOR_FLAGS(NetworkModel::ItemTypes) #endif // NETWORKMODEL_H diff --git a/src/client/selectionmodelsynchronizer.cpp b/src/client/selectionmodelsynchronizer.cpp index 625ec3f3..9d06fa0b 100644 --- a/src/client/selectionmodelsynchronizer.cpp +++ b/src/client/selectionmodelsynchronizer.cpp @@ -20,225 +20,254 @@ #include "selectionmodelsynchronizer.h" - #include #include #include SelectionModelSynchronizer::SelectionModelSynchronizer(QAbstractItemModel *parent) - : QObject(parent), + : QObject(parent), _model(parent), _selectionModel(parent), _changeCurrentEnabled(true), _changeSelectionEnabled(true) { - connect(&_selectionModel, SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), - this, SLOT(currentChanged(const QModelIndex &, const QModelIndex &))); - connect(&_selectionModel, SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), - this, SLOT(selectionChanged(const QItemSelection &, const QItemSelection &))); + connect(&_selectionModel, SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), + this, SLOT(currentChanged(const QModelIndex &, const QModelIndex &))); + connect(&_selectionModel, SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), + this, SLOT(selectionChanged(const QItemSelection &, const QItemSelection &))); } -bool SelectionModelSynchronizer::checkBaseModel(QItemSelectionModel *selectionModel) { - if(!selectionModel) - return false; - - const QAbstractItemModel *baseModel = selectionModel->model(); - const QAbstractProxyModel *proxyModel = 0; - while((proxyModel = qobject_cast(baseModel)) != 0) { - baseModel = proxyModel->sourceModel(); - if(baseModel == model()) - break; - } - return baseModel == model(); + +bool SelectionModelSynchronizer::checkBaseModel(QItemSelectionModel *selectionModel) +{ + if (!selectionModel) + return false; + + const QAbstractItemModel *baseModel = selectionModel->model(); + const QAbstractProxyModel *proxyModel = 0; + while ((proxyModel = qobject_cast(baseModel)) != 0) { + baseModel = proxyModel->sourceModel(); + if (baseModel == model()) + break; + } + return baseModel == model(); } -void SelectionModelSynchronizer::synchronizeSelectionModel(QItemSelectionModel *selectionModel) { - if(!checkBaseModel(selectionModel)) { - qWarning() << "cannot Synchronize SelectionModel" << selectionModel << "which has a different baseModel()"; - return; - } - if(_selectionModels.contains(selectionModel)) { - selectionModel->setCurrentIndex(mapFromSource(currentIndex(), selectionModel), QItemSelectionModel::Current); - selectionModel->select(mapSelectionFromSource(currentSelection(), selectionModel), QItemSelectionModel::ClearAndSelect); - return; - } +void SelectionModelSynchronizer::synchronizeSelectionModel(QItemSelectionModel *selectionModel) +{ + if (!checkBaseModel(selectionModel)) { + qWarning() << "cannot Synchronize SelectionModel" << selectionModel << "which has a different baseModel()"; + return; + } - connect(selectionModel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), - this, SLOT(syncedCurrentChanged(QModelIndex, QModelIndex))); - connect(selectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), - this, SLOT(syncedSelectionChanged(QItemSelection, QItemSelection))); + if (_selectionModels.contains(selectionModel)) { + selectionModel->setCurrentIndex(mapFromSource(currentIndex(), selectionModel), QItemSelectionModel::Current); + selectionModel->select(mapSelectionFromSource(currentSelection(), selectionModel), QItemSelectionModel::ClearAndSelect); + return; + } + + connect(selectionModel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), + this, SLOT(syncedCurrentChanged(QModelIndex, QModelIndex))); + connect(selectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), + this, SLOT(syncedSelectionChanged(QItemSelection, QItemSelection))); - connect(selectionModel, SIGNAL(destroyed(QObject *)), this, SLOT(selectionModelDestroyed(QObject *))); + connect(selectionModel, SIGNAL(destroyed(QObject *)), this, SLOT(selectionModelDestroyed(QObject *))); - _selectionModels << selectionModel; + _selectionModels << selectionModel; } -void SelectionModelSynchronizer::removeSelectionModel(QItemSelectionModel *model) { - disconnect(model, 0, this, 0); - disconnect(this, 0, model, 0); - selectionModelDestroyed(model); + +void SelectionModelSynchronizer::removeSelectionModel(QItemSelectionModel *model) +{ + disconnect(model, 0, this, 0); + disconnect(this, 0, model, 0); + selectionModelDestroyed(model); } -void SelectionModelSynchronizer::selectionModelDestroyed(QObject *object) { - QItemSelectionModel *model = static_cast(object); - QSet::iterator iter = _selectionModels.begin(); - while(iter != _selectionModels.end()) { - if(*iter == model) { - iter = _selectionModels.erase(iter); - } else { - iter++; + +void SelectionModelSynchronizer::selectionModelDestroyed(QObject *object) +{ + QItemSelectionModel *model = static_cast(object); + QSet::iterator iter = _selectionModels.begin(); + while (iter != _selectionModels.end()) { + if (*iter == model) { + iter = _selectionModels.erase(iter); + } + else { + iter++; + } } - } } -void SelectionModelSynchronizer::syncedCurrentChanged(const QModelIndex ¤t, const QModelIndex &previous) { - Q_UNUSED(previous); - if(!_changeCurrentEnabled) - return; +void SelectionModelSynchronizer::syncedCurrentChanged(const QModelIndex ¤t, const QModelIndex &previous) +{ + Q_UNUSED(previous); + + if (!_changeCurrentEnabled) + return; - QItemSelectionModel *selectionModel = qobject_cast(sender()); - Q_ASSERT(selectionModel); - QModelIndex newSourceCurrent = mapToSource(current, selectionModel); - if(newSourceCurrent.isValid() && newSourceCurrent != currentIndex()) - setCurrentIndex(newSourceCurrent); + QItemSelectionModel *selectionModel = qobject_cast(sender()); + Q_ASSERT(selectionModel); + QModelIndex newSourceCurrent = mapToSource(current, selectionModel); + if (newSourceCurrent.isValid() && newSourceCurrent != currentIndex()) + setCurrentIndex(newSourceCurrent); } -void SelectionModelSynchronizer::syncedSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected) { - Q_UNUSED(selected); - Q_UNUSED(deselected); - - if(!_changeSelectionEnabled) - return; - - QItemSelectionModel *selectionModel = qobject_cast(sender()); - Q_ASSERT(selectionModel); - - QItemSelection mappedSelection = selectionModel->selection(); - QItemSelection currentSelectionMapped = mapSelectionFromSource(currentSelection(), selectionModel); - - QItemSelection checkSelection = currentSelectionMapped; - checkSelection.merge(mappedSelection, QItemSelectionModel::Deselect); - if(checkSelection.isEmpty()) { - // that means the new selection contains the current selection (currentSel - newSel = {}) - checkSelection = mappedSelection; - checkSelection.merge(currentSelectionMapped, QItemSelectionModel::Deselect); - if(checkSelection.isEmpty()) { - // that means the current selection contains the new selection (newSel - currentSel = {}) - // -> currentSel == newSel - return; + +void SelectionModelSynchronizer::syncedSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected) +{ + Q_UNUSED(selected); + Q_UNUSED(deselected); + + if (!_changeSelectionEnabled) + return; + + QItemSelectionModel *selectionModel = qobject_cast(sender()); + Q_ASSERT(selectionModel); + + QItemSelection mappedSelection = selectionModel->selection(); + QItemSelection currentSelectionMapped = mapSelectionFromSource(currentSelection(), selectionModel); + + QItemSelection checkSelection = currentSelectionMapped; + checkSelection.merge(mappedSelection, QItemSelectionModel::Deselect); + if (checkSelection.isEmpty()) { + // that means the new selection contains the current selection (currentSel - newSel = {}) + checkSelection = mappedSelection; + checkSelection.merge(currentSelectionMapped, QItemSelectionModel::Deselect); + if (checkSelection.isEmpty()) { + // that means the current selection contains the new selection (newSel - currentSel = {}) + // -> currentSel == newSel + return; + } } - } - setCurrentSelection(mapSelectionToSource(mappedSelection, selectionModel)); + setCurrentSelection(mapSelectionToSource(mappedSelection, selectionModel)); } -QModelIndex SelectionModelSynchronizer::mapFromSource(const QModelIndex &sourceIndex, const QItemSelectionModel *selectionModel) { - Q_ASSERT(selectionModel); - - QModelIndex mappedIndex = sourceIndex; - - // make a list of all involved proxies, wie have to traverse backwards - QList proxyModels; - const QAbstractItemModel *baseModel = selectionModel->model(); - const QAbstractProxyModel *proxyModel = 0; - while((proxyModel = qobject_cast(baseModel)) != 0) { - if(baseModel == model()) - break; - proxyModels << proxyModel; - baseModel = proxyModel->sourceModel(); - } - - // now traverse it; - for(int i = proxyModels.count() - 1; i >= 0; i--) { - mappedIndex = proxyModels[i]->mapFromSource(mappedIndex); - } - - return mappedIndex; + +QModelIndex SelectionModelSynchronizer::mapFromSource(const QModelIndex &sourceIndex, const QItemSelectionModel *selectionModel) +{ + Q_ASSERT(selectionModel); + + QModelIndex mappedIndex = sourceIndex; + + // make a list of all involved proxies, wie have to traverse backwards + QList proxyModels; + const QAbstractItemModel *baseModel = selectionModel->model(); + const QAbstractProxyModel *proxyModel = 0; + while ((proxyModel = qobject_cast(baseModel)) != 0) { + if (baseModel == model()) + break; + proxyModels << proxyModel; + baseModel = proxyModel->sourceModel(); + } + + // now traverse it; + for (int i = proxyModels.count() - 1; i >= 0; i--) { + mappedIndex = proxyModels[i]->mapFromSource(mappedIndex); + } + + return mappedIndex; } -QItemSelection SelectionModelSynchronizer::mapSelectionFromSource(const QItemSelection &sourceSelection, const QItemSelectionModel *selectionModel) { - Q_ASSERT(selectionModel); - - QItemSelection mappedSelection = sourceSelection; - - // make a list of all involved proxies, wie have to traverse backwards - QList proxyModels; - const QAbstractItemModel *baseModel = selectionModel->model(); - const QAbstractProxyModel *proxyModel = 0; - while((proxyModel = qobject_cast(baseModel)) != 0) { - if(baseModel == model()) - break; - proxyModels << proxyModel; - baseModel = proxyModel->sourceModel(); - } - - // now traverse it; - for(int i = proxyModels.count() - 1; i >= 0; i--) { - mappedSelection = proxyModels[i]->mapSelectionFromSource(mappedSelection); - } - return mappedSelection; + +QItemSelection SelectionModelSynchronizer::mapSelectionFromSource(const QItemSelection &sourceSelection, const QItemSelectionModel *selectionModel) +{ + Q_ASSERT(selectionModel); + + QItemSelection mappedSelection = sourceSelection; + + // make a list of all involved proxies, wie have to traverse backwards + QList proxyModels; + const QAbstractItemModel *baseModel = selectionModel->model(); + const QAbstractProxyModel *proxyModel = 0; + while ((proxyModel = qobject_cast(baseModel)) != 0) { + if (baseModel == model()) + break; + proxyModels << proxyModel; + baseModel = proxyModel->sourceModel(); + } + + // now traverse it; + for (int i = proxyModels.count() - 1; i >= 0; i--) { + mappedSelection = proxyModels[i]->mapSelectionFromSource(mappedSelection); + } + return mappedSelection; } -QModelIndex SelectionModelSynchronizer::mapToSource(const QModelIndex &index, QItemSelectionModel *selectionModel) { - Q_ASSERT(selectionModel); - - QModelIndex sourceIndex = index; - const QAbstractItemModel *baseModel = selectionModel->model(); - const QAbstractProxyModel *proxyModel = 0; - while((proxyModel = qobject_cast(baseModel)) != 0) { - sourceIndex = proxyModel->mapToSource(sourceIndex); - baseModel = proxyModel->sourceModel(); - if(baseModel == model()) - break; - } - return sourceIndex; + +QModelIndex SelectionModelSynchronizer::mapToSource(const QModelIndex &index, QItemSelectionModel *selectionModel) +{ + Q_ASSERT(selectionModel); + + QModelIndex sourceIndex = index; + const QAbstractItemModel *baseModel = selectionModel->model(); + const QAbstractProxyModel *proxyModel = 0; + while ((proxyModel = qobject_cast(baseModel)) != 0) { + sourceIndex = proxyModel->mapToSource(sourceIndex); + baseModel = proxyModel->sourceModel(); + if (baseModel == model()) + break; + } + return sourceIndex; } -QItemSelection SelectionModelSynchronizer::mapSelectionToSource(const QItemSelection &selection, QItemSelectionModel *selectionModel) { - Q_ASSERT(selectionModel); - - QItemSelection sourceSelection = selection; - const QAbstractItemModel *baseModel = selectionModel->model(); - const QAbstractProxyModel *proxyModel = 0; - while((proxyModel = qobject_cast(baseModel)) != 0) { - sourceSelection = proxyModel->mapSelectionToSource(sourceSelection); - baseModel = proxyModel->sourceModel(); - if(baseModel == model()) - break; - } - return sourceSelection; + +QItemSelection SelectionModelSynchronizer::mapSelectionToSource(const QItemSelection &selection, QItemSelectionModel *selectionModel) +{ + Q_ASSERT(selectionModel); + + QItemSelection sourceSelection = selection; + const QAbstractItemModel *baseModel = selectionModel->model(); + const QAbstractProxyModel *proxyModel = 0; + while ((proxyModel = qobject_cast(baseModel)) != 0) { + sourceSelection = proxyModel->mapSelectionToSource(sourceSelection); + baseModel = proxyModel->sourceModel(); + if (baseModel == model()) + break; + } + return sourceSelection; } -void SelectionModelSynchronizer::setCurrentIndex(const QModelIndex &index) { - _selectionModel.setCurrentIndex(index, QItemSelectionModel::Current); + +void SelectionModelSynchronizer::setCurrentIndex(const QModelIndex &index) +{ + _selectionModel.setCurrentIndex(index, QItemSelectionModel::Current); } -void SelectionModelSynchronizer::setCurrentSelection(const QItemSelection &selection) { - _selectionModel.select(selection, QItemSelectionModel::ClearAndSelect); + + +void SelectionModelSynchronizer::setCurrentSelection(const QItemSelection &selection) +{ + _selectionModel.select(selection, QItemSelectionModel::ClearAndSelect); } -void SelectionModelSynchronizer::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { - Q_UNUSED(previous); - _changeCurrentEnabled = false; - QSet::iterator iter = _selectionModels.begin(); - while(iter != _selectionModels.end()) { - (*iter)->setCurrentIndex(mapFromSource(current, (*iter)), QItemSelectionModel::Current); - iter++; - } - _changeCurrentEnabled = true; +void SelectionModelSynchronizer::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) +{ + Q_UNUSED(previous); + + _changeCurrentEnabled = false; + QSet::iterator iter = _selectionModels.begin(); + while (iter != _selectionModels.end()) { + (*iter)->setCurrentIndex(mapFromSource(current, (*iter)), QItemSelectionModel::Current); + iter++; + } + _changeCurrentEnabled = true; } -void SelectionModelSynchronizer::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) { - Q_UNUSED(selected); - Q_UNUSED(deselected); - - _changeSelectionEnabled = false; - QSet::iterator iter = _selectionModels.begin(); - while(iter != _selectionModels.end()) { - (*iter)->select(mapSelectionFromSource(currentSelection(), (*iter)), QItemSelectionModel::ClearAndSelect); - iter++; - } - _changeSelectionEnabled = true; + +void SelectionModelSynchronizer::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) +{ + Q_UNUSED(selected); + Q_UNUSED(deselected); + + _changeSelectionEnabled = false; + QSet::iterator iter = _selectionModels.begin(); + while (iter != _selectionModels.end()) { + (*iter)->select(mapSelectionFromSource(currentSelection(), (*iter)), QItemSelectionModel::ClearAndSelect); + iter++; + } + _changeSelectionEnabled = true; } diff --git a/src/client/selectionmodelsynchronizer.h b/src/client/selectionmodelsynchronizer.h index 33550854..7fa13533 100644 --- a/src/client/selectionmodelsynchronizer.h +++ b/src/client/selectionmodelsynchronizer.h @@ -26,45 +26,47 @@ class QAbstractItemModel; -class SelectionModelSynchronizer : public QObject { - Q_OBJECT +class SelectionModelSynchronizer : public QObject +{ + Q_OBJECT public: - SelectionModelSynchronizer(QAbstractItemModel *parent = 0); + SelectionModelSynchronizer(QAbstractItemModel *parent = 0); - void synchronizeSelectionModel(QItemSelectionModel *selectionModel); - void removeSelectionModel(QItemSelectionModel *selectionModel); + void synchronizeSelectionModel(QItemSelectionModel *selectionModel); + void removeSelectionModel(QItemSelectionModel *selectionModel); - inline QAbstractItemModel *model() { return _model; } - inline QItemSelectionModel *selectionModel() const { return const_cast(&_selectionModel); } - inline QModelIndex currentIndex() const { return _selectionModel.currentIndex(); } - inline QItemSelection currentSelection() const { return _selectionModel.selection(); } + inline QAbstractItemModel *model() { return _model; } + inline QItemSelectionModel *selectionModel() const { return const_cast(&_selectionModel); } + inline QModelIndex currentIndex() const { return _selectionModel.currentIndex(); } + inline QItemSelection currentSelection() const { return _selectionModel.selection(); } private slots: - void syncedCurrentChanged(const QModelIndex ¤t, const QModelIndex &previous); - void syncedSelectionChanged(const QItemSelection &selected, const QItemSelection &previous); + void syncedCurrentChanged(const QModelIndex ¤t, const QModelIndex &previous); + void syncedSelectionChanged(const QItemSelection &selected, const QItemSelection &previous); - void setCurrentIndex(const QModelIndex &index); - void setCurrentSelection(const QItemSelection &selection); + void setCurrentIndex(const QModelIndex &index); + void setCurrentSelection(const QItemSelection &selection); - void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); - void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); + void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); + void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); - void selectionModelDestroyed(QObject *object); + void selectionModelDestroyed(QObject *object); private: - QAbstractItemModel *_model; - QItemSelectionModel _selectionModel; - bool _changeCurrentEnabled; - bool _changeSelectionEnabled; - - bool checkBaseModel(QItemSelectionModel *model); - QModelIndex mapFromSource(const QModelIndex &sourceIndex, const QItemSelectionModel *selectionModel); - QItemSelection mapSelectionFromSource(const QItemSelection &sourceSelection, const QItemSelectionModel *selectionModel); - QModelIndex mapToSource(const QModelIndex &index, QItemSelectionModel *selectionModel); - QItemSelection mapSelectionToSource(const QItemSelection &selection, QItemSelectionModel *selectionModel); - - QSet _selectionModels; + QAbstractItemModel *_model; + QItemSelectionModel _selectionModel; + bool _changeCurrentEnabled; + bool _changeSelectionEnabled; + + bool checkBaseModel(QItemSelectionModel *model); + QModelIndex mapFromSource(const QModelIndex &sourceIndex, const QItemSelectionModel *selectionModel); + QItemSelection mapSelectionFromSource(const QItemSelection &sourceSelection, const QItemSelectionModel *selectionModel); + QModelIndex mapToSource(const QModelIndex &index, QItemSelectionModel *selectionModel); + QItemSelection mapSelectionToSource(const QItemSelection &selection, QItemSelectionModel *selectionModel); + + QSet _selectionModels; }; + #endif diff --git a/src/client/treemodel.cpp b/src/client/treemodel.cpp index b3f2613c..777d483f 100644 --- a/src/client/treemodel.cpp +++ b/src/client/treemodel.cpp @@ -25,12 +25,13 @@ #include "quassel.h" -class RemoveChildLaterEvent : public QEvent { +class RemoveChildLaterEvent : public QEvent +{ public: - RemoveChildLaterEvent(AbstractTreeItem *child) : QEvent(QEvent::User), _child(child) {}; - inline AbstractTreeItem *child() { return _child; } + RemoveChildLaterEvent(AbstractTreeItem *child) : QEvent(QEvent::User), _child(child) {}; + inline AbstractTreeItem *child() { return _child; } private: - AbstractTreeItem *_child; + AbstractTreeItem *_child; }; @@ -38,354 +39,406 @@ private: * Abstract Items of a TreeModel *****************************************/ AbstractTreeItem::AbstractTreeItem(AbstractTreeItem *parent) - : QObject(parent), + : QObject(parent), _flags(Qt::ItemIsSelectable | Qt::ItemIsEnabled), _treeItemFlags(0) { } -bool AbstractTreeItem::newChild(AbstractTreeItem *item) { - int newRow = childCount(); - emit beginAppendChilds(newRow, newRow); - _childItems.append(item); - emit endAppendChilds(); - return true; + +bool AbstractTreeItem::newChild(AbstractTreeItem *item) +{ + int newRow = childCount(); + emit beginAppendChilds(newRow, newRow); + _childItems.append(item); + emit endAppendChilds(); + return true; } -bool AbstractTreeItem::newChilds(const QList &items) { - if(items.isEmpty()) - return false; - int nextRow = childCount(); - int lastRow = nextRow + items.count() - 1; +bool AbstractTreeItem::newChilds(const QList &items) +{ + if (items.isEmpty()) + return false; + + int nextRow = childCount(); + int lastRow = nextRow + items.count() - 1; - emit beginAppendChilds(nextRow, lastRow); - _childItems << items; - emit endAppendChilds(); + emit beginAppendChilds(nextRow, lastRow); + _childItems << items; + emit endAppendChilds(); - return true; + return true; } -bool AbstractTreeItem::removeChild(int row) { - if(row < 0 || childCount() <= row) - return false; - child(row)->removeAllChilds(); - emit beginRemoveChilds(row, row); - AbstractTreeItem *treeitem = _childItems.takeAt(row); - delete treeitem; - emit endRemoveChilds(); +bool AbstractTreeItem::removeChild(int row) +{ + if (row < 0 || childCount() <= row) + return false; + + child(row)->removeAllChilds(); + emit beginRemoveChilds(row, row); + AbstractTreeItem *treeitem = _childItems.takeAt(row); + delete treeitem; + emit endRemoveChilds(); - checkForDeletion(); + checkForDeletion(); - return true; + return true; } -void AbstractTreeItem::removeAllChilds() { - const int numChilds = childCount(); - if(numChilds == 0) - return; +void AbstractTreeItem::removeAllChilds() +{ + const int numChilds = childCount(); - AbstractTreeItem *child; + if (numChilds == 0) + return; - QList::iterator childIter; + AbstractTreeItem *child; - childIter = _childItems.begin(); - while(childIter != _childItems.end()) { - child = *childIter; - child->setTreeItemFlags(0); // disable self deletion, as this would only fuck up consitency and the child gets deleted anyways - child->removeAllChilds(); - childIter++; - } + QList::iterator childIter; - emit beginRemoveChilds(0, numChilds - 1); - childIter = _childItems.begin(); - while(childIter != _childItems.end()) { - child = *childIter; - childIter = _childItems.erase(childIter); - delete child; - } - emit endRemoveChilds(); + childIter = _childItems.begin(); + while (childIter != _childItems.end()) { + child = *childIter; + child->setTreeItemFlags(0); // disable self deletion, as this would only fuck up consitency and the child gets deleted anyways + child->removeAllChilds(); + childIter++; + } + + emit beginRemoveChilds(0, numChilds - 1); + childIter = _childItems.begin(); + while (childIter != _childItems.end()) { + child = *childIter; + childIter = _childItems.erase(childIter); + delete child; + } + emit endRemoveChilds(); - checkForDeletion(); + checkForDeletion(); } -void AbstractTreeItem::removeChildLater(AbstractTreeItem *child) { - Q_ASSERT(child); - QCoreApplication::postEvent(this, new RemoveChildLaterEvent(child)); + +void AbstractTreeItem::removeChildLater(AbstractTreeItem *child) +{ + Q_ASSERT(child); + QCoreApplication::postEvent(this, new RemoveChildLaterEvent(child)); } -void AbstractTreeItem::customEvent(QEvent *event) { - if(event->type() != QEvent::User) - return; - event->accept(); +void AbstractTreeItem::customEvent(QEvent *event) +{ + if (event->type() != QEvent::User) + return; + + event->accept(); - RemoveChildLaterEvent *removeEvent = static_cast(event); - int childRow = _childItems.indexOf(removeEvent->child()); - if(childRow == -1) - return; + RemoveChildLaterEvent *removeEvent = static_cast(event); + int childRow = _childItems.indexOf(removeEvent->child()); + if (childRow == -1) + return; - // since we are called asynchronously we have to recheck if the item in question still has no childs - if(removeEvent->child()->childCount()) - return; + // since we are called asynchronously we have to recheck if the item in question still has no childs + if (removeEvent->child()->childCount()) + return; - removeChild(childRow); + removeChild(childRow); } -bool AbstractTreeItem::reParent(AbstractTreeItem *newParent) { - // currently we support only re parenting if the child that's about to be - // adopted does not have any children itself. - if(childCount() != 0) { - qDebug() << "AbstractTreeItem::reParent(): cannot reparent" << this << "with children."; - return false; - } - int oldRow = row(); - if(oldRow == -1) - return false; +bool AbstractTreeItem::reParent(AbstractTreeItem *newParent) +{ + // currently we support only re parenting if the child that's about to be + // adopted does not have any children itself. + if (childCount() != 0) { + qDebug() << "AbstractTreeItem::reParent(): cannot reparent" << this << "with children."; + return false; + } + + int oldRow = row(); + if (oldRow == -1) + return false; - emit parent()->beginRemoveChilds(oldRow, oldRow); - parent()->_childItems.removeAt(oldRow); - emit parent()->endRemoveChilds(); + emit parent()->beginRemoveChilds(oldRow, oldRow); + parent()->_childItems.removeAt(oldRow); + emit parent()->endRemoveChilds(); - AbstractTreeItem *oldParent = parent(); - setParent(newParent); + AbstractTreeItem *oldParent = parent(); + setParent(newParent); - bool success = newParent->newChild(this); - if(!success) - qWarning() << "AbstractTreeItem::reParent(): failed to attach to new parent after removing from old parent! this:" << this << "new parent:" << newParent; + bool success = newParent->newChild(this); + if (!success) + qWarning() << "AbstractTreeItem::reParent(): failed to attach to new parent after removing from old parent! this:" << this << "new parent:" << newParent; - if(oldParent) - oldParent->checkForDeletion(); + if (oldParent) + oldParent->checkForDeletion(); - return success; + return success; } -AbstractTreeItem *AbstractTreeItem::child(int row) const { - if(childCount() <= row) - return 0; - else - return _childItems[row]; + +AbstractTreeItem *AbstractTreeItem::child(int row) const +{ + if (childCount() <= row) + return 0; + else + return _childItems[row]; } -int AbstractTreeItem::childCount(int column) const { - if(column > 0) - return 0; - else - return _childItems.count(); + +int AbstractTreeItem::childCount(int column) const +{ + if (column > 0) + return 0; + else + return _childItems.count(); } -int AbstractTreeItem::row() const { - if(!parent()) { - qWarning() << "AbstractTreeItem::row():" << this << "has no parent AbstractTreeItem as it's parent! parent is" << QObject::parent(); - return -1; - } - int row_ = parent()->_childItems.indexOf(const_cast(this)); - if(row_ == -1) - qWarning() << "AbstractTreeItem::row():" << this << "is not in the child list of" << QObject::parent(); - return row_; +int AbstractTreeItem::row() const +{ + if (!parent()) { + qWarning() << "AbstractTreeItem::row():" << this << "has no parent AbstractTreeItem as it's parent! parent is" << QObject::parent(); + return -1; + } + + int row_ = parent()->_childItems.indexOf(const_cast(this)); + if (row_ == -1) + qWarning() << "AbstractTreeItem::row():" << this << "is not in the child list of" << QObject::parent(); + return row_; } -void AbstractTreeItem::dumpChildList() { - qDebug() << "==== Childlist for Item:" << this << "===="; - if(childCount() > 0) { - AbstractTreeItem *child; - QList::const_iterator childIter = _childItems.constBegin(); - while(childIter != _childItems.constEnd()) { - child = *childIter; - qDebug() << "Row:" << child->row() << child << child->data(0, Qt::DisplayRole); - childIter++; + +void AbstractTreeItem::dumpChildList() +{ + qDebug() << "==== Childlist for Item:" << this << "===="; + if (childCount() > 0) { + AbstractTreeItem *child; + QList::const_iterator childIter = _childItems.constBegin(); + while (childIter != _childItems.constEnd()) { + child = *childIter; + qDebug() << "Row:" << child->row() << child << child->data(0, Qt::DisplayRole); + childIter++; + } } - } - qDebug() << "==== End Of Childlist ===="; + qDebug() << "==== End Of Childlist ===="; } + /***************************************** * SimpleTreeItem *****************************************/ SimpleTreeItem::SimpleTreeItem(const QList &data, AbstractTreeItem *parent) - : AbstractTreeItem(parent), + : AbstractTreeItem(parent), _itemData(data) { } -SimpleTreeItem::~SimpleTreeItem() { + +SimpleTreeItem::~SimpleTreeItem() +{ } -QVariant SimpleTreeItem::data(int column, int role) const { - if(column >= columnCount() || role != Qt::DisplayRole) - return QVariant(); - else - return _itemData[column]; + +QVariant SimpleTreeItem::data(int column, int role) const +{ + if (column >= columnCount() || role != Qt::DisplayRole) + return QVariant(); + else + return _itemData[column]; } -bool SimpleTreeItem::setData(int column, const QVariant &value, int role) { - if(column > columnCount() || role != Qt::DisplayRole) - return false; - if(column == columnCount()) - _itemData.append(value); - else - _itemData[column] = value; +bool SimpleTreeItem::setData(int column, const QVariant &value, int role) +{ + if (column > columnCount() || role != Qt::DisplayRole) + return false; + + if (column == columnCount()) + _itemData.append(value); + else + _itemData[column] = value; - emit dataChanged(column); - return true; + emit dataChanged(column); + return true; } -int SimpleTreeItem::columnCount() const { - return _itemData.count(); + +int SimpleTreeItem::columnCount() const +{ + return _itemData.count(); } + /***************************************** * PropertyMapItem *****************************************/ PropertyMapItem::PropertyMapItem(const QStringList &propertyOrder, AbstractTreeItem *parent) - : AbstractTreeItem(parent), + : AbstractTreeItem(parent), _propertyOrder(propertyOrder) { } + PropertyMapItem::PropertyMapItem(AbstractTreeItem *parent) - : AbstractTreeItem(parent), + : AbstractTreeItem(parent), _propertyOrder(QStringList()) { } -PropertyMapItem::~PropertyMapItem() { +PropertyMapItem::~PropertyMapItem() +{ } -QVariant PropertyMapItem::data(int column, int role) const { - if(column >= columnCount()) - return QVariant(); - - switch(role) { - case Qt::ToolTipRole: - return toolTip(column); - case Qt::DisplayRole: - case TreeModel::SortRole: // fallthrough, since SortRole should default to DisplayRole - return property(_propertyOrder[column].toAscii()); - default: - return QVariant(); - } +QVariant PropertyMapItem::data(int column, int role) const +{ + if (column >= columnCount()) + return QVariant(); + + switch (role) { + case Qt::ToolTipRole: + return toolTip(column); + case Qt::DisplayRole: + case TreeModel::SortRole: // fallthrough, since SortRole should default to DisplayRole + return property(_propertyOrder[column].toAscii()); + default: + return QVariant(); + } } -bool PropertyMapItem::setData(int column, const QVariant &value, int role) { - if(column >= columnCount() || role != Qt::DisplayRole) - return false; - emit dataChanged(column); - return setProperty(_propertyOrder[column].toAscii(), value); -} +bool PropertyMapItem::setData(int column, const QVariant &value, int role) +{ + if (column >= columnCount() || role != Qt::DisplayRole) + return false; -int PropertyMapItem::columnCount() const { - return _propertyOrder.count(); + emit dataChanged(column); + return setProperty(_propertyOrder[column].toAscii(), value); } -void PropertyMapItem::appendProperty(const QString &property) { - _propertyOrder << property; + +int PropertyMapItem::columnCount() const +{ + return _propertyOrder.count(); } +void PropertyMapItem::appendProperty(const QString &property) +{ + _propertyOrder << property; +} + /***************************************** * TreeModel *****************************************/ TreeModel::TreeModel(const QList &data, QObject *parent) - : QAbstractItemModel(parent), + : QAbstractItemModel(parent), _childStatus(QModelIndex(), 0, 0, 0), _aboutToRemoveOrInsert(false) { - rootItem = new SimpleTreeItem(data, 0); - connectItem(rootItem); + rootItem = new SimpleTreeItem(data, 0); + connectItem(rootItem); - if(Quassel::isOptionSet("debugmodel")) { - connect(this, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)), + if (Quassel::isOptionSet("debugmodel")) { + connect(this, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)), this, SLOT(debug_rowsAboutToBeInserted(const QModelIndex &, int, int))); - connect(this, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)), + connect(this, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)), this, SLOT(debug_rowsAboutToBeRemoved(const QModelIndex &, int, int))); - connect(this, SIGNAL(rowsInserted(const QModelIndex &, int, int)), + connect(this, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(debug_rowsInserted(const QModelIndex &, int, int))); - connect(this, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), + connect(this, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SLOT(debug_rowsRemoved(const QModelIndex &, int, int))); - connect(this, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), + connect(this, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(debug_dataChanged(const QModelIndex &, const QModelIndex &))); - } + } } -TreeModel::~TreeModel() { - delete rootItem; + +TreeModel::~TreeModel() +{ + delete rootItem; } -QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const { - if(row < 0 || row >= rowCount(parent) || column < 0 || column >= columnCount(parent)) - return QModelIndex(); - AbstractTreeItem *parentItem; +QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const +{ + if (row < 0 || row >= rowCount(parent) || column < 0 || column >= columnCount(parent)) + return QModelIndex(); - if(!parent.isValid()) - parentItem = rootItem; - else - parentItem = static_cast(parent.internalPointer()); + AbstractTreeItem *parentItem; - AbstractTreeItem *childItem = parentItem->child(row); + if (!parent.isValid()) + parentItem = rootItem; + else + parentItem = static_cast(parent.internalPointer()); - if(childItem) - return createIndex(row, column, childItem); - else - return QModelIndex(); + AbstractTreeItem *childItem = parentItem->child(row); + + if (childItem) + return createIndex(row, column, childItem); + else + return QModelIndex(); } -QModelIndex TreeModel::indexByItem(AbstractTreeItem *item) const { - if(item == 0) { - qWarning() << "TreeModel::indexByItem(AbstractTreeItem *item) received NULL-Pointer"; - return QModelIndex(); - } - if(item == rootItem) - return QModelIndex(); - else - return createIndex(item->row(), 0, item); +QModelIndex TreeModel::indexByItem(AbstractTreeItem *item) const +{ + if (item == 0) { + qWarning() << "TreeModel::indexByItem(AbstractTreeItem *item) received NULL-Pointer"; + return QModelIndex(); + } + + if (item == rootItem) + return QModelIndex(); + else + return createIndex(item->row(), 0, item); } -QModelIndex TreeModel::parent(const QModelIndex &index) const { - if(!index.isValid()) { - // ModelTest does this - // qWarning() << "TreeModel::parent(): has been asked for the rootItems Parent!"; - return QModelIndex(); - } - AbstractTreeItem *childItem = static_cast(index.internalPointer()); - AbstractTreeItem *parentItem = childItem->parent(); +QModelIndex TreeModel::parent(const QModelIndex &index) const +{ + if (!index.isValid()) { + // ModelTest does this + // qWarning() << "TreeModel::parent(): has been asked for the rootItems Parent!"; + return QModelIndex(); + } + + AbstractTreeItem *childItem = static_cast(index.internalPointer()); + AbstractTreeItem *parentItem = childItem->parent(); - Q_ASSERT(parentItem); - if(parentItem == rootItem) - return QModelIndex(); + Q_ASSERT(parentItem); + if (parentItem == rootItem) + return QModelIndex(); - return createIndex(parentItem->row(), 0, parentItem); + return createIndex(parentItem->row(), 0, parentItem); } -int TreeModel::rowCount(const QModelIndex &parent) const { - AbstractTreeItem *parentItem; - if(!parent.isValid()) - parentItem = rootItem; - else - parentItem = static_cast(parent.internalPointer()); - return parentItem->childCount(parent.column()); +int TreeModel::rowCount(const QModelIndex &parent) const +{ + AbstractTreeItem *parentItem; + if (!parent.isValid()) + parentItem = rootItem; + else + parentItem = static_cast(parent.internalPointer()); + + return parentItem->childCount(parent.column()); } -int TreeModel::columnCount(const QModelIndex &parent) const { - Q_UNUSED(parent) - return rootItem->columnCount(); - // since there the Qt Views don't draw more columns than the header has columns - // we can be lazy and simply return the count of header columns - // actually this gives us more freedom cause we don't have to ensure that a rows parent - // has equal or more columns than that row + +int TreeModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + return rootItem->columnCount(); + // since there the Qt Views don't draw more columns than the header has columns + // we can be lazy and simply return the count of header columns + // actually this gives us more freedom cause we don't have to ensure that a rows parent + // has equal or more columns than that row // AbstractTreeItem *parentItem; // if(!parent.isValid()) @@ -395,195 +448,229 @@ int TreeModel::columnCount(const QModelIndex &parent) const { // return parentItem->columnCount(); } -QVariant TreeModel::data(const QModelIndex &index, int role) const { - if(!index.isValid()) - return QVariant(); - AbstractTreeItem *item = static_cast(index.internalPointer()); - return item->data(index.column(), role); +QVariant TreeModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + AbstractTreeItem *item = static_cast(index.internalPointer()); + return item->data(index.column(), role); } -bool TreeModel::setData(const QModelIndex &index, const QVariant &value, int role) { - if(!index.isValid()) - return false; - AbstractTreeItem *item = static_cast(index.internalPointer()); - return item->setData(index.column(), value, role); -} +bool TreeModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid()) + return false; -Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const { - if(!index.isValid()) { - return rootItem->flags() & Qt::ItemIsDropEnabled; - } else { AbstractTreeItem *item = static_cast(index.internalPointer()); - return item->flags(); - } + return item->setData(index.column(), value, role); +} + + +Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) { + return rootItem->flags() & Qt::ItemIsDropEnabled; + } + else { + AbstractTreeItem *item = static_cast(index.internalPointer()); + return item->flags(); + } +} + + +QVariant TreeModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) + return rootItem->data(section, role); + else + return QVariant(); +} + + +void TreeModel::itemDataChanged(int column) +{ + AbstractTreeItem *item = qobject_cast(sender()); + QModelIndex leftIndex, rightIndex; + + if (item == rootItem) + return; + + if (column == -1) { + leftIndex = createIndex(item->row(), 0, item); + rightIndex = createIndex(item->row(), item->columnCount() - 1, item); + } + else { + leftIndex = createIndex(item->row(), column, item); + rightIndex = leftIndex; + } + + emit dataChanged(leftIndex, rightIndex); +} + + +void TreeModel::connectItem(AbstractTreeItem *item) +{ + connect(item, SIGNAL(dataChanged(int)), + this, SLOT(itemDataChanged(int))); + + connect(item, SIGNAL(beginAppendChilds(int, int)), + this, SLOT(beginAppendChilds(int, int))); + connect(item, SIGNAL(endAppendChilds()), + this, SLOT(endAppendChilds())); + + connect(item, SIGNAL(beginRemoveChilds(int, int)), + this, SLOT(beginRemoveChilds(int, int))); + connect(item, SIGNAL(endRemoveChilds()), + this, SLOT(endRemoveChilds())); +} + + +void TreeModel::beginAppendChilds(int firstRow, int lastRow) +{ + AbstractTreeItem *parentItem = qobject_cast(sender()); + if (!parentItem) { + qWarning() << "TreeModel::beginAppendChilds(): cannot append Children to unknown parent"; + return; + } + + QModelIndex parent = indexByItem(parentItem); + Q_ASSERT(!_aboutToRemoveOrInsert); + + _aboutToRemoveOrInsert = true; + _childStatus = ChildStatus(parent, rowCount(parent), firstRow, lastRow); + beginInsertRows(parent, firstRow, lastRow); } -QVariant TreeModel::headerData(int section, Qt::Orientation orientation, int role) const { - if (orientation == Qt::Horizontal && role == Qt::DisplayRole) - return rootItem->data(section, role); - else - return QVariant(); -} - -void TreeModel::itemDataChanged(int column) { - AbstractTreeItem *item = qobject_cast(sender()); - QModelIndex leftIndex, rightIndex; - - if(item == rootItem) - return; - - if(column == -1) { - leftIndex = createIndex(item->row(), 0, item); - rightIndex = createIndex(item->row(), item->columnCount() - 1, item); - } else { - leftIndex = createIndex(item->row(), column, item); - rightIndex = leftIndex; - } - emit dataChanged(leftIndex, rightIndex); +void TreeModel::endAppendChilds() +{ + AbstractTreeItem *parentItem = qobject_cast(sender()); + if (!parentItem) { + qWarning() << "TreeModel::endAppendChilds(): cannot append Children to unknown parent"; + return; + } + Q_ASSERT(_aboutToRemoveOrInsert); + ChildStatus cs = _childStatus; + QModelIndex parent = indexByItem(parentItem); + Q_ASSERT(cs.parent == parent); + Q_ASSERT(rowCount(parent) == cs.childCount + cs.end - cs.start + 1); + + _aboutToRemoveOrInsert = false; + for (int i = cs.start; i <= cs.end; i++) { + connectItem(parentItem->child(i)); + } + endInsertRows(); } -void TreeModel::connectItem(AbstractTreeItem *item) { - connect(item, SIGNAL(dataChanged(int)), - this, SLOT(itemDataChanged(int))); - connect(item, SIGNAL(beginAppendChilds(int, int)), - this, SLOT(beginAppendChilds(int, int))); - connect(item, SIGNAL(endAppendChilds()), - this, SLOT(endAppendChilds())); +void TreeModel::beginRemoveChilds(int firstRow, int lastRow) +{ + AbstractTreeItem *parentItem = qobject_cast(sender()); + if (!parentItem) { + qWarning() << "TreeModel::beginRemoveChilds(): cannot append Children to unknown parent"; + return; + } + + for (int i = firstRow; i <= lastRow; i++) { + disconnect(parentItem->child(i), 0, this, 0); + } + + // consitency checks + QModelIndex parent = indexByItem(parentItem); + Q_ASSERT(firstRow <= lastRow); + Q_ASSERT(parentItem->childCount() > lastRow); + Q_ASSERT(!_aboutToRemoveOrInsert); + _aboutToRemoveOrInsert = true; + _childStatus = ChildStatus(parent, rowCount(parent), firstRow, lastRow); - connect(item, SIGNAL(beginRemoveChilds(int, int)), - this, SLOT(beginRemoveChilds(int, int))); - connect(item, SIGNAL(endRemoveChilds()), - this, SLOT(endRemoveChilds())); + beginRemoveRows(parent, firstRow, lastRow); } -void TreeModel::beginAppendChilds(int firstRow, int lastRow) { - AbstractTreeItem *parentItem = qobject_cast(sender()); - if(!parentItem) { - qWarning() << "TreeModel::beginAppendChilds(): cannot append Children to unknown parent"; - return; - } - QModelIndex parent = indexByItem(parentItem); - Q_ASSERT(!_aboutToRemoveOrInsert); - - _aboutToRemoveOrInsert = true; - _childStatus = ChildStatus(parent, rowCount(parent), firstRow, lastRow); - beginInsertRows(parent, firstRow, lastRow); +void TreeModel::endRemoveChilds() +{ + AbstractTreeItem *parentItem = qobject_cast(sender()); + if (!parentItem) { + qWarning() << "TreeModel::endRemoveChilds(): cannot remove Children from unknown parent"; + return; + } + + // concistency checks + Q_ASSERT(_aboutToRemoveOrInsert); + ChildStatus cs = _childStatus; + QModelIndex parent = indexByItem(parentItem); + Q_ASSERT(cs.parent == parent); + Q_ASSERT(rowCount(parent) == cs.childCount - cs.end + cs.start - 1); + _aboutToRemoveOrInsert = false; + + endRemoveRows(); } -void TreeModel::endAppendChilds() { - AbstractTreeItem *parentItem = qobject_cast(sender()); - if(!parentItem) { - qWarning() << "TreeModel::endAppendChilds(): cannot append Children to unknown parent"; - return; - } - Q_ASSERT(_aboutToRemoveOrInsert); - ChildStatus cs = _childStatus; - QModelIndex parent = indexByItem(parentItem); - Q_ASSERT(cs.parent == parent); - Q_ASSERT(rowCount(parent) == cs.childCount + cs.end - cs.start + 1); - _aboutToRemoveOrInsert = false; - for(int i = cs.start; i <= cs.end; i++) { - connectItem(parentItem->child(i)); - } - endInsertRows(); +void TreeModel::clear() +{ + rootItem->removeAllChilds(); +} + + +void TreeModel::debug_rowsAboutToBeInserted(const QModelIndex &parent, int start, int end) +{ + qDebug() << "debug_rowsAboutToBeInserted" << parent << parent.internalPointer() << parent.data().toString() << rowCount(parent) << start << end; } -void TreeModel::beginRemoveChilds(int firstRow, int lastRow) { - AbstractTreeItem *parentItem = qobject_cast(sender()); - if(!parentItem) { - qWarning() << "TreeModel::beginRemoveChilds(): cannot append Children to unknown parent"; - return; - } - for(int i = firstRow; i <= lastRow; i++) { - disconnect(parentItem->child(i), 0, this, 0); - } +void TreeModel::debug_rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) +{ + AbstractTreeItem *parentItem; + parentItem = static_cast(parent.internalPointer()); + if (!parentItem) + parentItem = rootItem; + qDebug() << "debug_rowsAboutToBeRemoved" << parent << parentItem << parent.data().toString() << rowCount(parent) << start << end; + + QModelIndex child; + for (int i = end; i >= start; i--) { + child = parent.child(i, 0); + Q_ASSERT(parentItem->child(i)); + qDebug() << ">>>" << i << child << child.data().toString(); + } +} - // consitency checks - QModelIndex parent = indexByItem(parentItem); - Q_ASSERT(firstRow <= lastRow); - Q_ASSERT(parentItem->childCount() > lastRow); - Q_ASSERT(!_aboutToRemoveOrInsert); - _aboutToRemoveOrInsert = true; - _childStatus = ChildStatus(parent, rowCount(parent), firstRow, lastRow); - beginRemoveRows(parent, firstRow, lastRow); +void TreeModel::debug_rowsInserted(const QModelIndex &parent, int start, int end) +{ + AbstractTreeItem *parentItem; + parentItem = static_cast(parent.internalPointer()); + if (!parentItem) + parentItem = rootItem; + qDebug() << "debug_rowsInserted:" << parent << parentItem << parent.data().toString() << rowCount(parent) << start << end; + + QModelIndex child; + for (int i = start; i <= end; i++) { + child = parent.child(i, 0); + Q_ASSERT(parentItem->child(i)); + qDebug() << "<<<" << i << child << child.data().toString(); + } } -void TreeModel::endRemoveChilds() { - AbstractTreeItem *parentItem = qobject_cast(sender()); - if(!parentItem) { - qWarning() << "TreeModel::endRemoveChilds(): cannot remove Children from unknown parent"; - return; - } - - // concistency checks - Q_ASSERT(_aboutToRemoveOrInsert); - ChildStatus cs = _childStatus; - QModelIndex parent = indexByItem(parentItem); - Q_ASSERT(cs.parent == parent); - Q_ASSERT(rowCount(parent) == cs.childCount - cs.end + cs.start - 1); - _aboutToRemoveOrInsert = false; - - endRemoveRows(); -} - -void TreeModel::clear() { - rootItem->removeAllChilds(); -} - -void TreeModel::debug_rowsAboutToBeInserted(const QModelIndex &parent, int start, int end) { - qDebug() << "debug_rowsAboutToBeInserted" << parent << parent.internalPointer() << parent.data().toString() << rowCount(parent) << start << end; + +void TreeModel::debug_rowsRemoved(const QModelIndex &parent, int start, int end) +{ + qDebug() << "debug_rowsRemoved" << parent << parent.internalPointer() << parent.data().toString() << rowCount(parent) << start << end; } -void TreeModel::debug_rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { - AbstractTreeItem *parentItem; - parentItem = static_cast(parent.internalPointer()); - if(!parentItem) - parentItem = rootItem; - qDebug() << "debug_rowsAboutToBeRemoved" << parent << parentItem << parent.data().toString() << rowCount(parent) << start << end; - - QModelIndex child; - for(int i = end; i >= start; i--) { - child = parent.child(i, 0); - Q_ASSERT(parentItem->child(i)); - qDebug() << ">>>" << i << child << child.data().toString(); - } -} - -void TreeModel::debug_rowsInserted(const QModelIndex &parent, int start, int end) { - AbstractTreeItem *parentItem; - parentItem = static_cast(parent.internalPointer()); - if(!parentItem) - parentItem = rootItem; - qDebug() << "debug_rowsInserted:" << parent << parentItem << parent.data().toString() << rowCount(parent) << start << end; - - QModelIndex child; - for(int i = start; i <= end; i++) { - child = parent.child(i, 0); - Q_ASSERT(parentItem->child(i)); - qDebug() << "<<<" << i << child << child.data().toString(); - } -} - -void TreeModel::debug_rowsRemoved(const QModelIndex &parent, int start, int end) { - qDebug() << "debug_rowsRemoved" << parent << parent.internalPointer() << parent.data().toString() << rowCount(parent) << start << end; -} - -void TreeModel::debug_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { - qDebug() << "debug_dataChanged" << topLeft << bottomRight; - QStringList displayData; - for(int row = topLeft.row(); row <= bottomRight.row(); row++) { - displayData = QStringList(); - for(int column = topLeft.column(); column <= bottomRight.column(); column++) { - displayData << data(topLeft.sibling(row, column), Qt::DisplayRole).toString(); + +void TreeModel::debug_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) +{ + qDebug() << "debug_dataChanged" << topLeft << bottomRight; + QStringList displayData; + for (int row = topLeft.row(); row <= bottomRight.row(); row++) { + displayData = QStringList(); + for (int column = topLeft.column(); column <= bottomRight.column(); column++) { + displayData << data(topLeft.sibling(row, column), Qt::DisplayRole).toString(); + } + qDebug() << " row:" << row << displayData; } - qDebug() << " row:" << row << displayData; - } } diff --git a/src/client/treemodel.h b/src/client/treemodel.h index e585c0b0..6c2a6490 100644 --- a/src/client/treemodel.h +++ b/src/client/treemodel.h @@ -31,174 +31,183 @@ /***************************************** * general item used in the Tree Model *****************************************/ -class AbstractTreeItem : public QObject { - Q_OBJECT +class AbstractTreeItem : public QObject +{ + Q_OBJECT public: - enum TreeItemFlag { - NoTreeItemFlag = 0x00, - DeleteOnLastChildRemoved = 0x01 - }; - Q_DECLARE_FLAGS(TreeItemFlags, TreeItemFlag) + enum TreeItemFlag { + NoTreeItemFlag = 0x00, + DeleteOnLastChildRemoved = 0x01 + }; + Q_DECLARE_FLAGS(TreeItemFlags, TreeItemFlag) - AbstractTreeItem(AbstractTreeItem *parent = 0); + AbstractTreeItem(AbstractTreeItem *parent = 0); - bool newChild(AbstractTreeItem *child); - bool newChilds(const QList &items); + bool newChild(AbstractTreeItem *child); + bool newChilds(const QList &items); - bool removeChild(int row); - inline bool removeChild(AbstractTreeItem *child) { return removeChild(child->row()); } - void removeAllChilds(); + bool removeChild(int row); + inline bool removeChild(AbstractTreeItem *child) { return removeChild(child->row()); } + void removeAllChilds(); - bool reParent(AbstractTreeItem *newParent); - - AbstractTreeItem *child(int row) const; + bool reParent(AbstractTreeItem *newParent); - int childCount(int column = 0) const; + AbstractTreeItem *child(int row) const; - virtual int columnCount() const = 0; + int childCount(int column = 0) const; - virtual QVariant data(int column, int role) const = 0; - virtual bool setData(int column, const QVariant &value, int role) = 0; + virtual int columnCount() const = 0; - virtual inline Qt::ItemFlags flags() const { return _flags; } - virtual inline void setFlags(Qt::ItemFlags flags) { _flags = flags; } + virtual QVariant data(int column, int role) const = 0; + virtual bool setData(int column, const QVariant &value, int role) = 0; - inline AbstractTreeItem::TreeItemFlags treeItemFlags() const { return _treeItemFlags; } - inline void setTreeItemFlags(AbstractTreeItem::TreeItemFlags flags) { _treeItemFlags = flags; } - int row() const; - inline AbstractTreeItem *parent() const { return qobject_cast(QObject::parent()); } + virtual inline Qt::ItemFlags flags() const { return _flags; } + virtual inline void setFlags(Qt::ItemFlags flags) { _flags = flags; } - void dumpChildList(); + inline AbstractTreeItem::TreeItemFlags treeItemFlags() const { return _treeItemFlags; } + inline void setTreeItemFlags(AbstractTreeItem::TreeItemFlags flags) { _treeItemFlags = flags; } + int row() const; + inline AbstractTreeItem *parent() const { return qobject_cast(QObject::parent()); } + + void dumpChildList(); signals: - void dataChanged(int column = -1); + void dataChanged(int column = -1); + + void beginAppendChilds(int firstRow, int lastRow); + void endAppendChilds(); - void beginAppendChilds(int firstRow, int lastRow); - void endAppendChilds(); - - void beginRemoveChilds(int firstRow, int lastRow); - void endRemoveChilds(); + void beginRemoveChilds(int firstRow, int lastRow); + void endRemoveChilds(); protected: - void customEvent(QEvent *event); + void customEvent(QEvent *event); private: - QList _childItems; - Qt::ItemFlags _flags; - TreeItemFlags _treeItemFlags; - - void removeChildLater(AbstractTreeItem *child); - inline void checkForDeletion() { if(treeItemFlags() & DeleteOnLastChildRemoved && childCount() == 0) parent()->removeChildLater(this); } + QList _childItems; + Qt::ItemFlags _flags; + TreeItemFlags _treeItemFlags; + + void removeChildLater(AbstractTreeItem *child); + inline void checkForDeletion() + { + if (treeItemFlags() & DeleteOnLastChildRemoved && childCount() == 0) parent()->removeChildLater(this); + } }; /***************************************** * SimpleTreeItem *****************************************/ -class SimpleTreeItem : public AbstractTreeItem { - Q_OBJECT +class SimpleTreeItem : public AbstractTreeItem +{ + Q_OBJECT public: - SimpleTreeItem(const QList &data, AbstractTreeItem *parent = 0); - virtual ~SimpleTreeItem(); + SimpleTreeItem(const QList &data, AbstractTreeItem *parent = 0); + virtual ~SimpleTreeItem(); - virtual QVariant data(int column, int role) const; - virtual bool setData(int column, const QVariant &value, int role); + virtual QVariant data(int column, int role) const; + virtual bool setData(int column, const QVariant &value, int role); - virtual int columnCount() const; + virtual int columnCount() const; private: - QList _itemData; + QList _itemData; }; + /***************************************** * PropertyMapItem *****************************************/ -class PropertyMapItem : public AbstractTreeItem { - Q_OBJECT +class PropertyMapItem : public AbstractTreeItem +{ + Q_OBJECT public: - PropertyMapItem(const QStringList &propertyOrder, AbstractTreeItem *parent = 0); - PropertyMapItem(AbstractTreeItem *parent = 0); + PropertyMapItem(const QStringList &propertyOrder, AbstractTreeItem *parent = 0); + PropertyMapItem(AbstractTreeItem *parent = 0); + + virtual ~PropertyMapItem(); + + virtual QVariant data(int column, int role) const; + virtual bool setData(int column, const QVariant &value, int role); - virtual ~PropertyMapItem(); - - virtual QVariant data(int column, int role) const; - virtual bool setData(int column, const QVariant &value, int role); + virtual QString toolTip(int column) const { Q_UNUSED(column) return QString(); } + virtual int columnCount() const; - virtual QString toolTip(int column) const { Q_UNUSED(column) return QString(); } - virtual int columnCount() const; - - void appendProperty(const QString &property); + void appendProperty(const QString &property); private: - QStringList _propertyOrder; + QStringList _propertyOrder; }; /***************************************** * TreeModel *****************************************/ -class TreeModel : public QAbstractItemModel { - Q_OBJECT +class TreeModel : public QAbstractItemModel +{ + Q_OBJECT public: - enum myRoles { - SortRole = Qt::UserRole, - UserRole - }; + enum myRoles { + SortRole = Qt::UserRole, + UserRole + }; - TreeModel(const QList &, QObject *parent = 0); - virtual ~TreeModel(); + TreeModel(const QList &, QObject *parent = 0); + virtual ~TreeModel(); - virtual QVariant data(const QModelIndex &index, int role) const; - virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + 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; - QModelIndex indexByItem(AbstractTreeItem *item) const; + virtual Qt::ItemFlags flags(const QModelIndex &index) const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - QModelIndex parent(const QModelIndex &index) const; + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QModelIndex indexByItem(AbstractTreeItem *item) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &index) const; - virtual void clear(); + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + + virtual void clear(); private slots: - void itemDataChanged(int column = -1); - - void beginAppendChilds(int firstRow, int lastRow); - void endAppendChilds(); - - void beginRemoveChilds(int firstRow, int lastRow); - void endRemoveChilds(); - + void itemDataChanged(int column = -1); + + void beginAppendChilds(int firstRow, int lastRow); + void endAppendChilds(); + + void beginRemoveChilds(int firstRow, int lastRow); + void endRemoveChilds(); + protected: - AbstractTreeItem *rootItem; + AbstractTreeItem *rootItem; private: - void connectItem(AbstractTreeItem *item); - - struct ChildStatus { - QModelIndex parent; - int childCount; - int start; - int end; - inline ChildStatus(QModelIndex parent_, int cc_, int s_, int e_) : parent(parent_), childCount(cc_), start(s_), end(e_) {}; - }; - ChildStatus _childStatus; - int _aboutToRemoveOrInsert; + void connectItem(AbstractTreeItem *item); + + struct ChildStatus { + QModelIndex parent; + int childCount; + int start; + int end; + inline ChildStatus(QModelIndex parent_, int cc_, int s_, int e_) : parent(parent_), childCount(cc_), start(s_), end(e_) {}; + }; + ChildStatus _childStatus; + int _aboutToRemoveOrInsert; private slots: - void debug_rowsAboutToBeInserted(const QModelIndex &parent, int start, int end); - void debug_rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); - void debug_rowsInserted(const QModelIndex &parent, int start, int end); - void debug_rowsRemoved(const QModelIndex &parent, int start, int end); - void debug_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + void debug_rowsAboutToBeInserted(const QModelIndex &parent, int start, int end); + void debug_rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); + void debug_rowsInserted(const QModelIndex &parent, int start, int end); + void debug_rowsRemoved(const QModelIndex &parent, int start, int end); + void debug_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); }; + #endif diff --git a/src/common/abstractcliparser.h b/src/common/abstractcliparser.h index d424e5a2..79169e8f 100644 --- a/src/common/abstractcliparser.h +++ b/src/common/abstractcliparser.h @@ -23,47 +23,55 @@ #include -class AbstractCliParser { +class AbstractCliParser +{ public: - virtual bool init(const QStringList &arguments = QStringList()) = 0; + virtual bool init(const QStringList &arguments = QStringList()) = 0; - virtual QString value(const QString &longName) = 0; - virtual bool isSet(const QString &longName) = 0; - inline void addSwitch(const QString &longName, const char shortName = 0, const QString &help = QString()) { - addArgument(longName, CliParserArg(CliParserArg::CliArgSwitch, shortName, help)); - } - inline void addOption(const QString &longName, const char shortName = 0, const QString &help = QString(), const QString &def = QString()) { - addArgument(longName, CliParserArg(CliParserArg::CliArgOption, shortName, help, def)); - } - virtual void usage() = 0; + virtual QString value(const QString &longName) = 0; + virtual bool isSet(const QString &longName) = 0; + inline void addSwitch(const QString &longName, const char shortName = 0, const QString &help = QString()) + { + addArgument(longName, CliParserArg(CliParserArg::CliArgSwitch, shortName, help)); + } - virtual ~AbstractCliParser() {}; + + inline void addOption(const QString &longName, const char shortName = 0, const QString &help = QString(), const QString &def = QString()) + { + addArgument(longName, CliParserArg(CliParserArg::CliArgOption, shortName, help, def)); + } + + + virtual void usage() = 0; + + virtual ~AbstractCliParser() {}; protected: - struct CliParserArg { - enum CliArgType { - CliArgInvalid, - CliArgSwitch, - CliArgOption - }; + struct CliParserArg { + enum CliArgType { + CliArgInvalid, + CliArgSwitch, + CliArgOption + }; - CliParserArg(const CliArgType _type = CliArgInvalid, const char _shortName = 0, const QString _help = QString(), const QString _def = QString()) - : type(_type), - shortName(_shortName), - help(_help), - def(_def), - value(QString()), - boolValue(false) {}; + CliParserArg(const CliArgType _type = CliArgInvalid, const char _shortName = 0, const QString _help = QString(), const QString _def = QString()) + : type(_type), + shortName(_shortName), + help(_help), + def(_def), + value(QString()), + boolValue(false) {}; - CliArgType type; - char shortName; - QString help; - QString def; - QString value; - bool boolValue; - }; + CliArgType type; + char shortName; + QString help; + QString def; + QString value; + bool boolValue; + }; - virtual void addArgument(const QString &longName, const CliParserArg &arg) = 0; + virtual void addArgument(const QString &longName, const CliParserArg &arg) = 0; }; + #endif diff --git a/src/common/aliasmanager.cpp b/src/common/aliasmanager.cpp index 9815b580..51f4af73 100644 --- a/src/common/aliasmanager.cpp +++ b/src/common/aliasmanager.cpp @@ -18,7 +18,6 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ - #include #include @@ -26,167 +25,185 @@ #include "network.h" INIT_SYNCABLE_OBJECT(AliasManager) -AliasManager &AliasManager::operator=(const AliasManager &other) { - if(this == &other) - return *this; +AliasManager &AliasManager::operator=(const AliasManager &other) +{ + if (this == &other) + return *this; - SyncableObject::operator=(other); - _aliases = other._aliases; - return *this; + SyncableObject::operator=(other); + _aliases = other._aliases; + return *this; } -int AliasManager::indexOf(const QString &name) const { - for(int i = 0; i < _aliases.count(); i++) { - if(_aliases[i].name == name) - return i; - } - return -1; + +int AliasManager::indexOf(const QString &name) const +{ + for (int i = 0; i < _aliases.count(); i++) { + if (_aliases[i].name == name) + return i; + } + return -1; } -QVariantMap AliasManager::initAliases() const { - QVariantMap aliases; - QStringList names; - QStringList expansions; - for(int i = 0; i < _aliases.count(); i++) { - names << _aliases[i].name; - expansions << _aliases[i].expansion; - } +QVariantMap AliasManager::initAliases() const +{ + QVariantMap aliases; + QStringList names; + QStringList expansions; + + for (int i = 0; i < _aliases.count(); i++) { + names << _aliases[i].name; + expansions << _aliases[i].expansion; + } - aliases["names"] = names; - aliases["expansions"] = expansions; - return aliases; + aliases["names"] = names; + aliases["expansions"] = expansions; + return aliases; } -void AliasManager::initSetAliases(const QVariantMap &aliases) { - QStringList names = aliases["names"].toStringList(); - QStringList expansions = aliases["expansions"].toStringList(); - if(names.count() != expansions.count()) { - qWarning() << "AliasesManager::initSetAliases: received" << names.count() << "alias names but only" << expansions.count() << "expansions!"; - return; - } +void AliasManager::initSetAliases(const QVariantMap &aliases) +{ + QStringList names = aliases["names"].toStringList(); + QStringList expansions = aliases["expansions"].toStringList(); - _aliases.clear(); - for(int i = 0; i < names.count(); i++) { - _aliases << Alias(names[i], expansions[i]); - } + if (names.count() != expansions.count()) { + qWarning() << "AliasesManager::initSetAliases: received" << names.count() << "alias names but only" << expansions.count() << "expansions!"; + return; + } + + _aliases.clear(); + for (int i = 0; i < names.count(); i++) { + _aliases << Alias(names[i], expansions[i]); + } } -void AliasManager::addAlias(const QString &name, const QString &expansion) { - if(contains(name)) { - return; - } +void AliasManager::addAlias(const QString &name, const QString &expansion) +{ + if (contains(name)) { + return; + } - _aliases << Alias(name, expansion); + _aliases << Alias(name, expansion); - SYNC(ARG(name), ARG(expansion)) + SYNC(ARG(name), ARG(expansion)) } -AliasManager::AliasList AliasManager::defaults() { - AliasList aliases; - aliases << Alias("j", "/join $0") - << Alias("ns", "/msg nickserv $0") - << Alias("nickserv", "/msg nickserv $0") - << Alias("cs", "/msg chanserv $0") - << Alias("chanserv", "/msg chanserv $0") - << Alias("hs", "/msg hostserv $0") - << Alias("hostserv", "/msg hostserv $0") - << Alias("back", "/quote away"); + +AliasManager::AliasList AliasManager::defaults() +{ + AliasList aliases; + aliases << Alias("j", "/join $0") + << Alias("ns", "/msg nickserv $0") + << Alias("nickserv", "/msg nickserv $0") + << Alias("cs", "/msg chanserv $0") + << Alias("chanserv", "/msg chanserv $0") + << Alias("hs", "/msg hostserv $0") + << Alias("hostserv", "/msg hostserv $0") + << Alias("back", "/quote away"); #ifdef Q_OS_LINUX - // let's add aliases for scripts that only run on linux - aliases << Alias("inxi", "/exec inxi $0") - << Alias("sysinfo", "/exec inxi -d"); + // let's add aliases for scripts that only run on linux + aliases << Alias("inxi", "/exec inxi $0") + << Alias("sysinfo", "/exec inxi -d"); #endif - return aliases; + return aliases; } -AliasManager::CommandList AliasManager::processInput(const BufferInfo &info, const QString &msg) { - CommandList result; - processInput(info, msg, result); - return result; + +AliasManager::CommandList AliasManager::processInput(const BufferInfo &info, const QString &msg) +{ + CommandList result; + processInput(info, msg, result); + return result; } -void AliasManager::processInput(const BufferInfo &info, const QString &msg_, CommandList &list) { - QString msg = msg_; - - // leading slashes indicate there's a command to call unless there is another one in the first section (like a path /proc/cpuinfo) - int secondSlashPos = msg.indexOf('/', 1); - int firstSpacePos = msg.indexOf(' '); - if(!msg.startsWith('/') || (secondSlashPos != -1 && (secondSlashPos < firstSpacePos || firstSpacePos == -1))) { - if(msg.startsWith("//")) - msg.remove(0, 1); // //asdf is transformed to /asdf - msg.prepend("/SAY "); // make sure we only send proper commands to the core - } else { - // check for aliases - QString cmd = msg.section(' ', 0, 0).remove(0, 1).toUpper(); - for(int i = 0; i < count(); i++) { - if((*this)[i].name.toUpper() == cmd) { - expand((*this)[i].expansion, info, msg.section(' ', 1), list); - return; - } + +void AliasManager::processInput(const BufferInfo &info, const QString &msg_, CommandList &list) +{ + QString msg = msg_; + + // leading slashes indicate there's a command to call unless there is another one in the first section (like a path /proc/cpuinfo) + int secondSlashPos = msg.indexOf('/', 1); + int firstSpacePos = msg.indexOf(' '); + if (!msg.startsWith('/') || (secondSlashPos != -1 && (secondSlashPos < firstSpacePos || firstSpacePos == -1))) { + if (msg.startsWith("//")) + msg.remove(0, 1); // //asdf is transformed to /asdf + msg.prepend("/SAY "); // make sure we only send proper commands to the core + } + else { + // check for aliases + QString cmd = msg.section(' ', 0, 0).remove(0, 1).toUpper(); + for (int i = 0; i < count(); i++) { + if ((*this)[i].name.toUpper() == cmd) { + expand((*this)[i].expansion, info, msg.section(' ', 1), list); + return; + } + } } - } - list.append(qMakePair(info, msg)); + list.append(qMakePair(info, msg)); } -void AliasManager::expand(const QString &alias, const BufferInfo &bufferInfo, const QString &msg, CommandList &list) { - const Network *net = network(bufferInfo.networkId()); - if(!net) { - // FIXME send error as soon as we have a method for that! - return; - } - - QRegExp paramRangeR("\\$(\\d+)\\.\\.(\\d*)"); - QStringList commands = alias.split(QRegExp("; ?")); - QStringList params = msg.split(' '); - QStringList expandedCommands; - for(int i = 0; i < commands.count(); i++) { - QString command = commands[i]; - - // replace ranges like $1..3 - if(!params.isEmpty()) { - int pos; - while((pos = paramRangeR.indexIn(command)) != -1) { - int start = paramRangeR.cap(1).toInt(); - bool ok; - int end = paramRangeR.cap(2).toInt(&ok); - if(!ok) { - end = params.count(); + +void AliasManager::expand(const QString &alias, const BufferInfo &bufferInfo, const QString &msg, CommandList &list) +{ + const Network *net = network(bufferInfo.networkId()); + if (!net) { + // FIXME send error as soon as we have a method for that! + return; + } + + QRegExp paramRangeR("\\$(\\d+)\\.\\.(\\d*)"); + QStringList commands = alias.split(QRegExp("; ?")); + QStringList params = msg.split(' '); + QStringList expandedCommands; + for (int i = 0; i < commands.count(); i++) { + QString command = commands[i]; + + // replace ranges like $1..3 + if (!params.isEmpty()) { + int pos; + while ((pos = paramRangeR.indexIn(command)) != -1) { + int start = paramRangeR.cap(1).toInt(); + bool ok; + int end = paramRangeR.cap(2).toInt(&ok); + if (!ok) { + end = params.count(); + } + if (end < start) + command = command.replace(pos, paramRangeR.matchedLength(), QString()); + else { + command = command.replace(pos, paramRangeR.matchedLength(), QStringList(params.mid(start - 1, end - start + 1)).join(" ")); + } + } } - if(end < start) - command = command.replace(pos, paramRangeR.matchedLength(), QString()); - else { - command = command.replace(pos, paramRangeR.matchedLength(), QStringList(params.mid(start - 1, end - start + 1)).join(" ")); + + for (int j = params.count(); j > 0; j--) { + IrcUser *ircUser = net->ircUser(params[j - 1]); + command = command.replace(QString("$%1:hostname").arg(j), ircUser ? ircUser->host() : QString("*")); + command = command.replace(QString("$%1").arg(j), params[j - 1]); } - } + command = command.replace("$0", msg); + command = command.replace("$channelname", bufferInfo.bufferName()); // legacy + command = command.replace("$channel", bufferInfo.bufferName()); + command = command.replace("$currentnick", net->myNick()); // legacy + command = command.replace("$nick", net->myNick()); + expandedCommands << command; } - for(int j = params.count(); j > 0; j--) { - IrcUser *ircUser = net->ircUser(params[j - 1]); - command = command.replace(QString("$%1:hostname").arg(j), ircUser ? ircUser->host() : QString("*")); - command = command.replace(QString("$%1").arg(j), params[j - 1]); - } - command = command.replace("$0", msg); - command = command.replace("$channelname", bufferInfo.bufferName()); // legacy - command = command.replace("$channel", bufferInfo.bufferName()); - command = command.replace("$currentnick", net->myNick()); // legacy - command = command.replace("$nick", net->myNick()); - expandedCommands << command; - } - - while(!expandedCommands.isEmpty()) { - QString command; - if(expandedCommands[0].trimmed().toLower().startsWith("/wait")) { - command = expandedCommands.join("; "); - expandedCommands.clear(); - } else { - command = expandedCommands.takeFirst(); + while (!expandedCommands.isEmpty()) { + QString command; + if (expandedCommands[0].trimmed().toLower().startsWith("/wait")) { + command = expandedCommands.join("; "); + expandedCommands.clear(); + } + else { + command = expandedCommands.takeFirst(); + } + list.append(qMakePair(bufferInfo, command)); } - list.append(qMakePair(bufferInfo, command)); - } } diff --git a/src/common/aliasmanager.h b/src/common/aliasmanager.h index 67a56206..240d9e5d 100644 --- a/src/common/aliasmanager.h +++ b/src/common/aliasmanager.h @@ -28,52 +28,53 @@ class Network; -class AliasManager : public SyncableObject { - SYNCABLE_OBJECT - Q_OBJECT +class AliasManager : public SyncableObject +{ + SYNCABLE_OBJECT + Q_OBJECT public: - inline AliasManager(QObject *parent = 0) : SyncableObject(parent) { setAllowClientUpdates(true); } - AliasManager &operator=(const AliasManager &other); + inline AliasManager(QObject *parent = 0) : SyncableObject(parent) { setAllowClientUpdates(true); } + AliasManager &operator=(const AliasManager &other); - struct Alias { - QString name; - QString expansion; - Alias(const QString &name_, const QString &expansion_) : name(name_), expansion(expansion_) {} - }; - typedef QList AliasList ; + struct Alias { + QString name; + QString expansion; + Alias(const QString &name_, const QString &expansion_) : name(name_), expansion(expansion_) {} + }; + typedef QList AliasList; - int indexOf(const QString &name) const; - inline bool contains(const QString &name) const { return indexOf(name) != -1; } - inline bool isEmpty() const { return _aliases.isEmpty(); } - inline int count() const { return _aliases.count(); } - inline void removeAt(int index) { _aliases.removeAt(index); } - inline Alias &operator[](int i) { return _aliases[i]; } - inline const Alias &operator[](int i) const { return _aliases.at(i); } - inline const AliasList &aliases() const { return _aliases; } + int indexOf(const QString &name) const; + inline bool contains(const QString &name) const { return indexOf(name) != -1; } + inline bool isEmpty() const { return _aliases.isEmpty(); } + inline int count() const { return _aliases.count(); } + inline void removeAt(int index) { _aliases.removeAt(index); } + inline Alias &operator[](int i) { return _aliases[i]; } + inline const Alias &operator[](int i) const { return _aliases.at(i); } + inline const AliasList &aliases() const { return _aliases; } - static AliasList defaults(); + static AliasList defaults(); - typedef QList > CommandList; + typedef QList > CommandList; - CommandList processInput(const BufferInfo &info, const QString &message); + CommandList processInput(const BufferInfo &info, const QString &message); public slots: - virtual QVariantMap initAliases() const; - virtual void initSetAliases(const QVariantMap &aliases); + virtual QVariantMap initAliases() const; + virtual void initSetAliases(const QVariantMap &aliases); - virtual void addAlias(const QString &name, const QString &expansion); + virtual void addAlias(const QString &name, const QString &expansion); protected: - void setAliases(const QList &aliases) { _aliases = aliases; } - virtual const Network *network(NetworkId) const = 0; // core and client require different access + void setAliases(const QList &aliases) { _aliases = aliases; } + virtual const Network *network(NetworkId) const = 0; // core and client require different access private: - void processInput(const BufferInfo &info, const QString &message, CommandList &previousCommands); - void expand(const QString &alias, const BufferInfo &bufferInfo, const QString &msg, CommandList &previousCommands); - - AliasList _aliases; + void processInput(const BufferInfo &info, const QString &message, CommandList &previousCommands); + void expand(const QString &alias, const BufferInfo &bufferInfo, const QString &msg, CommandList &previousCommands); + AliasList _aliases; }; + #endif //ALIASMANAGER_H diff --git a/src/common/backlogmanager.cpp b/src/common/backlogmanager.cpp index 449b9cd5..aceeb2f1 100644 --- a/src/common/backlogmanager.cpp +++ b/src/common/backlogmanager.cpp @@ -21,12 +21,15 @@ #include "backlogmanager.h" INIT_SYNCABLE_OBJECT(BacklogManager) -QVariantList BacklogManager::requestBacklog(BufferId bufferId, MsgId first, MsgId last, int limit, int additional) { - REQUEST(ARG(bufferId), ARG(first), ARG(last), ARG(limit), ARG(additional)) - return QVariantList(); +QVariantList BacklogManager::requestBacklog(BufferId bufferId, MsgId first, MsgId last, int limit, int additional) +{ + REQUEST(ARG(bufferId), ARG(first), ARG(last), ARG(limit), ARG(additional)) + return QVariantList(); } -QVariantList BacklogManager::requestBacklogAll(MsgId first, MsgId last, int limit, int additional) { - REQUEST(ARG(first), ARG(last), ARG(limit), ARG(additional)) - return QVariantList(); + +QVariantList BacklogManager::requestBacklogAll(MsgId first, MsgId last, int limit, int additional) +{ + REQUEST(ARG(first), ARG(last), ARG(limit), ARG(additional)) + return QVariantList(); } diff --git a/src/common/backlogmanager.h b/src/common/backlogmanager.h index 95c87a04..91d1c5c5 100644 --- a/src/common/backlogmanager.h +++ b/src/common/backlogmanager.h @@ -24,24 +24,26 @@ #include "syncableobject.h" #include "types.h" -class BacklogManager : public SyncableObject { - SYNCABLE_OBJECT - Q_OBJECT +class BacklogManager : public SyncableObject +{ + SYNCABLE_OBJECT + Q_OBJECT public: - BacklogManager(QObject *parent = 0) : SyncableObject(parent) {} - inline virtual const QMetaObject *syncMetaObject() const { return &staticMetaObject; } + BacklogManager(QObject *parent = 0) : SyncableObject(parent) {} + inline virtual const QMetaObject *syncMetaObject() const { return &staticMetaObject; } public slots: - virtual QVariantList requestBacklog(BufferId bufferId, MsgId first = -1, MsgId last = -1, int limit = -1, int additional = 0); - inline virtual void receiveBacklog(BufferId, MsgId, MsgId, int, int, QVariantList) {}; + virtual QVariantList requestBacklog(BufferId bufferId, MsgId first = -1, MsgId last = -1, int limit = -1, int additional = 0); + inline virtual void receiveBacklog(BufferId, MsgId, MsgId, int, int, QVariantList) {}; - virtual QVariantList requestBacklogAll(MsgId first = -1, MsgId last = -1, int limit = -1, int additional = 0); - inline virtual void receiveBacklogAll(MsgId, MsgId, int, int, QVariantList) {}; + virtual QVariantList requestBacklogAll(MsgId first = -1, MsgId last = -1, int limit = -1, int additional = 0); + inline virtual void receiveBacklogAll(MsgId, MsgId, int, int, QVariantList) {}; signals: - void backlogRequested(BufferId, MsgId, MsgId, int, int); - void backlogAllRequested(MsgId, MsgId, int, int); + void backlogRequested(BufferId, MsgId, MsgId, int, int); + void backlogAllRequested(MsgId, MsgId, int, int); }; + #endif // BACKLOGMANAGER_H diff --git a/src/common/basichandler.cpp b/src/common/basichandler.cpp index fe80c33f..0717cbf3 100644 --- a/src/common/basichandler.cpp +++ b/src/common/basichandler.cpp @@ -24,70 +24,78 @@ #include "logger.h" BasicHandler::BasicHandler(QObject *parent) - : QObject(parent), + : QObject(parent), _defaultHandler(-1), _initDone(false), _methodPrefix("handle") { } + BasicHandler::BasicHandler(const QString &methodPrefix, QObject *parent) - : QObject(parent), + : QObject(parent), _defaultHandler(-1), _initDone(false), _methodPrefix(methodPrefix) { } -QStringList BasicHandler::providesHandlers() { - return handlerHash().keys(); + +QStringList BasicHandler::providesHandlers() +{ + return handlerHash().keys(); } -const QHash &BasicHandler::handlerHash() { - if(!_initDone) { - for(int i = metaObject()->methodOffset(); i < metaObject()->methodCount(); i++) { - QString methodSignature(metaObject()->method(i).signature()); - if(methodSignature.startsWith("defaultHandler")) { - _defaultHandler = i; - continue; - } - - if(!methodSignature.startsWith(_methodPrefix)) - continue; - - methodSignature = methodSignature.section('(',0,0); // chop the attribute list - methodSignature = methodSignature.mid(_methodPrefix.length()); // strip "handle" or whatever the prefix is - _handlerHash[methodSignature] = i; + +const QHash &BasicHandler::handlerHash() +{ + if (!_initDone) { + for (int i = metaObject()->methodOffset(); i < metaObject()->methodCount(); i++) { + QString methodSignature(metaObject()->method(i).signature()); + if (methodSignature.startsWith("defaultHandler")) { + _defaultHandler = i; + continue; + } + + if (!methodSignature.startsWith(_methodPrefix)) + continue; + + methodSignature = methodSignature.section('(', 0, 0); // chop the attribute list + methodSignature = methodSignature.mid(_methodPrefix.length()); // strip "handle" or whatever the prefix is + _handlerHash[methodSignature] = i; + } + _initDone = true; } - _initDone = true; - } - return _handlerHash; + return _handlerHash; } + void BasicHandler::handle(const QString &member, QGenericArgument val0, - QGenericArgument val1, QGenericArgument val2, - QGenericArgument val3, QGenericArgument val4, - QGenericArgument val5, QGenericArgument val6, - QGenericArgument val7, QGenericArgument val8) { - // Now we try to find a handler for this message. BTW, I do love the Trolltech guys ;-) - // and now we even have a fast lookup! Thanks thiago! - - QString handler = member.toLower(); - handler[0] = handler[0].toUpper(); - - if(!handlerHash().contains(handler)) { - if(_defaultHandler == -1) { - qWarning() << QString("No such Handler: %1::%2%3").arg(metaObject()->className(), _methodPrefix, handler); - return; - } else { - void *param[] = {0, Q_ARG(QString, member).data(), val0.data(), val1.data(), val2.data(), val3.data(), val4.data(), - val5.data(), val6.data(), val7.data(), val8.data(), val8.data()}; - qt_metacall(QMetaObject::InvokeMetaMethod, _defaultHandler, param); - return; + QGenericArgument val1, QGenericArgument val2, + QGenericArgument val3, QGenericArgument val4, + QGenericArgument val5, QGenericArgument val6, + QGenericArgument val7, QGenericArgument val8) +{ + // Now we try to find a handler for this message. BTW, I do love the Trolltech guys ;-) + // and now we even have a fast lookup! Thanks thiago! + + QString handler = member.toLower(); + handler[0] = handler[0].toUpper(); + + if (!handlerHash().contains(handler)) { + if (_defaultHandler == -1) { + qWarning() << QString("No such Handler: %1::%2%3").arg(metaObject()->className(), _methodPrefix, handler); + return; + } + else { + void *param[] = { 0, Q_ARG(QString, member).data(), val0.data(), val1.data(), val2.data(), val3.data(), val4.data(), + val5.data(), val6.data(), val7.data(), val8.data(), val8.data() }; + qt_metacall(QMetaObject::InvokeMetaMethod, _defaultHandler, param); + return; + } } - } - void *param[] = {0, val0.data(), val1.data(), val2.data(), val3.data(), val4.data(), - val5.data(), val6.data(), val7.data(), val8.data(), val8.data(), 0}; - qt_metacall(QMetaObject::InvokeMetaMethod, handlerHash()[handler], param); + void *param[] = { 0, val0.data(), val1.data(), val2.data(), val3.data(), val4.data(), + val5.data(), val6.data(), val7.data(), val8.data(), val8.data(), 0 }; + qt_metacall(QMetaObject::InvokeMetaMethod, handlerHash()[handler], param); } diff --git a/src/common/basichandler.h b/src/common/basichandler.h index e62d128f..78801c17 100644 --- a/src/common/basichandler.h +++ b/src/common/basichandler.h @@ -27,27 +27,30 @@ #include #include -class BasicHandler : public QObject { - Q_OBJECT +class BasicHandler : public QObject +{ + Q_OBJECT public: - BasicHandler(QObject *parent = 0); - BasicHandler(const QString &methodPrefix, QObject *parent = 0); + BasicHandler(QObject *parent = 0); + BasicHandler(const QString &methodPrefix, QObject *parent = 0); - QStringList providesHandlers(); + QStringList providesHandlers(); protected: - virtual void handle(const QString &member, QGenericArgument val0 = QGenericArgument(0), - QGenericArgument val1 = QGenericArgument(), QGenericArgument val2 = QGenericArgument(), - QGenericArgument val3 = QGenericArgument(), QGenericArgument val4 = QGenericArgument(), - QGenericArgument val5 = QGenericArgument(), QGenericArgument val6 = QGenericArgument(), - QGenericArgument val7 = QGenericArgument(), QGenericArgument val8 = QGenericArgument()); + virtual void handle(const QString &member, QGenericArgument val0 = QGenericArgument(0), + QGenericArgument val1 = QGenericArgument(), QGenericArgument val2 = QGenericArgument(), + QGenericArgument val3 = QGenericArgument(), QGenericArgument val4 = QGenericArgument(), + QGenericArgument val5 = QGenericArgument(), QGenericArgument val6 = QGenericArgument(), + QGenericArgument val7 = QGenericArgument(), QGenericArgument val8 = QGenericArgument()); private: - const QHash &handlerHash(); - QHash _handlerHash; - int _defaultHandler; - bool _initDone; - QString _methodPrefix; + const QHash &handlerHash(); + QHash _handlerHash; + int _defaultHandler; + bool _initDone; + QString _methodPrefix; }; + + #endif diff --git a/src/common/bufferinfo.cpp b/src/common/bufferinfo.cpp index 57320487..fb6678f5 100644 --- a/src/common/bufferinfo.cpp +++ b/src/common/bufferinfo.cpp @@ -28,7 +28,7 @@ #include "util.h" BufferInfo::BufferInfo() - : _bufferId(0), + : _bufferId(0), _netid(0), _type(InvalidBuffer), _groupId(0), @@ -36,8 +36,9 @@ BufferInfo::BufferInfo() { } + BufferInfo::BufferInfo(BufferId id, NetworkId networkid, Type type, uint gid, QString buf) - : _bufferId(id), + : _bufferId(id), _netid(networkid), _type(type), _groupId(gid), @@ -45,37 +46,48 @@ BufferInfo::BufferInfo(BufferId id, NetworkId networkid, Type type, uint gid, Q { } -BufferInfo BufferInfo::fakeStatusBuffer(NetworkId networkId) { - return BufferInfo(0, networkId, StatusBuffer); -} -QString BufferInfo::bufferName() const { - if(isChannelName(_bufferName)) - return _bufferName; - else - return nickFromMask(_bufferName); // FIXME get rid of global functions and use the Network stuff instead! +BufferInfo BufferInfo::fakeStatusBuffer(NetworkId networkId) +{ + return BufferInfo(0, networkId, StatusBuffer); } -QDebug operator<<(QDebug dbg, const BufferInfo &b) { - dbg.nospace() << "(bufId: " << b.bufferId() << ", netId: " << b.networkId() << ", groupId: " << b.groupId() << ", buf: " << b.bufferName() << ")"; - return dbg.space(); + +QString BufferInfo::bufferName() const +{ + if (isChannelName(_bufferName)) + return _bufferName; + else + return nickFromMask(_bufferName); // FIXME get rid of global functions and use the Network stuff instead! } -QDataStream &operator<<(QDataStream &out, const BufferInfo &bufferInfo) { - out << bufferInfo._bufferId << bufferInfo._netid << (qint16)bufferInfo._type << bufferInfo._groupId << bufferInfo._bufferName.toUtf8(); - return out; + +QDebug operator<<(QDebug dbg, const BufferInfo &b) +{ + dbg.nospace() << "(bufId: " << b.bufferId() << ", netId: " << b.networkId() << ", groupId: " << b.groupId() << ", buf: " << b.bufferName() << ")"; + return dbg.space(); } -QDataStream &operator>>(QDataStream &in, BufferInfo &bufferInfo) { - QByteArray buffername; - qint16 bufferType; - in >> bufferInfo._bufferId >> bufferInfo._netid >> bufferType >> bufferInfo._groupId >> buffername; - bufferInfo._type = (BufferInfo::Type)bufferType; - bufferInfo._bufferName = QString::fromUtf8(buffername); - return in; + +QDataStream &operator<<(QDataStream &out, const BufferInfo &bufferInfo) +{ + out << bufferInfo._bufferId << bufferInfo._netid << (qint16)bufferInfo._type << bufferInfo._groupId << bufferInfo._bufferName.toUtf8(); + return out; } -uint qHash(const BufferInfo &bufferid) { - return qHash(bufferid._bufferId); + +QDataStream &operator>>(QDataStream &in, BufferInfo &bufferInfo) +{ + QByteArray buffername; + qint16 bufferType; + in >> bufferInfo._bufferId >> bufferInfo._netid >> bufferType >> bufferInfo._groupId >> buffername; + bufferInfo._type = (BufferInfo::Type)bufferType; + bufferInfo._bufferName = QString::fromUtf8(buffername); + return in; } + +uint qHash(const BufferInfo &bufferid) +{ + return qHash(bufferid._bufferId); +} diff --git a/src/common/bufferinfo.h b/src/common/bufferinfo.h index 63ba6a52..2956af65 100644 --- a/src/common/bufferinfo.h +++ b/src/common/bufferinfo.h @@ -25,53 +25,55 @@ class QString; class QDataStream; -class BufferInfo { +class BufferInfo +{ public: - enum Type { - InvalidBuffer = 0x00, - StatusBuffer = 0x01, - ChannelBuffer = 0x02, - QueryBuffer = 0x04, - GroupBuffer = 0x08 - }; - - enum Activity { - NoActivity = 0x00, - OtherActivity = 0x01, - NewMessage = 0x02, - Highlight = 0x40 - }; - Q_DECLARE_FLAGS(ActivityLevel, Activity) - - BufferInfo(); - BufferInfo(BufferId id, NetworkId networkid, Type type, uint gid = 0, QString buf = QString()); - - static BufferInfo fakeStatusBuffer(NetworkId networkId); - - inline bool isValid() const { return _bufferId != 0; } - inline const BufferId &bufferId() const { return _bufferId; } - inline void setBufferId(BufferId id) { _bufferId = id; } - inline const NetworkId &networkId() const { return _netid; } - inline const Type &type() const { return _type; } - inline const uint &groupId() const { return _groupId; } - void setGroupId(uint gid) { _groupId = gid; } - - QString bufferName() const; - - inline bool operator==(const BufferInfo &other) const { return _bufferId == other._bufferId; } + enum Type { + InvalidBuffer = 0x00, + StatusBuffer = 0x01, + ChannelBuffer = 0x02, + QueryBuffer = 0x04, + GroupBuffer = 0x08 + }; + + enum Activity { + NoActivity = 0x00, + OtherActivity = 0x01, + NewMessage = 0x02, + Highlight = 0x40 + }; + Q_DECLARE_FLAGS(ActivityLevel, Activity) + + BufferInfo(); + BufferInfo(BufferId id, NetworkId networkid, Type type, uint gid = 0, QString buf = QString()); + + static BufferInfo fakeStatusBuffer(NetworkId networkId); + + inline bool isValid() const { return _bufferId != 0; } + inline const BufferId &bufferId() const { return _bufferId; } + inline void setBufferId(BufferId id) { _bufferId = id; } + inline const NetworkId &networkId() const { return _netid; } + inline const Type &type() const { return _type; } + inline const uint &groupId() const { return _groupId; } + void setGroupId(uint gid) { _groupId = gid; } + + QString bufferName() const; + + inline bool operator==(const BufferInfo &other) const { return _bufferId == other._bufferId; } private: - BufferId _bufferId; - NetworkId _netid; - Type _type; - uint _groupId; - QString _bufferName; - - friend uint qHash(const BufferInfo &); - friend QDataStream &operator<<(QDataStream &out, const BufferInfo &bufferInfo); - friend QDataStream &operator>>(QDataStream &in, BufferInfo &bufferInfo); + BufferId _bufferId; + NetworkId _netid; + Type _type; + uint _groupId; + QString _bufferName; + + friend uint qHash(const BufferInfo &); + friend QDataStream &operator<<(QDataStream &out, const BufferInfo &bufferInfo); + friend QDataStream &operator>>(QDataStream &in, BufferInfo &bufferInfo); }; + QDataStream &operator<<(QDataStream &out, const BufferInfo &bufferInfo); QDataStream &operator>>(QDataStream &in, BufferInfo &bufferInfo); QDebug operator<<(QDebug dbg, const BufferInfo &b); diff --git a/src/common/buffersyncer.cpp b/src/common/buffersyncer.cpp index 222f65bc..581adf69 100644 --- a/src/common/buffersyncer.cpp +++ b/src/common/buffersyncer.cpp @@ -22,104 +22,125 @@ INIT_SYNCABLE_OBJECT(BufferSyncer) BufferSyncer::BufferSyncer(QObject *parent) - : SyncableObject(parent) + : SyncableObject(parent) { } + BufferSyncer::BufferSyncer(const QHash &lastSeenMsg, const QHash &markerLines, QObject *parent) - : SyncableObject(parent), + : SyncableObject(parent), _lastSeenMsg(lastSeenMsg), _markerLines(markerLines) { } -MsgId BufferSyncer::lastSeenMsg(BufferId buffer) const { - return _lastSeenMsg.value(buffer, MsgId()); + +MsgId BufferSyncer::lastSeenMsg(BufferId buffer) const +{ + return _lastSeenMsg.value(buffer, MsgId()); } -bool BufferSyncer::setLastSeenMsg(BufferId buffer, const MsgId &msgId) { - if(!msgId.isValid()) - return false; - const MsgId oldLastSeenMsg = lastSeenMsg(buffer); - if(!oldLastSeenMsg.isValid() || oldLastSeenMsg < msgId) { - _lastSeenMsg[buffer] = msgId; - SYNC(ARG(buffer), ARG(msgId)) - emit lastSeenMsgSet(buffer, msgId); - return true; - } - return false; +bool BufferSyncer::setLastSeenMsg(BufferId buffer, const MsgId &msgId) +{ + if (!msgId.isValid()) + return false; + + const MsgId oldLastSeenMsg = lastSeenMsg(buffer); + if (!oldLastSeenMsg.isValid() || oldLastSeenMsg < msgId) { + _lastSeenMsg[buffer] = msgId; + SYNC(ARG(buffer), ARG(msgId)) + emit lastSeenMsgSet(buffer, msgId); + return true; + } + return false; } -MsgId BufferSyncer::markerLine(BufferId buffer) const { - return _markerLines.value(buffer, MsgId()); + +MsgId BufferSyncer::markerLine(BufferId buffer) const +{ + return _markerLines.value(buffer, MsgId()); } -bool BufferSyncer::setMarkerLine(BufferId buffer, const MsgId &msgId) { - if(!msgId.isValid()) - return false; - if(_markerLines.value(buffer) == msgId) - return false; +bool BufferSyncer::setMarkerLine(BufferId buffer, const MsgId &msgId) +{ + if (!msgId.isValid()) + return false; + + if (_markerLines.value(buffer) == msgId) + return false; - _markerLines[buffer] = msgId; - SYNC(ARG(buffer), ARG(msgId)) - emit markerLineSet(buffer, msgId); - return true; + _markerLines[buffer] = msgId; + SYNC(ARG(buffer), ARG(msgId)) + emit markerLineSet(buffer, msgId); + return true; } -QVariantList BufferSyncer::initLastSeenMsg() const { - QVariantList list; - QHash::const_iterator iter = _lastSeenMsg.constBegin(); - while(iter != _lastSeenMsg.constEnd()) { - list << QVariant::fromValue(iter.key()) - << QVariant::fromValue(iter.value()); - ++iter; - } - return list; + +QVariantList BufferSyncer::initLastSeenMsg() const +{ + QVariantList list; + QHash::const_iterator iter = _lastSeenMsg.constBegin(); + while (iter != _lastSeenMsg.constEnd()) { + list << QVariant::fromValue(iter.key()) + << QVariant::fromValue(iter.value()); + ++iter; + } + return list; } -void BufferSyncer::initSetLastSeenMsg(const QVariantList &list) { - _lastSeenMsg.clear(); - Q_ASSERT(list.count() % 2 == 0); - for(int i = 0; i < list.count(); i += 2) { - setLastSeenMsg(list.at(i).value(), list.at(i+1).value()); - } + +void BufferSyncer::initSetLastSeenMsg(const QVariantList &list) +{ + _lastSeenMsg.clear(); + Q_ASSERT(list.count() % 2 == 0); + for (int i = 0; i < list.count(); i += 2) { + setLastSeenMsg(list.at(i).value(), list.at(i+1).value()); + } } -QVariantList BufferSyncer::initMarkerLines() const { - QVariantList list; - QHash::const_iterator iter = _markerLines.constBegin(); - while(iter != _markerLines.constEnd()) { - list << QVariant::fromValue(iter.key()) - << QVariant::fromValue(iter.value()); - ++iter; - } - return list; + +QVariantList BufferSyncer::initMarkerLines() const +{ + QVariantList list; + QHash::const_iterator iter = _markerLines.constBegin(); + while (iter != _markerLines.constEnd()) { + list << QVariant::fromValue(iter.key()) + << QVariant::fromValue(iter.value()); + ++iter; + } + return list; } -void BufferSyncer::initSetMarkerLines(const QVariantList &list) { - _markerLines.clear(); - Q_ASSERT(list.count() % 2 == 0); - for(int i = 0; i < list.count(); i += 2) { - setMarkerLine(list.at(i).value(), list.at(i+1).value()); - } + +void BufferSyncer::initSetMarkerLines(const QVariantList &list) +{ + _markerLines.clear(); + Q_ASSERT(list.count() % 2 == 0); + for (int i = 0; i < list.count(); i += 2) { + setMarkerLine(list.at(i).value(), list.at(i+1).value()); + } } -void BufferSyncer::removeBuffer(BufferId buffer) { - if(_lastSeenMsg.contains(buffer)) - _lastSeenMsg.remove(buffer); - if(_markerLines.contains(buffer)) - _markerLines.remove(buffer); - SYNC(ARG(buffer)) - emit bufferRemoved(buffer); + +void BufferSyncer::removeBuffer(BufferId buffer) +{ + if (_lastSeenMsg.contains(buffer)) + _lastSeenMsg.remove(buffer); + if (_markerLines.contains(buffer)) + _markerLines.remove(buffer); + SYNC(ARG(buffer)) + emit bufferRemoved(buffer); } -void BufferSyncer::mergeBuffersPermanently(BufferId buffer1, BufferId buffer2) { - if(_lastSeenMsg.contains(buffer2)) - _lastSeenMsg.remove(buffer2); - if(_markerLines.contains(buffer2)) - _markerLines.remove(buffer2); - SYNC(ARG(buffer1), ARG(buffer2)) - emit buffersPermanentlyMerged(buffer1, buffer2); + +void BufferSyncer::mergeBuffersPermanently(BufferId buffer1, BufferId buffer2) +{ + if (_lastSeenMsg.contains(buffer2)) + _lastSeenMsg.remove(buffer2); + if (_markerLines.contains(buffer2)) + _markerLines.remove(buffer2); + SYNC(ARG(buffer1), ARG(buffer2)) + emit buffersPermanentlyMerged(buffer1, buffer2); } diff --git a/src/common/buffersyncer.h b/src/common/buffersyncer.h index 716178a7..0805e343 100644 --- a/src/common/buffersyncer.h +++ b/src/common/buffersyncer.h @@ -24,63 +24,65 @@ #include "syncableobject.h" #include "types.h" -class BufferSyncer : public SyncableObject { - SYNCABLE_OBJECT - Q_OBJECT +class BufferSyncer : public SyncableObject +{ + SYNCABLE_OBJECT + Q_OBJECT public: - explicit BufferSyncer(QObject *parent); - explicit BufferSyncer(const QHash &lastSeenMsg, const QHash &markerLines, QObject *parent); + explicit BufferSyncer(QObject *parent); + explicit BufferSyncer(const QHash &lastSeenMsg, const QHash &markerLines, QObject *parent); - inline virtual const QMetaObject *syncMetaObject() const { return &staticMetaObject; } + inline virtual const QMetaObject *syncMetaObject() const { return &staticMetaObject; } - MsgId lastSeenMsg(BufferId buffer) const; - MsgId markerLine(BufferId buffer) const; + MsgId lastSeenMsg(BufferId buffer) const; + MsgId markerLine(BufferId buffer) const; public slots: - QVariantList initLastSeenMsg() const; - void initSetLastSeenMsg(const QVariantList &); + QVariantList initLastSeenMsg() const; + void initSetLastSeenMsg(const QVariantList &); - QVariantList initMarkerLines() const; - void initSetMarkerLines(const QVariantList &); + QVariantList initMarkerLines() const; + void initSetMarkerLines(const QVariantList &); - virtual inline void requestSetLastSeenMsg(BufferId buffer, const MsgId &msgId) { REQUEST(ARG(buffer), ARG(msgId)) } - virtual inline void requestSetMarkerLine(BufferId buffer, const MsgId &msgId) { REQUEST(ARG(buffer), ARG(msgId)) setMarkerLine(buffer, msgId); } + virtual inline void requestSetLastSeenMsg(BufferId buffer, const MsgId &msgId) { REQUEST(ARG(buffer), ARG(msgId)) } + virtual inline void requestSetMarkerLine(BufferId buffer, const MsgId &msgId) { REQUEST(ARG(buffer), ARG(msgId)) setMarkerLine(buffer, msgId); } - virtual inline void requestRemoveBuffer(BufferId buffer) { REQUEST(ARG(buffer)) } - virtual void removeBuffer(BufferId buffer); + virtual inline void requestRemoveBuffer(BufferId buffer) { REQUEST(ARG(buffer)) } + virtual void removeBuffer(BufferId buffer); - virtual inline void requestRenameBuffer(BufferId buffer, QString newName) { REQUEST(ARG(buffer), ARG(newName)) } - virtual inline void renameBuffer(BufferId buffer, QString newName) { SYNC(ARG(buffer), ARG(newName)) emit bufferRenamed(buffer, newName); } + virtual inline void requestRenameBuffer(BufferId buffer, QString newName) { REQUEST(ARG(buffer), ARG(newName)) } + virtual inline void renameBuffer(BufferId buffer, QString newName) { SYNC(ARG(buffer), ARG(newName)) emit bufferRenamed(buffer, newName); } - virtual inline void requestMergeBuffersPermanently(BufferId buffer1, BufferId buffer2) { emit REQUEST(ARG(buffer1), ARG(buffer2)) } - virtual void mergeBuffersPermanently(BufferId buffer1, BufferId buffer2); + virtual inline void requestMergeBuffersPermanently(BufferId buffer1, BufferId buffer2) { emit REQUEST(ARG(buffer1), ARG(buffer2)) } + virtual void mergeBuffersPermanently(BufferId buffer1, BufferId buffer2); - virtual inline void requestPurgeBufferIds() { REQUEST(NO_ARG); } + virtual inline void requestPurgeBufferIds() { REQUEST(NO_ARG); } - virtual inline void requestMarkBufferAsRead(BufferId buffer) { REQUEST(ARG(buffer)) emit bufferMarkedAsRead(buffer); } - virtual inline void markBufferAsRead(BufferId buffer) { SYNC(ARG(buffer)) emit bufferMarkedAsRead(buffer); } + virtual inline void requestMarkBufferAsRead(BufferId buffer) { REQUEST(ARG(buffer)) emit bufferMarkedAsRead(buffer); } + virtual inline void markBufferAsRead(BufferId buffer) { SYNC(ARG(buffer)) emit bufferMarkedAsRead(buffer); } signals: - void lastSeenMsgSet(BufferId buffer, const MsgId &msgId); - void markerLineSet(BufferId buffer, const MsgId &msgId); - void bufferRemoved(BufferId buffer); - void bufferRenamed(BufferId buffer, QString newName); - void buffersPermanentlyMerged(BufferId buffer1, BufferId buffer2); - void bufferMarkedAsRead(BufferId buffer); + void lastSeenMsgSet(BufferId buffer, const MsgId &msgId); + void markerLineSet(BufferId buffer, const MsgId &msgId); + void bufferRemoved(BufferId buffer); + void bufferRenamed(BufferId buffer, QString newName); + void buffersPermanentlyMerged(BufferId buffer1, BufferId buffer2); + void bufferMarkedAsRead(BufferId buffer); protected slots: - bool setLastSeenMsg(BufferId buffer, const MsgId &msgId); - bool setMarkerLine(BufferId buffer, const MsgId &msgId); + bool setLastSeenMsg(BufferId buffer, const MsgId &msgId); + bool setMarkerLine(BufferId buffer, const MsgId &msgId); protected: - inline QList lastSeenBufferIds() const { return _lastSeenMsg.keys(); } - inline QList markerLineBufferIds() const { return _markerLines.keys(); } - inline QHash markerLines() const { return _markerLines; } + inline QList lastSeenBufferIds() const { return _lastSeenMsg.keys(); } + inline QList markerLineBufferIds() const { return _markerLines.keys(); } + inline QHash markerLines() const { return _markerLines; } private: - QHash _lastSeenMsg; - QHash _markerLines; + QHash _lastSeenMsg; + QHash _markerLines; }; + #endif diff --git a/src/common/bufferviewconfig.cpp b/src/common/bufferviewconfig.cpp index 5cae5f8f..15750ced 100644 --- a/src/common/bufferviewconfig.cpp +++ b/src/common/bufferviewconfig.cpp @@ -24,7 +24,7 @@ INIT_SYNCABLE_OBJECT(BufferViewConfig) BufferViewConfig::BufferViewConfig(int bufferViewId, QObject *parent) - : SyncableObject(parent), + : SyncableObject(parent), _bufferViewId(bufferViewId), _addNewBuffersAutomatically(true), _sortAlphabetically(true), @@ -33,214 +33,253 @@ BufferViewConfig::BufferViewConfig(int bufferViewId, QObject *parent) _allowedBufferTypes(BufferInfo::StatusBuffer | BufferInfo::ChannelBuffer | BufferInfo::QueryBuffer | BufferInfo::GroupBuffer), _minimumActivity(0) { - setObjectName(QString::number(bufferViewId)); + setObjectName(QString::number(bufferViewId)); } + BufferViewConfig::BufferViewConfig(int bufferViewId, const QVariantMap &properties, QObject *parent) - : SyncableObject(parent), + : SyncableObject(parent), _bufferViewId(bufferViewId) { - fromVariantMap(properties); - setObjectName(QString::number(bufferViewId)); + fromVariantMap(properties); + setObjectName(QString::number(bufferViewId)); } -void BufferViewConfig::setBufferViewName(const QString &bufferViewName) { - if(_bufferViewName == bufferViewName) - return; - _bufferViewName = bufferViewName; - SYNC(ARG(bufferViewName)) - emit bufferViewNameSet(bufferViewName); +void BufferViewConfig::setBufferViewName(const QString &bufferViewName) +{ + if (_bufferViewName == bufferViewName) + return; + + _bufferViewName = bufferViewName; + SYNC(ARG(bufferViewName)) + emit bufferViewNameSet(bufferViewName); } -void BufferViewConfig::setNetworkId(const NetworkId &networkId) { - if(_networkId == networkId) - return; - _networkId = networkId; - SYNC(ARG(networkId)) - emit networkIdSet(networkId); - emit configChanged(); +void BufferViewConfig::setNetworkId(const NetworkId &networkId) +{ + if (_networkId == networkId) + return; + + _networkId = networkId; + SYNC(ARG(networkId)) + emit networkIdSet(networkId); + emit configChanged(); } -void BufferViewConfig::setAddNewBuffersAutomatically(bool addNewBuffersAutomatically) { - if(_addNewBuffersAutomatically == addNewBuffersAutomatically) - return; - _addNewBuffersAutomatically = addNewBuffersAutomatically; - SYNC(ARG(addNewBuffersAutomatically)) - emit configChanged(); +void BufferViewConfig::setAddNewBuffersAutomatically(bool addNewBuffersAutomatically) +{ + if (_addNewBuffersAutomatically == addNewBuffersAutomatically) + return; + + _addNewBuffersAutomatically = addNewBuffersAutomatically; + SYNC(ARG(addNewBuffersAutomatically)) + emit configChanged(); } -void BufferViewConfig::setSortAlphabetically(bool sortAlphabetically) { - if(_sortAlphabetically == sortAlphabetically) - return; - _sortAlphabetically = sortAlphabetically; - SYNC(ARG(sortAlphabetically)) - emit configChanged(); +void BufferViewConfig::setSortAlphabetically(bool sortAlphabetically) +{ + if (_sortAlphabetically == sortAlphabetically) + return; + + _sortAlphabetically = sortAlphabetically; + SYNC(ARG(sortAlphabetically)) + emit configChanged(); } -void BufferViewConfig::setDisableDecoration(bool disableDecoration) { - if(_disableDecoration == disableDecoration) - return; - _disableDecoration = disableDecoration; - SYNC(ARG(disableDecoration)) +void BufferViewConfig::setDisableDecoration(bool disableDecoration) +{ + if (_disableDecoration == disableDecoration) + return; + + _disableDecoration = disableDecoration; + SYNC(ARG(disableDecoration)) } -void BufferViewConfig::setAllowedBufferTypes(int bufferTypes) { - if(_allowedBufferTypes == bufferTypes) - return; - _allowedBufferTypes = bufferTypes; - SYNC(ARG(bufferTypes)) - emit configChanged(); +void BufferViewConfig::setAllowedBufferTypes(int bufferTypes) +{ + if (_allowedBufferTypes == bufferTypes) + return; + + _allowedBufferTypes = bufferTypes; + SYNC(ARG(bufferTypes)) + emit configChanged(); } -void BufferViewConfig::setMinimumActivity(int activity) { - if(_minimumActivity == activity) - return; - _minimumActivity = activity; - SYNC(ARG(activity)) - emit configChanged(); +void BufferViewConfig::setMinimumActivity(int activity) +{ + if (_minimumActivity == activity) + return; + + _minimumActivity = activity; + SYNC(ARG(activity)) + emit configChanged(); } -void BufferViewConfig::setHideInactiveBuffers(bool hideInactiveBuffers) { - if(_hideInactiveBuffers == hideInactiveBuffers) - return; - _hideInactiveBuffers = hideInactiveBuffers; - SYNC(ARG(hideInactiveBuffers)) - emit configChanged(); +void BufferViewConfig::setHideInactiveBuffers(bool hideInactiveBuffers) +{ + if (_hideInactiveBuffers == hideInactiveBuffers) + return; + + _hideInactiveBuffers = hideInactiveBuffers; + SYNC(ARG(hideInactiveBuffers)) + emit configChanged(); } -QVariantList BufferViewConfig::initBufferList() const { - QVariantList buffers; - foreach(BufferId bufferId, _buffers) { - buffers << qVariantFromValue(bufferId); - } +QVariantList BufferViewConfig::initBufferList() const +{ + QVariantList buffers; - return buffers; + foreach(BufferId bufferId, _buffers) { + buffers << qVariantFromValue(bufferId); + } + + return buffers; } -void BufferViewConfig::initSetBufferList(const QVariantList &buffers) { - _buffers.clear(); - foreach(QVariant buffer, buffers) { - _buffers << buffer.value(); - } +void BufferViewConfig::initSetBufferList(const QVariantList &buffers) +{ + _buffers.clear(); - emit configChanged(); // used to track changes in the settingspage + foreach(QVariant buffer, buffers) { + _buffers << buffer.value(); + } + + emit configChanged(); // used to track changes in the settingspage } -void BufferViewConfig::initSetBufferList(const QList &buffers) { - _buffers.clear(); - foreach(BufferId bufferId, buffers) { - _buffers << bufferId; - } +void BufferViewConfig::initSetBufferList(const QList &buffers) +{ + _buffers.clear(); + + foreach(BufferId bufferId, buffers) { + _buffers << bufferId; + } - emit configChanged(); // used to track changes in the settingspage + emit configChanged(); // used to track changes in the settingspage } -QVariantList BufferViewConfig::initRemovedBuffers() const { - QVariantList removedBuffers; - foreach(BufferId bufferId, _removedBuffers) { - removedBuffers << qVariantFromValue(bufferId); - } +QVariantList BufferViewConfig::initRemovedBuffers() const +{ + QVariantList removedBuffers; + + foreach(BufferId bufferId, _removedBuffers) { + removedBuffers << qVariantFromValue(bufferId); + } - return removedBuffers; + return removedBuffers; } -void BufferViewConfig::initSetRemovedBuffers(const QVariantList &buffers) { - _removedBuffers.clear(); - foreach(QVariant buffer, buffers) { - _removedBuffers << buffer.value(); - } +void BufferViewConfig::initSetRemovedBuffers(const QVariantList &buffers) +{ + _removedBuffers.clear(); + + foreach(QVariant buffer, buffers) { + _removedBuffers << buffer.value(); + } } -QVariantList BufferViewConfig::initTemporarilyRemovedBuffers() const { - QVariantList temporarilyRemovedBuffers; - foreach(BufferId bufferId, _temporarilyRemovedBuffers) { - temporarilyRemovedBuffers << qVariantFromValue(bufferId); - } +QVariantList BufferViewConfig::initTemporarilyRemovedBuffers() const +{ + QVariantList temporarilyRemovedBuffers; - return temporarilyRemovedBuffers; + foreach(BufferId bufferId, _temporarilyRemovedBuffers) { + temporarilyRemovedBuffers << qVariantFromValue(bufferId); + } + + return temporarilyRemovedBuffers; } -void BufferViewConfig::initSetTemporarilyRemovedBuffers(const QVariantList &buffers) { - _temporarilyRemovedBuffers.clear(); - foreach(QVariant buffer, buffers) { - _temporarilyRemovedBuffers << buffer.value(); - } +void BufferViewConfig::initSetTemporarilyRemovedBuffers(const QVariantList &buffers) +{ + _temporarilyRemovedBuffers.clear(); + + foreach(QVariant buffer, buffers) { + _temporarilyRemovedBuffers << buffer.value(); + } } -void BufferViewConfig::addBuffer(const BufferId &bufferId, int pos) { - if(_buffers.contains(bufferId)) - return; - if(pos < 0) - pos = 0; - if(pos > _buffers.count()) - pos = _buffers.count(); +void BufferViewConfig::addBuffer(const BufferId &bufferId, int pos) +{ + if (_buffers.contains(bufferId)) + return; - if(_removedBuffers.contains(bufferId)) - _removedBuffers.remove(bufferId); + if (pos < 0) + pos = 0; + if (pos > _buffers.count()) + pos = _buffers.count(); - if(_temporarilyRemovedBuffers.contains(bufferId)) - _temporarilyRemovedBuffers.remove(bufferId); + if (_removedBuffers.contains(bufferId)) + _removedBuffers.remove(bufferId); - _buffers.insert(pos, bufferId); - SYNC(ARG(bufferId), ARG(pos)) - emit bufferAdded(bufferId, pos); - emit configChanged(); -} + if (_temporarilyRemovedBuffers.contains(bufferId)) + _temporarilyRemovedBuffers.remove(bufferId); -void BufferViewConfig::moveBuffer(const BufferId &bufferId, int pos) { - if(!_buffers.contains(bufferId)) - return; + _buffers.insert(pos, bufferId); + SYNC(ARG(bufferId), ARG(pos)) + emit bufferAdded(bufferId, pos); + emit configChanged(); +} - if(pos < 0) - pos = 0; - if(pos >= _buffers.count()) - pos = _buffers.count() - 1; - _buffers.move(_buffers.indexOf(bufferId), pos); - SYNC(ARG(bufferId), ARG(pos)) - emit bufferMoved(bufferId, pos); - emit configChanged(); +void BufferViewConfig::moveBuffer(const BufferId &bufferId, int pos) +{ + if (!_buffers.contains(bufferId)) + return; + + if (pos < 0) + pos = 0; + if (pos >= _buffers.count()) + pos = _buffers.count() - 1; + + _buffers.move(_buffers.indexOf(bufferId), pos); + SYNC(ARG(bufferId), ARG(pos)) + emit bufferMoved(bufferId, pos); + emit configChanged(); } -void BufferViewConfig::removeBuffer(const BufferId &bufferId) { - if(_buffers.contains(bufferId)) - _buffers.removeAt(_buffers.indexOf(bufferId)); - if(_removedBuffers.contains(bufferId)) - _removedBuffers.remove(bufferId); +void BufferViewConfig::removeBuffer(const BufferId &bufferId) +{ + if (_buffers.contains(bufferId)) + _buffers.removeAt(_buffers.indexOf(bufferId)); + + if (_removedBuffers.contains(bufferId)) + _removedBuffers.remove(bufferId); - _temporarilyRemovedBuffers << bufferId; - SYNC(ARG(bufferId)) - emit bufferRemoved(bufferId); - emit configChanged(); + _temporarilyRemovedBuffers << bufferId; + SYNC(ARG(bufferId)) + emit bufferRemoved(bufferId); + emit configChanged(); } -void BufferViewConfig::removeBufferPermanently(const BufferId &bufferId) { - if(_buffers.contains(bufferId)) - _buffers.removeAt(_buffers.indexOf(bufferId)); - if(_temporarilyRemovedBuffers.contains(bufferId)) - _temporarilyRemovedBuffers.remove(bufferId); +void BufferViewConfig::removeBufferPermanently(const BufferId &bufferId) +{ + if (_buffers.contains(bufferId)) + _buffers.removeAt(_buffers.indexOf(bufferId)); + + if (_temporarilyRemovedBuffers.contains(bufferId)) + _temporarilyRemovedBuffers.remove(bufferId); - _removedBuffers << bufferId; + _removedBuffers << bufferId; - SYNC(ARG(bufferId)) - emit bufferPermanentlyRemoved(bufferId); - emit configChanged(); + SYNC(ARG(bufferId)) + emit bufferPermanentlyRemoved(bufferId); + emit configChanged(); } diff --git a/src/common/bufferviewconfig.h b/src/common/bufferviewconfig.h index 75ca9cf6..e35e0bfb 100644 --- a/src/common/bufferviewconfig.h +++ b/src/common/bufferviewconfig.h @@ -25,114 +25,115 @@ #include "types.h" -class BufferViewConfig : public SyncableObject { - SYNCABLE_OBJECT - Q_OBJECT - - Q_PROPERTY(QString bufferViewName READ bufferViewName WRITE setBufferViewName) - Q_PROPERTY(NetworkId networkId READ networkId WRITE setNetworkId) - Q_PROPERTY(bool addNewBuffersAutomatically READ addNewBuffersAutomatically WRITE setAddNewBuffersAutomatically) - Q_PROPERTY(bool sortAlphabetically READ sortAlphabetically WRITE setSortAlphabetically) - Q_PROPERTY(bool hideInactiveBuffers READ hideInactiveBuffers WRITE setHideInactiveBuffers) - Q_PROPERTY(bool disableDecoration READ disableDecoration WRITE setDisableDecoration) - Q_PROPERTY(int allowedBufferTypes READ allowedBufferTypes WRITE setAllowedBufferTypes) - Q_PROPERTY(int minimumActivity READ minimumActivity WRITE setMinimumActivity) - -public: - BufferViewConfig(int bufferViewId, QObject *parent = 0); - BufferViewConfig(int bufferViewId, const QVariantMap &properties, QObject *parent = 0); - - inline virtual const QMetaObject *syncMetaObject() const { return &staticMetaObject; } +class BufferViewConfig : public SyncableObject +{ + SYNCABLE_OBJECT + Q_OBJECT + + Q_PROPERTY(QString bufferViewName READ bufferViewName WRITE setBufferViewName) + Q_PROPERTY(NetworkId networkId READ networkId WRITE setNetworkId) + Q_PROPERTY(bool addNewBuffersAutomatically READ addNewBuffersAutomatically WRITE setAddNewBuffersAutomatically) + Q_PROPERTY(bool sortAlphabetically READ sortAlphabetically WRITE setSortAlphabetically) + Q_PROPERTY(bool hideInactiveBuffers READ hideInactiveBuffers WRITE setHideInactiveBuffers) + Q_PROPERTY(bool disableDecoration READ disableDecoration WRITE setDisableDecoration) + Q_PROPERTY(int allowedBufferTypes READ allowedBufferTypes WRITE setAllowedBufferTypes) + Q_PROPERTY(int minimumActivity READ minimumActivity WRITE setMinimumActivity) + +public : + BufferViewConfig(int bufferViewId, QObject *parent = 0); + BufferViewConfig(int bufferViewId, const QVariantMap &properties, QObject *parent = 0); + + inline virtual const QMetaObject *syncMetaObject() const { return &staticMetaObject; } public slots: - inline int bufferViewId() const { return _bufferViewId; } + inline int bufferViewId() const { return _bufferViewId; } - inline const QString &bufferViewName() const { return _bufferViewName; } - void setBufferViewName(const QString &bufferViewName); + inline const QString &bufferViewName() const { return _bufferViewName; } + void setBufferViewName(const QString &bufferViewName); - inline const NetworkId &networkId() const { return _networkId; } - void setNetworkId(const NetworkId &networkId); + inline const NetworkId &networkId() const { return _networkId; } + void setNetworkId(const NetworkId &networkId); - inline bool addNewBuffersAutomatically() const { return _addNewBuffersAutomatically; } - void setAddNewBuffersAutomatically(bool addNewBuffersAutomatically); + inline bool addNewBuffersAutomatically() const { return _addNewBuffersAutomatically; } + void setAddNewBuffersAutomatically(bool addNewBuffersAutomatically); - inline bool sortAlphabetically() const { return _sortAlphabetically; } - void setSortAlphabetically(bool sortAlphabetically); + inline bool sortAlphabetically() const { return _sortAlphabetically; } + void setSortAlphabetically(bool sortAlphabetically); - inline bool disableDecoration() const { return _disableDecoration; } - void setDisableDecoration(bool disableDecoration); + inline bool disableDecoration() const { return _disableDecoration; } + void setDisableDecoration(bool disableDecoration); - inline int allowedBufferTypes() const { return _allowedBufferTypes; } - void setAllowedBufferTypes(int bufferTypes); + inline int allowedBufferTypes() const { return _allowedBufferTypes; } + void setAllowedBufferTypes(int bufferTypes); - inline int minimumActivity() const { return _minimumActivity; } - void setMinimumActivity(int activity); + inline int minimumActivity() const { return _minimumActivity; } + void setMinimumActivity(int activity); - inline bool hideInactiveBuffers() const { return _hideInactiveBuffers; } - void setHideInactiveBuffers(bool hideInactiveBuffers); + inline bool hideInactiveBuffers() const { return _hideInactiveBuffers; } + void setHideInactiveBuffers(bool hideInactiveBuffers); - virtual inline void requestSetBufferViewName(const QString &bufferViewName) { REQUEST(ARG(bufferViewName)) } + virtual inline void requestSetBufferViewName(const QString &bufferViewName) { REQUEST(ARG(bufferViewName)) } - const QList &bufferList() const { return _buffers; } - const QSet &removedBuffers() const { return _removedBuffers; } - const QSet &temporarilyRemovedBuffers() const { return _temporarilyRemovedBuffers; } + const QList &bufferList() const { return _buffers; } + const QSet &removedBuffers() const { return _removedBuffers; } + const QSet &temporarilyRemovedBuffers() const { return _temporarilyRemovedBuffers; } - QVariantList initBufferList() const; - void initSetBufferList(const QVariantList &buffers); - void initSetBufferList(const QList &buffers); + QVariantList initBufferList() const; + void initSetBufferList(const QVariantList &buffers); + void initSetBufferList(const QList &buffers); - QVariantList initRemovedBuffers() const; - void initSetRemovedBuffers(const QVariantList &buffers); + QVariantList initRemovedBuffers() const; + void initSetRemovedBuffers(const QVariantList &buffers); - QVariantList initTemporarilyRemovedBuffers() const; - void initSetTemporarilyRemovedBuffers(const QVariantList &buffers); - - void addBuffer(const BufferId &bufferId, int pos); - virtual inline void requestAddBuffer(const BufferId &bufferId, int pos) { REQUEST(ARG(bufferId), ARG(pos)) } - void moveBuffer(const BufferId &bufferId, int pos); - virtual inline void requestMoveBuffer(const BufferId &bufferId, int pos) { REQUEST(ARG(bufferId), ARG(pos)) } - void removeBuffer(const BufferId &bufferId); - virtual inline void requestRemoveBuffer(const BufferId &bufferId) { REQUEST(ARG(bufferId)) } - void removeBufferPermanently(const BufferId &bufferId); - virtual inline void requestRemoveBufferPermanently(const BufferId &bufferId) { REQUEST(ARG(bufferId)) } + QVariantList initTemporarilyRemovedBuffers() const; + void initSetTemporarilyRemovedBuffers(const QVariantList &buffers); + void addBuffer(const BufferId &bufferId, int pos); + virtual inline void requestAddBuffer(const BufferId &bufferId, int pos) { REQUEST(ARG(bufferId), ARG(pos)) } + void moveBuffer(const BufferId &bufferId, int pos); + virtual inline void requestMoveBuffer(const BufferId &bufferId, int pos) { REQUEST(ARG(bufferId), ARG(pos)) } + void removeBuffer(const BufferId &bufferId); + virtual inline void requestRemoveBuffer(const BufferId &bufferId) { REQUEST(ARG(bufferId)) } + void removeBufferPermanently(const BufferId &bufferId); + virtual inline void requestRemoveBufferPermanently(const BufferId &bufferId) { REQUEST(ARG(bufferId)) } signals: - void bufferViewNameSet(const QString &bufferViewName); // invalidate - void configChanged(); - void networkIdSet(const NetworkId &networkId); + void bufferViewNameSet(const QString &bufferViewName); // invalidate + void configChanged(); + void networkIdSet(const NetworkId &networkId); // void addNewBuffersAutomaticallySet(bool addNewBuffersAutomatically); // invalidate // void sortAlphabeticallySet(bool sortAlphabetically); // invalidate // // void disableDecorationSet(bool disableDecoration); // invalidate // void allowedBufferTypesSet(int allowedBufferTypes); // invalidate // void minimumActivitySet(int activity); // invalidate // void hideInactiveBuffersSet(bool hideInactiveBuffers); // invalidate - void bufferListSet(); // invalidate + void bufferListSet(); // invalidate - void bufferAdded(const BufferId &bufferId, int pos); + void bufferAdded(const BufferId &bufferId, int pos); // void addBufferRequested(const BufferId &bufferId, int pos); - void bufferMoved(const BufferId &bufferId, int pos); + void bufferMoved(const BufferId &bufferId, int pos); // void moveBufferRequested(const BufferId &bufferId, int pos); - void bufferRemoved(const BufferId &bufferId); - void bufferPermanentlyRemoved(const BufferId &bufferId); + void bufferRemoved(const BufferId &bufferId); + void bufferPermanentlyRemoved(const BufferId &bufferId); // void removeBufferRequested(const BufferId &bufferId); // void removeBufferPermanentlyRequested(const BufferId &bufferId); // void setBufferViewNameRequested(const QString &bufferViewName); private: - int _bufferViewId; - QString _bufferViewName; - NetworkId _networkId; - bool _addNewBuffersAutomatically; - bool _sortAlphabetically; - bool _hideInactiveBuffers; - bool _disableDecoration; - int _allowedBufferTypes; - int _minimumActivity; - QList _buffers; - QSet _removedBuffers; - QSet _temporarilyRemovedBuffers; + int _bufferViewId; + QString _bufferViewName; + NetworkId _networkId; + bool _addNewBuffersAutomatically; + bool _sortAlphabetically; + bool _hideInactiveBuffers; + bool _disableDecoration; + int _allowedBufferTypes; + int _minimumActivity; + QList _buffers; + QSet _removedBuffers; + QSet _temporarilyRemovedBuffers; }; + #endif // BUFFERVIEWCONFIG_H diff --git a/src/common/bufferviewmanager.cpp b/src/common/bufferviewmanager.cpp index 42cb6ad1..36018fd9 100644 --- a/src/common/bufferviewmanager.cpp +++ b/src/common/bufferviewmanager.cpp @@ -25,67 +25,81 @@ INIT_SYNCABLE_OBJECT(BufferViewManager) BufferViewManager::BufferViewManager(SignalProxy *proxy, QObject *parent) - : SyncableObject(parent), + : SyncableObject(parent), _proxy(proxy) { - _proxy->synchronize(this); + _proxy->synchronize(this); } -BufferViewConfig *BufferViewManager::bufferViewConfig(int bufferViewId) const { - if(_bufferViewConfigs.contains(bufferViewId)) - return _bufferViewConfigs[bufferViewId]; - else - return 0; + +BufferViewConfig *BufferViewManager::bufferViewConfig(int bufferViewId) const +{ + if (_bufferViewConfigs.contains(bufferViewId)) + return _bufferViewConfigs[bufferViewId]; + else + return 0; } -BufferViewConfig *BufferViewManager::bufferViewConfigFactory(int bufferViewConfigId) { - return new BufferViewConfig(bufferViewConfigId, this); + +BufferViewConfig *BufferViewManager::bufferViewConfigFactory(int bufferViewConfigId) +{ + return new BufferViewConfig(bufferViewConfigId, this); } -void BufferViewManager::addBufferViewConfig(BufferViewConfig *config) { - if(_bufferViewConfigs.contains(config->bufferViewId())) - return; - _proxy->synchronize(config); - _bufferViewConfigs[config->bufferViewId()] = config; - int bufferViewId = config->bufferViewId(); - SYNC_OTHER(addBufferViewConfig, ARG(bufferViewId)) - emit bufferViewConfigAdded(bufferViewId); +void BufferViewManager::addBufferViewConfig(BufferViewConfig *config) +{ + if (_bufferViewConfigs.contains(config->bufferViewId())) + return; + + _proxy->synchronize(config); + _bufferViewConfigs[config->bufferViewId()] = config; + int bufferViewId = config->bufferViewId(); + SYNC_OTHER(addBufferViewConfig, ARG(bufferViewId)) + emit bufferViewConfigAdded(bufferViewId); } -void BufferViewManager::addBufferViewConfig(int bufferViewConfigId) { - if(_bufferViewConfigs.contains(bufferViewConfigId)) - return; - - addBufferViewConfig(bufferViewConfigFactory(bufferViewConfigId)); + +void BufferViewManager::addBufferViewConfig(int bufferViewConfigId) +{ + if (_bufferViewConfigs.contains(bufferViewConfigId)) + return; + + addBufferViewConfig(bufferViewConfigFactory(bufferViewConfigId)); } -void BufferViewManager::deleteBufferViewConfig(int bufferViewConfigId) { - if(!_bufferViewConfigs.contains(bufferViewConfigId)) - return; - _bufferViewConfigs[bufferViewConfigId]->deleteLater(); - _bufferViewConfigs.remove(bufferViewConfigId); - SYNC(ARG(bufferViewConfigId)) - emit bufferViewConfigDeleted(bufferViewConfigId); +void BufferViewManager::deleteBufferViewConfig(int bufferViewConfigId) +{ + if (!_bufferViewConfigs.contains(bufferViewConfigId)) + return; + + _bufferViewConfigs[bufferViewConfigId]->deleteLater(); + _bufferViewConfigs.remove(bufferViewConfigId); + SYNC(ARG(bufferViewConfigId)) + emit bufferViewConfigDeleted(bufferViewConfigId); } -QVariantList BufferViewManager::initBufferViewIds() const { - QVariantList bufferViewIds; - BufferViewConfigHash::const_iterator iter = _bufferViewConfigs.constBegin(); - BufferViewConfigHash::const_iterator iterEnd = _bufferViewConfigs.constEnd(); - while(iter != iterEnd) { - bufferViewIds << (*iter)->bufferViewId(); - iter++; - } - return bufferViewIds; + +QVariantList BufferViewManager::initBufferViewIds() const +{ + QVariantList bufferViewIds; + BufferViewConfigHash::const_iterator iter = _bufferViewConfigs.constBegin(); + BufferViewConfigHash::const_iterator iterEnd = _bufferViewConfigs.constEnd(); + while (iter != iterEnd) { + bufferViewIds << (*iter)->bufferViewId(); + iter++; + } + return bufferViewIds; } -void BufferViewManager::initSetBufferViewIds(const QVariantList bufferViewIds) { - QVariantList::const_iterator iter = bufferViewIds.constBegin(); - QVariantList::const_iterator iterEnd = bufferViewIds.constEnd(); - while(iter != iterEnd) { - newBufferViewConfig((*iter).value()); - iter++; - } + +void BufferViewManager::initSetBufferViewIds(const QVariantList bufferViewIds) +{ + QVariantList::const_iterator iter = bufferViewIds.constBegin(); + QVariantList::const_iterator iterEnd = bufferViewIds.constEnd(); + while (iter != iterEnd) { + newBufferViewConfig((*iter).value()); + iter++; + } } diff --git a/src/common/bufferviewmanager.h b/src/common/bufferviewmanager.h index 23322ab8..e620ce67 100644 --- a/src/common/bufferviewmanager.h +++ b/src/common/bufferviewmanager.h @@ -29,49 +29,51 @@ class BufferViewConfig; class SignalProxy; -class BufferViewManager : public SyncableObject { - SYNCABLE_OBJECT - Q_OBJECT +class BufferViewManager : public SyncableObject +{ + SYNCABLE_OBJECT + Q_OBJECT public: - BufferViewManager(SignalProxy *proxy, QObject *parent = 0); + BufferViewManager(SignalProxy *proxy, QObject *parent = 0); - inline virtual const QMetaObject *syncMetaObject() const { return &staticMetaObject; } + inline virtual const QMetaObject *syncMetaObject() const { return &staticMetaObject; } - inline QList bufferViewConfigs() const { return _bufferViewConfigs.values(); } - BufferViewConfig *bufferViewConfig(int bufferViewId) const; + inline QList bufferViewConfigs() const { return _bufferViewConfigs.values(); } + BufferViewConfig *bufferViewConfig(int bufferViewId) const; public slots: - void addBufferViewConfig(BufferViewConfig *config); - void addBufferViewConfig(int bufferViewConfigId); - inline void newBufferViewConfig(int bufferViewConfigId) { addBufferViewConfig(bufferViewConfigId); } + void addBufferViewConfig(BufferViewConfig *config); + void addBufferViewConfig(int bufferViewConfigId); + inline void newBufferViewConfig(int bufferViewConfigId) { addBufferViewConfig(bufferViewConfigId); } - void deleteBufferViewConfig(int bufferViewConfigId); + void deleteBufferViewConfig(int bufferViewConfigId); - QVariantList initBufferViewIds() const; - void initSetBufferViewIds(const QVariantList bufferViewIds); + QVariantList initBufferViewIds() const; + void initSetBufferViewIds(const QVariantList bufferViewIds); - virtual inline void requestCreateBufferView(const QVariantMap &properties) { REQUEST(ARG(properties)) } - virtual inline void requestCreateBufferViews(const QVariantList &properties) { REQUEST(ARG(properties)) } - virtual inline void requestDeleteBufferView(int bufferViewId) { REQUEST(ARG(bufferViewId)) } - virtual inline void requestDeleteBufferViews(const QVariantList &bufferViews) { REQUEST(ARG(bufferViews)) } + virtual inline void requestCreateBufferView(const QVariantMap &properties) { REQUEST(ARG(properties)) } + virtual inline void requestCreateBufferViews(const QVariantList &properties) { REQUEST(ARG(properties)) } + virtual inline void requestDeleteBufferView(int bufferViewId) { REQUEST(ARG(bufferViewId)) } + virtual inline void requestDeleteBufferViews(const QVariantList &bufferViews) { REQUEST(ARG(bufferViews)) } signals: - void bufferViewConfigAdded(int bufferViewConfigId); - void bufferViewConfigDeleted(int bufferViewConfigId); + void bufferViewConfigAdded(int bufferViewConfigId); + void bufferViewConfigDeleted(int bufferViewConfigId); // void createBufferViewRequested(const QVariantMap &properties); // void createBufferViewsRequested(const QVariantList &properties); // void deleteBufferViewRequested(int bufferViewId); // void deleteBufferViewsRequested(const QVariantList &bufferViews); protected: - typedef QHash BufferViewConfigHash; - inline const BufferViewConfigHash &bufferViewConfigHash() { return _bufferViewConfigs; } - virtual BufferViewConfig *bufferViewConfigFactory(int bufferViewConfigId); + typedef QHash BufferViewConfigHash; + inline const BufferViewConfigHash &bufferViewConfigHash() { return _bufferViewConfigs; } + virtual BufferViewConfig *bufferViewConfigFactory(int bufferViewConfigId); private: - BufferViewConfigHash _bufferViewConfigs; - SignalProxy *_proxy; + BufferViewConfigHash _bufferViewConfigs; + SignalProxy *_proxy; }; + #endif // BUFFERVIEWMANAGER_H diff --git a/src/common/cliparser.cpp b/src/common/cliparser.cpp index 5036e165..912fb594 100644 --- a/src/common/cliparser.cpp +++ b/src/common/cliparser.cpp @@ -26,198 +26,216 @@ #include -CliParser::CliParser() : AbstractCliParser() { - +CliParser::CliParser() : AbstractCliParser() +{ } -void CliParser::addArgument(const QString &longName_, const CliParserArg &arg) { - QString longName = longName_; - longName.remove(QRegExp("\\s*<.*>\\s*")); // KCmdLineArgs takes args of the form "arg " - if(argsMap.contains(longName)) qWarning() << "Warning: Multiple definition of argument" << longName; - if(arg.shortName != 0 && !lnameOfShortArg(arg.shortName).isNull()) - qWarning().nospace() << "Warning: Redefining shortName '" << arg.shortName << "' for " << longName << " previously defined for " << lnameOfShortArg(arg.shortName); - argsMap.insert(longName, arg); + +void CliParser::addArgument(const QString &longName_, const CliParserArg &arg) +{ + QString longName = longName_; + longName.remove(QRegExp("\\s*<.*>\\s*")); // KCmdLineArgs takes args of the form "arg " + if (argsMap.contains(longName)) qWarning() << "Warning: Multiple definition of argument" << longName; + if (arg.shortName != 0 && !lnameOfShortArg(arg.shortName).isNull()) + qWarning().nospace() << "Warning: Redefining shortName '" << arg.shortName << "' for " << longName << " previously defined for " << lnameOfShortArg(arg.shortName); + argsMap.insert(longName, arg); } -bool CliParser::addLongArg(const CliParserArg::CliArgType type, const QString &name, const QString &value) { - if(argsMap.contains(name)){ - if(type == CliParserArg::CliArgOption && argsMap.value(name).type == type) { - argsMap[name].value = escapedValue(value); - return true; - } - else if (type == CliParserArg::CliArgSwitch && argsMap.value(name).type == type) { - argsMap[name].boolValue = true; - return true; + +bool CliParser::addLongArg(const CliParserArg::CliArgType type, const QString &name, const QString &value) +{ + if (argsMap.contains(name)) { + if (type == CliParserArg::CliArgOption && argsMap.value(name).type == type) { + argsMap[name].value = escapedValue(value); + return true; + } + else if (type == CliParserArg::CliArgSwitch && argsMap.value(name).type == type) { + argsMap[name].boolValue = true; + return true; + } } - } - qWarning() << "Warning: Unrecognized argument:" << name; - return false; + qWarning() << "Warning: Unrecognized argument:" << name; + return false; } -bool CliParser::addShortArg(const CliParserArg::CliArgType type, const char shortName, const QString &value) { - QString longName = lnameOfShortArg(shortName); - if(!longName.isNull()) { - if(type == CliParserArg::CliArgOption && argsMap.value(longName).type == type) { - argsMap[longName].value = escapedValue(value); - return true; - } - else if (type == CliParserArg::CliArgSwitch) { - if(argsMap.value(longName).type == type) { - argsMap[longName].boolValue = true; - return true; - } - // arg is an option but detected as a switch -> argument is missing - else { - qWarning().nospace() << "Warning: '" << shortName << "' is an option which needs an argument"; - return false; - } + +bool CliParser::addShortArg(const CliParserArg::CliArgType type, const char shortName, const QString &value) +{ + QString longName = lnameOfShortArg(shortName); + if (!longName.isNull()) { + if (type == CliParserArg::CliArgOption && argsMap.value(longName).type == type) { + argsMap[longName].value = escapedValue(value); + return true; + } + else if (type == CliParserArg::CliArgSwitch) { + if (argsMap.value(longName).type == type) { + argsMap[longName].boolValue = true; + return true; + } + // arg is an option but detected as a switch -> argument is missing + else { + qWarning().nospace() << "Warning: '" << shortName << "' is an option which needs an argument"; + return false; + } + } } - } - qWarning().nospace() << "Warning: Unrecognized argument: '" << shortName << "'"; - return false; + qWarning().nospace() << "Warning: Unrecognized argument: '" << shortName << "'"; + return false; } -QString CliParser::escapedValue(const QString &value) { - QString escapedValue = value; - if(escapedValue.startsWith("~")) - escapedValue.replace(0, 1, QDir::homePath()); - return escapedValue; +QString CliParser::escapedValue(const QString &value) +{ + QString escapedValue = value; + if (escapedValue.startsWith("~")) + escapedValue.replace(0, 1, QDir::homePath()); + + return escapedValue; } -bool CliParser::init(const QStringList &args) { - argsRaw = args; - QStringList::const_iterator currentArg; - for (currentArg = argsRaw.constBegin(); currentArg != argsRaw.constEnd(); ++currentArg) { - if(currentArg->startsWith("--")) { - // long - QString name; - if(currentArg->contains("=")) { - // option - QStringList tmp = currentArg->mid(2).split("="); - name = tmp.at(0); - QString value; - // this is needed to allow --option="" - if(tmp.at(1).isNull()) value = QString(""); - else value = tmp.at(1); - if(!addLongArg(CliParserArg::CliArgOption, name, value)) return false; - } - else { - // switch - name = currentArg->mid(2); - if(!addLongArg(CliParserArg::CliArgSwitch, name)) return false; - } - } - else if(currentArg->startsWith("-")) { - // short - char name; - QStringList::const_iterator nextArg = currentArg+1; - // if next arg is a short/long option/switch the current arg is one too - if(nextArg == argsRaw.constEnd() || nextArg->startsWith("-")) { - // switch - for (int i = 0; i < currentArg->mid(1).toAscii().size(); i++) { - name = currentArg->mid(1).toAscii().at(i); - if(!addShortArg(CliParserArg::CliArgSwitch, name)) return false; + +bool CliParser::init(const QStringList &args) +{ + argsRaw = args; + QStringList::const_iterator currentArg; + for (currentArg = argsRaw.constBegin(); currentArg != argsRaw.constEnd(); ++currentArg) { + if (currentArg->startsWith("--")) { + // long + QString name; + if (currentArg->contains("=")) { + // option + QStringList tmp = currentArg->mid(2).split("="); + name = tmp.at(0); + QString value; + // this is needed to allow --option="" + if (tmp.at(1).isNull()) value = QString(""); + else value = tmp.at(1); + if (!addLongArg(CliParserArg::CliArgOption, name, value)) return false; + } + else { + // switch + name = currentArg->mid(2); + if (!addLongArg(CliParserArg::CliArgSwitch, name)) return false; + } } - } - // if next arg is is no option/switch it's an argument to a shortoption - else { - // option - // short options are not freely mixable with other shortargs - if(currentArg->mid(1).toAscii().size() > 1) { - qWarning() << "Warning: Shortoptions may not be combined with other shortoptions or switches"; - return false; + else if (currentArg->startsWith("-")) { + // short + char name; + QStringList::const_iterator nextArg = currentArg+1; + // if next arg is a short/long option/switch the current arg is one too + if (nextArg == argsRaw.constEnd() || nextArg->startsWith("-")) { + // switch + for (int i = 0; i < currentArg->mid(1).toAscii().size(); i++) { + name = currentArg->mid(1).toAscii().at(i); + if (!addShortArg(CliParserArg::CliArgSwitch, name)) return false; + } + } + // if next arg is is no option/switch it's an argument to a shortoption + else { + // option + // short options are not freely mixable with other shortargs + if (currentArg->mid(1).toAscii().size() > 1) { + qWarning() << "Warning: Shortoptions may not be combined with other shortoptions or switches"; + return false; + } + QString value; + bool skipNext = false; + if (nextArg != argsRaw.constEnd()) { + value = nextArg->toLocal8Bit(); + skipNext = true; + } + else value = currentArg->toLocal8Bit(); + name = currentArg->mid(1).toAscii().at(0); + // we took one argument as argument to an option so skip it next time + if (skipNext) currentArg++; + if (!addShortArg(CliParserArg::CliArgOption, name, value)) return false; + } } - QString value; - bool skipNext = false; - if(nextArg != argsRaw.constEnd()) { - value = nextArg->toLocal8Bit(); - skipNext = true; + else { + // we don't support plain arguments without -/-- + if (currentArg->toLatin1() != argsRaw.at(0)) return false; } - else value = currentArg->toLocal8Bit(); - name = currentArg->mid(1).toAscii().at(0); - // we took one argument as argument to an option so skip it next time - if(skipNext) currentArg++; - if(!addShortArg(CliParserArg::CliArgOption, name, value)) return false; - } - } - else { - // we don't support plain arguments without -/-- - if(currentArg->toLatin1() != argsRaw.at(0)) return false; } - } - return true; + return true; } -void CliParser::usage() { - std::cout << "Usage: " << qPrintable(QFileInfo(argsRaw.at(0)).completeBaseName()) << " [arguments]" << std::endl; - - // get size of longName field - QStringList keys = argsMap.keys(); - uint lnameFieldSize = 0; - foreach (QString key, keys) { - uint size = 0; - if(argsMap.value(key).type == CliParserArg::CliArgOption) - size += key.size()*2; - else - size += key.size(); - // this is for " --...=[....] " - size += 8; - if(size > lnameFieldSize) lnameFieldSize = size; - } - - QMap::const_iterator arg; - for(arg = argsMap.constBegin(); arg != argsMap.constEnd(); ++arg) { - QString output; - QString lnameField; - - if(arg.value().shortName) { - output.append(" -").append(arg.value().shortName).append(","); + +void CliParser::usage() +{ + std::cout << "Usage: " << qPrintable(QFileInfo(argsRaw.at(0)).completeBaseName()) << " [arguments]" << std::endl; + + // get size of longName field + QStringList keys = argsMap.keys(); + uint lnameFieldSize = 0; + foreach(QString key, keys) { + uint size = 0; + if (argsMap.value(key).type == CliParserArg::CliArgOption) + size += key.size()*2; + else + size += key.size(); + // this is for " --...=[....] " + size += 8; + if (size > lnameFieldSize) lnameFieldSize = size; } - else output.append(" "); - lnameField.append(" --").append(arg.key()); - if(arg.value().type == CliParserArg::CliArgOption) { - lnameField.append("=[").append(arg.key().toUpper()).append("]"); + + QMap::const_iterator arg; + for (arg = argsMap.constBegin(); arg != argsMap.constEnd(); ++arg) { + QString output; + QString lnameField; + + if (arg.value().shortName) { + output.append(" -").append(arg.value().shortName).append(","); + } + else output.append(" "); + lnameField.append(" --").append(arg.key()); + if (arg.value().type == CliParserArg::CliArgOption) { + lnameField.append("=[").append(arg.key().toUpper()).append("]"); + } + output.append(lnameField.leftJustified(lnameFieldSize)); + if (!arg.value().help.isEmpty()) { + output.append(arg.value().help); + } + if (arg.value().type == CliParserArg::CliArgOption && !arg.value().def.isNull()) { + output.append(". Default is: ").append(arg.value().def); + } + std::cout << qPrintable(output) << std::endl; } - output.append(lnameField.leftJustified(lnameFieldSize)); - if(!arg.value().help.isEmpty()) { - output.append(arg.value().help); +} + + +QString CliParser::value(const QString &longName) +{ + if (argsMap.contains(longName) && argsMap.value(longName).type == CliParserArg::CliArgOption) { + if (!argsMap.value(longName).value.isNull()) + return argsMap.value(longName).value; + else + return argsMap.value(longName).def; } - if(arg.value().type == CliParserArg::CliArgOption && !arg.value().def.isNull()) { - output.append(". Default is: ").append(arg.value().def); + else { + qWarning() << "Warning: Requested value of not defined argument" << longName << "or argument is a switch"; + return QString(); } - std::cout << qPrintable(output) << std::endl; - } } -QString CliParser::value(const QString &longName) { - if(argsMap.contains(longName) && argsMap.value(longName).type == CliParserArg::CliArgOption) { - if(!argsMap.value(longName).value.isNull()) - return argsMap.value(longName).value; - else - return argsMap.value(longName).def; - } - else { - qWarning() << "Warning: Requested value of not defined argument" << longName << "or argument is a switch"; - return QString(); - } -} -bool CliParser::isSet(const QString &longName) { - if(argsMap.contains(longName)) { - if(argsMap.value(longName).type == CliParserArg::CliArgOption) return !argsMap.value(longName).value.isNull(); - else return argsMap.value(longName).boolValue; - } - else { - qWarning() << "Warning: Requested isSet of not defined argument" << longName; - return false; - } +bool CliParser::isSet(const QString &longName) +{ + if (argsMap.contains(longName)) { + if (argsMap.value(longName).type == CliParserArg::CliArgOption) return !argsMap.value(longName).value.isNull(); + else return argsMap.value(longName).boolValue; + } + else { + qWarning() << "Warning: Requested isSet of not defined argument" << longName; + return false; + } } -QString CliParser::lnameOfShortArg(const char arg) { - QMap::const_iterator cur; - for (cur = argsMap.constBegin(); cur != argsMap.constEnd(); ++cur) { - if(cur.value().shortName == arg) return cur.key(); - } - return QString(); + +QString CliParser::lnameOfShortArg(const char arg) +{ + QMap::const_iterator cur; + for (cur = argsMap.constBegin(); cur != argsMap.constEnd(); ++cur) { + if (cur.value().shortName == arg) return cur.key(); + } + return QString(); } diff --git a/src/common/cliparser.h b/src/common/cliparser.h index 761eb0d4..fe32d0dc 100644 --- a/src/common/cliparser.h +++ b/src/common/cliparser.h @@ -26,25 +26,27 @@ #include "abstractcliparser.h" //! Quassel's own parser for command line arguments -class CliParser : public AbstractCliParser { +class CliParser : public AbstractCliParser +{ public: - CliParser(); + CliParser(); - bool init(const QStringList &arguments = QStringList()); + bool init(const QStringList &arguments = QStringList()); - QString value(const QString &longName); - bool isSet(const QString &longName); - void usage(); + QString value(const QString &longName); + bool isSet(const QString &longName); + void usage(); private: - void addArgument(const QString &longName, const CliParserArg &arg); - bool addLongArg(const CliParserArg::CliArgType type, const QString &name, const QString &value = QString()); - bool addShortArg(const CliParserArg::CliArgType type, const char shortName, const QString &value = QString()); - QString escapedValue(const QString &value); - QString lnameOfShortArg(const char arg); - - QStringList argsRaw; - QMap argsMap; + void addArgument(const QString &longName, const CliParserArg &arg); + bool addLongArg(const CliParserArg::CliArgType type, const QString &name, const QString &value = QString()); + bool addShortArg(const CliParserArg::CliArgType type, const char shortName, const QString &value = QString()); + QString escapedValue(const QString &value); + QString lnameOfShortArg(const char arg); + + QStringList argsRaw; + QMap argsMap; }; + #endif diff --git a/src/common/coreinfo.h b/src/common/coreinfo.h index 68c4f7af..185e6eec 100644 --- a/src/common/coreinfo.h +++ b/src/common/coreinfo.h @@ -27,17 +27,19 @@ * gather various informations about the core. */ -class CoreInfo : public SyncableObject { - Q_OBJECT +class CoreInfo : public SyncableObject +{ + Q_OBJECT - Q_PROPERTY(QVariantMap coreData READ coreData WRITE setCoreData STORED false) + Q_PROPERTY(QVariantMap coreData READ coreData WRITE setCoreData STORED false) -public: - CoreInfo(QObject *parent = 0) : SyncableObject(parent) {} +public : + CoreInfo(QObject *parent = 0) : SyncableObject(parent) {} public slots: - virtual inline QVariantMap coreData() const { return QVariantMap(); } - virtual inline void setCoreData(const QVariantMap &) {} + virtual inline QVariantMap coreData() const { return QVariantMap(); } + virtual inline void setCoreData(const QVariantMap &) {} }; + #endif //COREINFO_H diff --git a/src/common/ctcpevent.cpp b/src/common/ctcpevent.cpp index 780cda5d..e45b585b 100644 --- a/src/common/ctcpevent.cpp +++ b/src/common/ctcpevent.cpp @@ -20,32 +20,34 @@ #include "ctcpevent.h" -Event *CtcpEvent::create(EventManager::EventType type, QVariantMap &map, Network *network) { - if(type == EventManager::CtcpEvent || type == EventManager::CtcpEventFlush) - return new CtcpEvent(type, map, network); +Event *CtcpEvent::create(EventManager::EventType type, QVariantMap &map, Network *network) +{ + if (type == EventManager::CtcpEvent || type == EventManager::CtcpEventFlush) + return new CtcpEvent(type, map, network); - return 0; + return 0; } CtcpEvent::CtcpEvent(EventManager::EventType type, QVariantMap &map, Network *network) - : IrcEvent(type, map, network) + : IrcEvent(type, map, network) { - _ctcpType = static_cast(map.take("ctcpType").toInt()); - _ctcpCmd = map.take("ctcpCmd").toString(); - _target = map.take("target").toString(); - _param = map.take("param").toString(); - _reply = map.take("repy").toString(); - _uuid = map.take("uuid").toString(); + _ctcpType = static_cast(map.take("ctcpType").toInt()); + _ctcpCmd = map.take("ctcpCmd").toString(); + _target = map.take("target").toString(); + _param = map.take("param").toString(); + _reply = map.take("repy").toString(); + _uuid = map.take("uuid").toString(); } -void CtcpEvent::toVariantMap(QVariantMap &map) const { - IrcEvent::toVariantMap(map); - map["ctcpType"] = ctcpType(); - map["ctcpCmd"] = ctcpCmd(); - map["target"] = target(); - map["param"] = param(); - map["reply"] = reply(); - map["uuid"] = uuid().toString(); +void CtcpEvent::toVariantMap(QVariantMap &map) const +{ + IrcEvent::toVariantMap(map); + map["ctcpType"] = ctcpType(); + map["ctcpCmd"] = ctcpCmd(); + map["target"] = target(); + map["param"] = param(); + map["reply"] = reply(); + map["uuid"] = uuid().toString(); } diff --git a/src/common/ctcpevent.h b/src/common/ctcpevent.h index 42d8995f..4068c1f0 100644 --- a/src/common/ctcpevent.h +++ b/src/common/ctcpevent.h @@ -25,67 +25,71 @@ #include -class CtcpEvent : public IrcEvent { - +class CtcpEvent : public IrcEvent +{ public: - enum CtcpType { - Query, - Reply - }; + enum CtcpType { + Query, + Reply + }; + + explicit CtcpEvent(EventManager::EventType type, Network *network, const QString &prefix, const QString &target, + CtcpType ctcpType, const QString &ctcpCmd, const QString ¶m, + const QDateTime ×tamp = QDateTime(), const QUuid &uuid = QUuid()) + : IrcEvent(type, network, prefix), + _ctcpType(ctcpType), + _ctcpCmd(ctcpCmd), + _target(target), + _param(param), + _uuid(uuid) + { + setTimestamp(timestamp); + } - explicit CtcpEvent(EventManager::EventType type, Network *network, const QString &prefix, const QString &target, - CtcpType ctcpType, const QString &ctcpCmd, const QString ¶m, - const QDateTime ×tamp = QDateTime(), const QUuid &uuid = QUuid()) - : IrcEvent(type, network, prefix), - _ctcpType(ctcpType), - _ctcpCmd(ctcpCmd), - _target(target), - _param(param), - _uuid(uuid) - { - setTimestamp(timestamp); - } - inline CtcpType ctcpType() const { return _ctcpType; } - inline void setCtcpType(CtcpType type) { _ctcpType = type; } + inline CtcpType ctcpType() const { return _ctcpType; } + inline void setCtcpType(CtcpType type) { _ctcpType = type; } - inline QString ctcpCmd() const { return _ctcpCmd; } - inline void setCtcpCmd(const QString &ctcpCmd) { _ctcpCmd = ctcpCmd; } + inline QString ctcpCmd() const { return _ctcpCmd; } + inline void setCtcpCmd(const QString &ctcpCmd) { _ctcpCmd = ctcpCmd; } - inline QString target() const { return _target; } - inline void setTarget(const QString &target) { _target = target; } + inline QString target() const { return _target; } + inline void setTarget(const QString &target) { _target = target; } - inline QString param() const { return _param; } - inline void setParam(const QString ¶m) { _param = param; } + inline QString param() const { return _param; } + inline void setParam(const QString ¶m) { _param = param; } - inline QString reply() const { return _reply; } - inline void setReply(const QString &reply) { _reply = reply; } + inline QString reply() const { return _reply; } + inline void setReply(const QString &reply) { _reply = reply; } - inline QUuid uuid() const { return _uuid; } - inline void setUuid(const QUuid &uuid) { _uuid = uuid; } + inline QUuid uuid() const { return _uuid; } + inline void setUuid(const QUuid &uuid) { _uuid = uuid; } - static Event *create(EventManager::EventType type, QVariantMap &map, Network *network); + static Event *create(EventManager::EventType type, QVariantMap &map, Network *network); protected: - explicit CtcpEvent(EventManager::EventType type, QVariantMap &map, Network *network); - void toVariantMap(QVariantMap &map) const; - - virtual inline QString className() const { return "CtcpEvent"; } - virtual inline void debugInfo(QDebug &dbg) const { - NetworkEvent::debugInfo(dbg); - dbg << ", prefix = " << qPrintable(prefix()) - << ", target = " << qPrintable(target()) - << ", ctcptype = " << (ctcpType() == Query? "query" : "reply") - << ", cmd = " << qPrintable(ctcpCmd()) - << ", param = " << qPrintable(param()) - << ", reply = " << qPrintable(reply()); - } + explicit CtcpEvent(EventManager::EventType type, QVariantMap &map, Network *network); + void toVariantMap(QVariantMap &map) const; + + virtual inline QString className() const { return "CtcpEvent"; } + virtual inline void debugInfo(QDebug &dbg) const + { + NetworkEvent::debugInfo(dbg); + dbg << ", prefix = " << qPrintable(prefix()) + << ", target = " << qPrintable(target()) + << ", ctcptype = " << (ctcpType() == Query ? "query" : "reply") + << ", cmd = " << qPrintable(ctcpCmd()) + << ", param = " << qPrintable(param()) + << ", reply = " << qPrintable(reply()); + } + private: - CtcpType _ctcpType; - QString _ctcpCmd; - QString _target, _param, _reply; - QUuid _uuid; + CtcpType _ctcpType; + QString _ctcpCmd; + QString _target, _param, _reply; + QUuid _uuid; }; + #endif diff --git a/src/common/event.cpp b/src/common/event.cpp index 19b56a7d..dbd46ccb 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -24,100 +24,102 @@ #include "messageevent.h" Event::Event(EventManager::EventType type) - : _type(type) - , _valid(true) + : _type(type) + , _valid(true) { - } Event::Event(EventManager::EventType type, QVariantMap &map) - : _type(type) - , _valid(true) + : _type(type) + , _valid(true) { - if(!map.contains("flags") || !map.contains("timestamp")) { - qWarning() << "Received invalid serialized event:" << map; - setValid(false); - return; - } - - setFlags(static_cast(map.take("flags").toInt())); // TODO sanity check? - setTimestamp(QDateTime::fromTime_t(map.take("timestamp").toUInt())); + if (!map.contains("flags") || !map.contains("timestamp")) { + qWarning() << "Received invalid serialized event:" << map; + setValid(false); + return; + } + + setFlags(static_cast(map.take("flags").toInt())); // TODO sanity check? + setTimestamp(QDateTime::fromTime_t(map.take("timestamp").toUInt())); } -void Event::toVariantMap(QVariantMap &map) const { - map["type"] = static_cast(type()); - map["flags"] = static_cast(flags()); - map["timestamp"] = timestamp().toTime_t(); +void Event::toVariantMap(QVariantMap &map) const +{ + map["type"] = static_cast(type()); + map["flags"] = static_cast(flags()); + map["timestamp"] = timestamp().toTime_t(); } -QVariantMap Event::toVariantMap() const { - QVariantMap map; - toVariantMap(map); - return map; +QVariantMap Event::toVariantMap() const +{ + QVariantMap map; + toVariantMap(map); + return map; } -Event *Event::fromVariantMap(QVariantMap &map, Network *network) { - int inttype = map.take("type").toInt(); - // sanity check if we have a valid enum value - if(EventManager::enumName(inttype).isEmpty()) { - qWarning() << "Received a serialized event with unknown type" << inttype; - return 0; - } - - EventManager::EventType type = static_cast(inttype); - if(type == EventManager::Invalid || type == EventManager::GenericEvent) - return 0; - - EventManager::EventType group = static_cast(type & EventManager::EventGroupMask); - - Event *e = 0; - - // we use static create() functions to keep group-specific special cases in the files they belong - // e.g. IrcEventRawMessage - switch(group) { - case EventManager::NetworkEvent: - e = NetworkEvent::create(type, map, network); - break; - case EventManager::IrcServerEvent: - // not in use! - break; - case EventManager::IrcEvent: - e = IrcEvent::create(type, map, network); - break; - case EventManager::MessageEvent: - e = MessageEvent::create(type, map, network); - break; - case EventManager::CtcpEvent: - e = CtcpEvent::create(type, map, network); - break; - default: - break; - } - - if(!e) { - qWarning() << "Can't create event of type" << type; - return 0; - } - - if(!map.isEmpty()) { - qWarning() << "Event creation from map did not consume all data:" << map; - } - - return e; +Event *Event::fromVariantMap(QVariantMap &map, Network *network) +{ + int inttype = map.take("type").toInt(); + // sanity check if we have a valid enum value + if (EventManager::enumName(inttype).isEmpty()) { + qWarning() << "Received a serialized event with unknown type" << inttype; + return 0; + } + + EventManager::EventType type = static_cast(inttype); + if (type == EventManager::Invalid || type == EventManager::GenericEvent) + return 0; + + EventManager::EventType group = static_cast(type & EventManager::EventGroupMask); + + Event *e = 0; + + // we use static create() functions to keep group-specific special cases in the files they belong + // e.g. IrcEventRawMessage + switch (group) { + case EventManager::NetworkEvent: + e = NetworkEvent::create(type, map, network); + break; + case EventManager::IrcServerEvent: + // not in use! + break; + case EventManager::IrcEvent: + e = IrcEvent::create(type, map, network); + break; + case EventManager::MessageEvent: + e = MessageEvent::create(type, map, network); + break; + case EventManager::CtcpEvent: + e = CtcpEvent::create(type, map, network); + break; + default: + break; + } + + if (!e) { + qWarning() << "Can't create event of type" << type; + return 0; + } + + if (!map.isEmpty()) { + qWarning() << "Event creation from map did not consume all data:" << map; + } + + return e; } -QDebug operator<<(QDebug dbg, Event *e) { - dbg.nospace() << qPrintable(e->className()) << "(" - << "type = 0x" << qPrintable(QString::number(e->type(), 16)); - e->debugInfo(dbg); - //<< ", data = " << e->data(); // we don't use data anywhere yet - dbg.nospace() << ", flags = 0x" << qPrintable(QString::number(e->flags(), 16)) - << ")"; - return dbg.space(); +QDebug operator<<(QDebug dbg, Event *e) +{ + dbg.nospace() << qPrintable(e->className()) << "(" + << "type = 0x" << qPrintable(QString::number(e->type(), 16)); + e->debugInfo(dbg); + //<< ", data = " << e->data(); // we don't use data anywhere yet + dbg.nospace() << ", flags = 0x" << qPrintable(QString::number(e->flags(), 16)) + << ")"; + return dbg.space(); } - diff --git a/src/common/event.h b/src/common/event.h index e0fb8e39..91944aec 100644 --- a/src/common/event.h +++ b/src/common/event.h @@ -28,55 +28,56 @@ class Network; -class Event { - +class Event +{ public: - explicit Event(EventManager::EventType type = EventManager::Invalid); - virtual ~Event() {} + explicit Event(EventManager::EventType type = EventManager::Invalid); + virtual ~Event() {} - inline EventManager::EventType type() const { return _type; } + inline EventManager::EventType type() const { return _type; } - inline void setFlag(EventManager::EventFlag flag) { _flags |= flag; } - inline void setFlags(EventManager::EventFlags flags) { _flags = flags; } - inline bool testFlag(EventManager::EventFlag flag) { return _flags.testFlag(flag); } - inline EventManager::EventFlags flags() const { return _flags; } + inline void setFlag(EventManager::EventFlag flag) { _flags |= flag; } + inline void setFlags(EventManager::EventFlags flags) { _flags = flags; } + inline bool testFlag(EventManager::EventFlag flag) { return _flags.testFlag(flag); } + inline EventManager::EventFlags flags() const { return _flags; } - inline bool isValid() const { return _valid; } - inline void stop() { setFlag(EventManager::Stopped); } - inline bool isStopped() { return _flags.testFlag(EventManager::Stopped); } + inline bool isValid() const { return _valid; } + inline void stop() { setFlag(EventManager::Stopped); } + inline bool isStopped() { return _flags.testFlag(EventManager::Stopped); } - inline void setTimestamp(const QDateTime &time) { _timestamp = time; } - inline QDateTime timestamp() const { return _timestamp; } + inline void setTimestamp(const QDateTime &time) { _timestamp = time; } + inline QDateTime timestamp() const { return _timestamp; } - //inline void setData(const QVariant &data) { _data = data; } - //inline QVariant data() const { return _data; } + //inline void setData(const QVariant &data) { _data = data; } + //inline QVariant data() const { return _data; } - // call EventManager::createEvent(map) instead! - static Event *fromVariantMap(QVariantMap &map, Network *network); - QVariantMap toVariantMap() const; + // call EventManager::createEvent(map) instead! + static Event *fromVariantMap(QVariantMap &map, Network *network); + QVariantMap toVariantMap() const; protected: - virtual inline QString className() const { return "Event"; } - virtual inline void debugInfo(QDebug &dbg) const { Q_UNUSED(dbg); } + virtual inline QString className() const { return "Event"; } + virtual inline void debugInfo(QDebug &dbg) const { Q_UNUSED(dbg); } - explicit Event(EventManager::EventType type, QVariantMap &map); + explicit Event(EventManager::EventType type, QVariantMap &map); - // must only use primitive types: string, int, double, list, hash - // we want to convert this to JSON in the future! - virtual void toVariantMap(QVariantMap &map) const; + // must only use primitive types: string, int, double, list, hash + // we want to convert this to JSON in the future! + virtual void toVariantMap(QVariantMap &map) const; - inline void setValid(bool valid) { _valid = valid; } + inline void setValid(bool valid) { _valid = valid; } private: - EventManager::EventType _type; - EventManager::EventFlags _flags; - QDateTime _timestamp; - //QVariant _data; - bool _valid; + EventManager::EventType _type; + EventManager::EventFlags _flags; + QDateTime _timestamp; + //QVariant _data; + bool _valid; - friend QDebug operator<<(QDebug dbg, Event *e); + friend QDebug operator<<(QDebug dbg, Event *e); }; + QDebug operator<<(QDebug dbg, Event *e); /*******/ diff --git a/src/common/eventmanager.cpp b/src/common/eventmanager.cpp index 03c04df3..3adbadcc 100644 --- a/src/common/eventmanager.cpp +++ b/src/common/eventmanager.cpp @@ -30,55 +30,71 @@ // ============================================================ // QueuedEvent // ============================================================ -class QueuedQuasselEvent : public QEvent { +class QueuedQuasselEvent : public QEvent +{ public: - QueuedQuasselEvent(Event *event) - : QEvent(QEvent::User), event(event) {} - Event *event; + QueuedQuasselEvent(Event *event) + : QEvent(QEvent::User), event(event) {} + Event *event; }; + // ============================================================ // EventManager // ============================================================ EventManager::EventManager(QObject *parent) - : QObject(parent) { + : QObject(parent) +{ } -QMetaEnum EventManager::eventEnum() { - if(!_enum.isValid()) { - int eventEnumIndex = staticMetaObject.indexOfEnumerator("EventType"); - Q_ASSERT(eventEnumIndex >= 0); - _enum = staticMetaObject.enumerator(eventEnumIndex); - Q_ASSERT(_enum.isValid()); - } - return _enum; + +QMetaEnum EventManager::eventEnum() +{ + if (!_enum.isValid()) { + int eventEnumIndex = staticMetaObject.indexOfEnumerator("EventType"); + Q_ASSERT(eventEnumIndex >= 0); + _enum = staticMetaObject.enumerator(eventEnumIndex); + Q_ASSERT(_enum.isValid()); + } + return _enum; } -EventManager::EventType EventManager::eventTypeByName(const QString &name) { - int val = eventEnum().keyToValue(name.toLatin1()); - return (val == -1) ? Invalid : static_cast(val); + +EventManager::EventType EventManager::eventTypeByName(const QString &name) +{ + int val = eventEnum().keyToValue(name.toLatin1()); + return (val == -1) ? Invalid : static_cast(val); } -EventManager::EventType EventManager::eventGroupByName(const QString &name) { - EventType type = eventTypeByName(name); - return type == Invalid? Invalid : static_cast(type & EventGroupMask); + +EventManager::EventType EventManager::eventGroupByName(const QString &name) +{ + EventType type = eventTypeByName(name); + return type == Invalid ? Invalid : static_cast(type & EventGroupMask); } -QString EventManager::enumName(EventType type) { - return eventEnum().valueToKey(type); + +QString EventManager::enumName(EventType type) +{ + return eventEnum().valueToKey(type); } -QString EventManager::enumName(int type) { - return eventEnum().valueToKey(type); + +QString EventManager::enumName(int type) +{ + return eventEnum().valueToKey(type); } -Event *EventManager::createEvent(const QVariantMap &map) { - QVariantMap m = map; - Network *net = networkById(m.take("network").toInt()); - return Event::fromVariantMap(m, net); +Event *EventManager::createEvent(const QVariantMap &map) +{ + QVariantMap m = map; + + Network *net = networkById(m.take("network").toInt()); + return Event::fromVariantMap(m, net); } + /* NOTE: Registering and calling handlers works fine even if they specify a subclass of Event as their parameter. However, this most probably is a result from a reinterpret_cast somewhere deep inside Qt, so there is *no* @@ -93,218 +109,244 @@ Event *EventManager::createEvent(const QVariantMap &map) { with the actual class. Possibly (optionally) using rtti... */ -int EventManager::findEventType(const QString &methodSignature_, const QString &methodPrefix) const { - if(!methodSignature_.startsWith(methodPrefix)) - return -1; +int EventManager::findEventType(const QString &methodSignature_, const QString &methodPrefix) const +{ + if (!methodSignature_.startsWith(methodPrefix)) + return -1; - QString methodSignature = methodSignature_; + QString methodSignature = methodSignature_; - methodSignature = methodSignature.section('(',0,0); // chop the attribute list - methodSignature = methodSignature.mid(methodPrefix.length()); // strip prefix + methodSignature = methodSignature.section('(', 0, 0); // chop the attribute list + methodSignature = methodSignature.mid(methodPrefix.length()); // strip prefix - int eventType = -1; + int eventType = -1; - // special handling for numeric IrcEvents: IrcEvent042 gets mapped to IrcEventNumeric + 42 - if(methodSignature.length() == 8+3 && methodSignature.startsWith("IrcEvent")) { - int num = methodSignature.right(3).toUInt(); - if(num > 0) { - QString numericSig = methodSignature.left(methodSignature.length() - 3) + "Numeric"; - eventType = eventEnum().keyToValue(numericSig.toAscii()); - if(eventType < 0) { - qWarning() << Q_FUNC_INFO << "Could not find EventType" << numericSig << "for handling" << methodSignature; + // special handling for numeric IrcEvents: IrcEvent042 gets mapped to IrcEventNumeric + 42 + if (methodSignature.length() == 8+3 && methodSignature.startsWith("IrcEvent")) { + int num = methodSignature.right(3).toUInt(); + if (num > 0) { + QString numericSig = methodSignature.left(methodSignature.length() - 3) + "Numeric"; + eventType = eventEnum().keyToValue(numericSig.toAscii()); + if (eventType < 0) { + qWarning() << Q_FUNC_INFO << "Could not find EventType" << numericSig << "for handling" << methodSignature; + return -1; + } + eventType += num; + } + } + + if (eventType < 0) + eventType = eventEnum().keyToValue(methodSignature.toAscii()); + if (eventType < 0) { + qWarning() << Q_FUNC_INFO << "Could not find EventType" << methodSignature; return -1; - } - eventType += num; } - } - - if(eventType < 0) - eventType = eventEnum().keyToValue(methodSignature.toAscii()); - if(eventType < 0) { - qWarning() << Q_FUNC_INFO << "Could not find EventType" << methodSignature; - return -1; - } - return eventType; + return eventType; } -void EventManager::registerObject(QObject *object, Priority priority, const QString &methodPrefix, const QString &filterPrefix) { - for(int i = object->metaObject()->methodOffset(); i < object->metaObject()->methodCount(); i++) { - QString methodSignature(object->metaObject()->method(i).signature()); - int eventType = findEventType(methodSignature, methodPrefix); - if(eventType > 0) { - Handler handler(object, i, priority); - registeredHandlers()[eventType].append(handler); - //qDebug() << "Registered event handler for" << methodSignature << "in" << object; - } - eventType = findEventType(methodSignature, filterPrefix); - if(eventType > 0) { - Handler handler(object, i, priority); - registeredFilters()[eventType].append(handler); - //qDebug() << "Registered event filterer for" << methodSignature << "in" << object; +void EventManager::registerObject(QObject *object, Priority priority, const QString &methodPrefix, const QString &filterPrefix) +{ + for (int i = object->metaObject()->methodOffset(); i < object->metaObject()->methodCount(); i++) { + QString methodSignature(object->metaObject()->method(i).signature()); + + int eventType = findEventType(methodSignature, methodPrefix); + if (eventType > 0) { + Handler handler(object, i, priority); + registeredHandlers()[eventType].append(handler); + //qDebug() << "Registered event handler for" << methodSignature << "in" << object; + } + eventType = findEventType(methodSignature, filterPrefix); + if (eventType > 0) { + Handler handler(object, i, priority); + registeredFilters()[eventType].append(handler); + //qDebug() << "Registered event filterer for" << methodSignature << "in" << object; + } } - } } -void EventManager::registerEventFilter(EventType event, QObject *object, const char *slot) { - registerEventHandler(QList() << event, object, slot, NormalPriority, true); + +void EventManager::registerEventFilter(EventType event, QObject *object, const char *slot) +{ + registerEventHandler(QList() << event, object, slot, NormalPriority, true); } -void EventManager::registerEventFilter(QList events, QObject *object, const char *slot) { - registerEventHandler(events, object, slot, NormalPriority, true); + +void EventManager::registerEventFilter(QList events, QObject *object, const char *slot) +{ + registerEventHandler(events, object, slot, NormalPriority, true); } -void EventManager::registerEventHandler(EventType event, QObject *object, const char *slot, Priority priority, bool isFilter) { - registerEventHandler(QList() << event, object, slot, priority, isFilter); + +void EventManager::registerEventHandler(EventType event, QObject *object, const char *slot, Priority priority, bool isFilter) +{ + registerEventHandler(QList() << event, object, slot, priority, isFilter); } -void EventManager::registerEventHandler(QList events, QObject *object, const char *slot, Priority priority, bool isFilter) { - int methodIndex = object->metaObject()->indexOfMethod(slot); - if(methodIndex < 0) { - qWarning() << Q_FUNC_INFO << QString("Slot %1 not found in object %2").arg(slot).arg(object->objectName()); - return; - } - Handler handler(object, methodIndex, priority); - foreach(EventType event, events) { - if(isFilter) { - registeredFilters()[event].append(handler); - qDebug() << "Registered event filter for" << event << "in" << object; - } else { - registeredHandlers()[event].append(handler); - qDebug() << "Registered event handler for" << event << "in" << object; + +void EventManager::registerEventHandler(QList events, QObject *object, const char *slot, Priority priority, bool isFilter) +{ + int methodIndex = object->metaObject()->indexOfMethod(slot); + if (methodIndex < 0) { + qWarning() << Q_FUNC_INFO << QString("Slot %1 not found in object %2").arg(slot).arg(object->objectName()); + return; + } + Handler handler(object, methodIndex, priority); + foreach(EventType event, events) { + if (isFilter) { + registeredFilters()[event].append(handler); + qDebug() << "Registered event filter for" << event << "in" << object; + } + else { + registeredHandlers()[event].append(handler); + qDebug() << "Registered event handler for" << event << "in" << object; + } } - } } -void EventManager::postEvent(Event *event) { - if(sender() && sender()->thread() != this->thread()) { - QueuedQuasselEvent *queuedEvent = new QueuedQuasselEvent(event); - QCoreApplication::postEvent(this, queuedEvent); - } else { - if(_eventQueue.isEmpty()) - // we're currently not processing events - processEvent(event); - else - _eventQueue.append(event); - } -} -void EventManager::customEvent(QEvent *event) { - if(event->type() == QEvent::User) { - QueuedQuasselEvent *queuedEvent = static_cast(event); - processEvent(queuedEvent->event); - event->accept(); - } +void EventManager::postEvent(Event *event) +{ + if (sender() && sender()->thread() != this->thread()) { + QueuedQuasselEvent *queuedEvent = new QueuedQuasselEvent(event); + QCoreApplication::postEvent(this, queuedEvent); + } + else { + if (_eventQueue.isEmpty()) + // we're currently not processing events + processEvent(event); + else + _eventQueue.append(event); + } } -void EventManager::processEvent(Event *event) { - Q_ASSERT(_eventQueue.isEmpty()); - dispatchEvent(event); - // dispatching the event might cause new events to be generated. we process those afterwards. - while(!_eventQueue.isEmpty()) { - dispatchEvent(_eventQueue.first()); - _eventQueue.removeFirst(); - } -} -void EventManager::dispatchEvent(Event *event) { - //qDebug() << "Dispatching" << event; +void EventManager::customEvent(QEvent *event) +{ + if (event->type() == QEvent::User) { + QueuedQuasselEvent *queuedEvent = static_cast(event); + processEvent(queuedEvent->event); + event->accept(); + } +} - // we try handlers from specialized to generic by masking the enum - // build a list sorted by priorities that contains all eligible handlers - QList handlers; - QHash filters; - QSet ignored; - uint type = event->type(); +void EventManager::processEvent(Event *event) +{ + Q_ASSERT(_eventQueue.isEmpty()); + dispatchEvent(event); + // dispatching the event might cause new events to be generated. we process those afterwards. + while (!_eventQueue.isEmpty()) { + dispatchEvent(_eventQueue.first()); + _eventQueue.removeFirst(); + } +} - bool checkDupes = false; - // special handling for numeric IrcEvents - if((type & ~IrcEventNumericMask) == IrcEventNumeric) { - ::IrcEventNumeric *numEvent = static_cast< ::IrcEventNumeric *>(event); - if(!numEvent) - qWarning() << "Invalid event type for IrcEventNumeric!"; - else { - int num = numEvent->number(); - if(num > 0) { - insertHandlers(registeredHandlers().value(type + num), handlers, false); - insertFilters(registeredFilters().value(type + num), filters); - checkDupes = true; - } +void EventManager::dispatchEvent(Event *event) +{ + //qDebug() << "Dispatching" << event; + + // we try handlers from specialized to generic by masking the enum + + // build a list sorted by priorities that contains all eligible handlers + QList handlers; + QHash filters; + QSet ignored; + uint type = event->type(); + + bool checkDupes = false; + + // special handling for numeric IrcEvents + if ((type & ~IrcEventNumericMask) == IrcEventNumeric) { + ::IrcEventNumeric *numEvent = static_cast< ::IrcEventNumeric *>(event); + if (!numEvent) + qWarning() << "Invalid event type for IrcEventNumeric!"; + else { + int num = numEvent->number(); + if (num > 0) { + insertHandlers(registeredHandlers().value(type + num), handlers, false); + insertFilters(registeredFilters().value(type + num), filters); + checkDupes = true; + } + } } - } - - // exact type - insertHandlers(registeredHandlers().value(type), handlers, checkDupes); - insertFilters(registeredFilters().value(type), filters); - - // check if we have a generic handler for the event group - if((type & EventGroupMask) != type) { - insertHandlers(registeredHandlers().value(type & EventGroupMask), handlers, true); - insertFilters(registeredFilters().value(type & EventGroupMask), filters); - } - - // now dispatch the event - QList::const_iterator it; - for(it = handlers.begin(); it != handlers.end() && !event->isStopped(); ++it) { - QObject *obj = it->object; - - if(ignored.contains(obj)) // object has filtered the event - continue; - - if(filters.contains(obj)) { // we have a filter, so let's check if we want to deliver the event - Handler filter = filters.value(obj); - bool result = false; - void *param[] = {Q_RETURN_ARG(bool, result).data(), Q_ARG(Event *, event).data() }; - obj->qt_metacall(QMetaObject::InvokeMetaMethod, filter.methodIndex, param); - if(!result) { - ignored.insert(obj); - continue; // mmmh, event filter told us to not accept - } + + // exact type + insertHandlers(registeredHandlers().value(type), handlers, checkDupes); + insertFilters(registeredFilters().value(type), filters); + + // check if we have a generic handler for the event group + if ((type & EventGroupMask) != type) { + insertHandlers(registeredHandlers().value(type & EventGroupMask), handlers, true); + insertFilters(registeredFilters().value(type & EventGroupMask), filters); } - // finally, deliverance! - void *param[] = {0, Q_ARG(Event *, event).data() }; - obj->qt_metacall(QMetaObject::InvokeMetaMethod, it->methodIndex, param); - } + // now dispatch the event + QList::const_iterator it; + for (it = handlers.begin(); it != handlers.end() && !event->isStopped(); ++it) { + QObject *obj = it->object; + + if (ignored.contains(obj)) // object has filtered the event + continue; + + if (filters.contains(obj)) { // we have a filter, so let's check if we want to deliver the event + Handler filter = filters.value(obj); + bool result = false; + void *param[] = { Q_RETURN_ARG(bool, result).data(), Q_ARG(Event *, event).data() }; + obj->qt_metacall(QMetaObject::InvokeMetaMethod, filter.methodIndex, param); + if (!result) { + ignored.insert(obj); + continue; // mmmh, event filter told us to not accept + } + } + + // finally, deliverance! + void *param[] = { 0, Q_ARG(Event *, event).data() }; + obj->qt_metacall(QMetaObject::InvokeMetaMethod, it->methodIndex, param); + } - // that's it - delete event; + // that's it + delete event; } -void EventManager::insertHandlers(const QList &newHandlers, QList &existing, bool checkDupes) { - foreach(const Handler &handler, newHandlers) { - if(existing.isEmpty()) - existing.append(handler); - else { - // need to insert it at the proper position, but only if we don't yet have a handler for this event and object! - bool insert = true; - QList::iterator insertpos = existing.end(); - QList::iterator it = existing.begin(); - while(it != existing.end()) { - if(checkDupes && handler.object == it->object) { - insert = false; - break; - } - if(insertpos == existing.end() && handler.priority > it->priority) - insertpos = it; - ++it; - } - if(insert) - existing.insert(it, handler); +void EventManager::insertHandlers(const QList &newHandlers, QList &existing, bool checkDupes) +{ + foreach(const Handler &handler, newHandlers) { + if (existing.isEmpty()) + existing.append(handler); + else { + // need to insert it at the proper position, but only if we don't yet have a handler for this event and object! + bool insert = true; + QList::iterator insertpos = existing.end(); + QList::iterator it = existing.begin(); + while (it != existing.end()) { + if (checkDupes && handler.object == it->object) { + insert = false; + break; + } + if (insertpos == existing.end() && handler.priority > it->priority) + insertpos = it; + + ++it; + } + if (insert) + existing.insert(it, handler); + } } - } } + // priority is ignored, and only the first (should be most specialized) filter is being used // fun things could happen if you used the registerEventFilter() methods in the wrong order though -void EventManager::insertFilters(const QList &newFilters, QHash &existing) { - foreach(const Handler &filter, newFilters) { - if(!existing.contains(filter.object)) - existing[filter.object] = filter; - } +void EventManager::insertFilters(const QList &newFilters, QHash &existing) +{ + foreach(const Handler &filter, newFilters) { + if (!existing.contains(filter.object)) + existing[filter.object] = filter; + } } + QMetaEnum EventManager::_enum; diff --git a/src/common/eventmanager.h b/src/common/eventmanager.h index eb319212..b899be5b 100644 --- a/src/common/eventmanager.h +++ b/src/common/eventmanager.h @@ -28,163 +28,166 @@ class Event; class Network; -class EventManager : public QObject { - Q_OBJECT - Q_FLAGS(EventFlag EventFlags) - Q_ENUMS(EventType) - -public: - - enum RegistrationMode { - Prepend, - Append - }; - - enum Priority { - VeryLowPriority, - LowPriority, - NormalPriority, - HighPriority, - HighestPriority - }; - - enum EventFlag { - Self = 0x01, ///< Self-generated (user input) event - Fake = 0x08, ///< Ignore this in CoreSessionEventProcessor - Netsplit = 0x10, ///< Netsplit join/part, ignore on display - Backlog = 0x20, - Silent = 0x40, ///< Don't generate a MessageEvent - Stopped = 0x80 - }; - Q_DECLARE_FLAGS(EventFlags, EventFlag) - - /* - - */ - /* These values make sense! Don't change without knowing what you do! */ - enum EventType { - Invalid = 0xffffffff, - GenericEvent = 0x00000000, - - // for event group handlers (handleIrcEvent() will handle all IrcEvent* enums) - // event groups are specified by bits 20-24 - EventGroupMask = 0x00ff0000, - - NetworkEvent = 0x00010000, - NetworkConnecting, - NetworkInitializing, - NetworkInitialized, - NetworkReconnecting, - NetworkDisconnecting, - NetworkDisconnected, - NetworkSplitJoin, - NetworkSplitQuit, - NetworkIncoming, - - IrcServerEvent = 0x00020000, - IrcServerIncoming, - IrcServerParseError, - - IrcEvent = 0x00030000, - IrcEventAuthenticate, - IrcEventCap, - IrcEventInvite, - IrcEventJoin, - IrcEventKick, - IrcEventMode, - IrcEventNick, - IrcEventNotice, - IrcEventPart, - IrcEventPing, - IrcEventPong, - IrcEventPrivmsg, - IrcEventQuit, - IrcEventTopic, - IrcEventRawPrivmsg, ///< Undecoded privmsg (still needs CTCP parsing) - IrcEventRawNotice, ///< Undecoded notice (still needs CTCP parsing) - IrcEventUnknown, ///< Unknown non-numeric cmd - - IrcEventNumeric = 0x00031000, /* needs 1000 (0x03e8) consecutive free values! */ - IrcEventNumericMask = 0x00000fff, /* for checking if an event is numeric */ - - MessageEvent = 0x00040000, ///< Stringified event suitable for converting to Message - - CtcpEvent = 0x00050000, - CtcpEventFlush - }; - - EventManager(QObject *parent = 0); - - static EventType eventTypeByName(const QString &name); - static EventType eventGroupByName(const QString &name); - static QString enumName(EventType type); - static QString enumName(int type); // for sanity tests - - Event *createEvent(const QVariantMap &map); +class EventManager : public QObject +{ + Q_OBJECT + Q_FLAGS(EventFlag EventFlags) + Q_ENUMS(EventType) + +public : + + enum RegistrationMode { + Prepend, + Append + }; + + enum Priority { + VeryLowPriority, + LowPriority, + NormalPriority, + HighPriority, + HighestPriority + }; + + enum EventFlag { + Self = 0x01, ///< Self-generated (user input) event + Fake = 0x08, ///< Ignore this in CoreSessionEventProcessor + Netsplit = 0x10, ///< Netsplit join/part, ignore on display + Backlog = 0x20, + Silent = 0x40, ///< Don't generate a MessageEvent + Stopped = 0x80 + }; + Q_DECLARE_FLAGS(EventFlags, EventFlag) + + /* + + */ + /* These values make sense! Don't change without knowing what you do! */ + enum EventType { + Invalid = 0xffffffff, + GenericEvent = 0x00000000, + + // for event group handlers (handleIrcEvent() will handle all IrcEvent* enums) + // event groups are specified by bits 20-24 + EventGroupMask = 0x00ff0000, + + NetworkEvent = 0x00010000, + NetworkConnecting, + NetworkInitializing, + NetworkInitialized, + NetworkReconnecting, + NetworkDisconnecting, + NetworkDisconnected, + NetworkSplitJoin, + NetworkSplitQuit, + NetworkIncoming, + + IrcServerEvent = 0x00020000, + IrcServerIncoming, + IrcServerParseError, + + IrcEvent = 0x00030000, + IrcEventAuthenticate, + IrcEventCap, + IrcEventInvite, + IrcEventJoin, + IrcEventKick, + IrcEventMode, + IrcEventNick, + IrcEventNotice, + IrcEventPart, + IrcEventPing, + IrcEventPong, + IrcEventPrivmsg, + IrcEventQuit, + IrcEventTopic, + IrcEventRawPrivmsg, ///< Undecoded privmsg (still needs CTCP parsing) + IrcEventRawNotice, ///< Undecoded notice (still needs CTCP parsing) + IrcEventUnknown, ///< Unknown non-numeric cmd + + IrcEventNumeric = 0x00031000, /* needs 1000 (0x03e8) consecutive free values! */ + IrcEventNumericMask = 0x00000fff, /* for checking if an event is numeric */ + + MessageEvent = 0x00040000, ///< Stringified event suitable for converting to Message + + CtcpEvent = 0x00050000, + CtcpEventFlush + }; + + EventManager(QObject *parent = 0); + + static EventType eventTypeByName(const QString &name); + static EventType eventGroupByName(const QString &name); + static QString enumName(EventType type); + static QString enumName(int type); // for sanity tests + + Event *createEvent(const QVariantMap &map); public slots: - void registerObject(QObject *object, Priority priority = NormalPriority, - const QString &methodPrefix = "process", - const QString &filterPrefix = "filter"); - void registerEventHandler(EventType event, QObject *object, const char *slot, - Priority priority = NormalPriority, bool isFilter = false); - void registerEventHandler(QList events, QObject *object, const char *slot, - Priority priority = NormalPriority, bool isFilter = false); - - void registerEventFilter(EventType event, QObject *object, const char *slot); - void registerEventFilter(QList events, QObject *object, const char *slot); - - //! Send an event to the registered handlers - /** - The EventManager takes ownership of the event and will delete it once it's processed. - @param event The event to be dispatched - */ - void postEvent(Event *event); + void registerObject(QObject *object, Priority priority = NormalPriority, + const QString &methodPrefix = "process", + const QString &filterPrefix = "filter"); + void registerEventHandler(EventType event, QObject *object, const char *slot, + Priority priority = NormalPriority, bool isFilter = false); + void registerEventHandler(QList events, QObject *object, const char *slot, + Priority priority = NormalPriority, bool isFilter = false); + + void registerEventFilter(EventType event, QObject *object, const char *slot); + void registerEventFilter(QList events, QObject *object, const char *slot); + + //! Send an event to the registered handlers + /** + The EventManager takes ownership of the event and will delete it once it's processed. + @param event The event to be dispatched + */ + void postEvent(Event *event); protected: - virtual Network *networkById(NetworkId id) const = 0; - virtual void customEvent(QEvent *event); + virtual Network *networkById(NetworkId id) const = 0; + virtual void customEvent(QEvent *event); private: - struct Handler { - QObject *object; - int methodIndex; - Priority priority; + struct Handler { + QObject *object; + int methodIndex; + Priority priority; - explicit Handler(QObject *obj = 0, int method = 0, Priority prio = NormalPriority) { - object = obj; - methodIndex = method; - priority = prio; - } - }; + explicit Handler(QObject *obj = 0, int method = 0, Priority prio = NormalPriority) + { + object = obj; + methodIndex = method; + priority = prio; + } + }; - typedef QHash > HandlerHash; + typedef QHash > HandlerHash; - inline const HandlerHash ®isteredHandlers() const { return _registeredHandlers; } - inline HandlerHash ®isteredHandlers() { return _registeredHandlers; } + inline const HandlerHash ®isteredHandlers() const { return _registeredHandlers; } + inline HandlerHash ®isteredHandlers() { return _registeredHandlers; } - inline const HandlerHash ®isteredFilters() const { return _registeredFilters; } - inline HandlerHash ®isteredFilters() { return _registeredFilters; } + inline const HandlerHash ®isteredFilters() const { return _registeredFilters; } + inline HandlerHash ®isteredFilters() { return _registeredFilters; } - //! Add handlers to an existing sorted (by priority) handler list - void insertHandlers(const QList &newHandlers, QList &existing, bool checkDupes = false); - //! Add filters to an existing filter hash - void insertFilters(const QList &newFilters, QHash &existing); + //! Add handlers to an existing sorted (by priority) handler list + void insertHandlers(const QList &newHandlers, QList &existing, bool checkDupes = false); + //! Add filters to an existing filter hash + void insertFilters(const QList &newFilters, QHash &existing); - int findEventType(const QString &methodSignature, const QString &methodPrefix) const; + int findEventType(const QString &methodSignature, const QString &methodPrefix) const; - void processEvent(Event *event); - void dispatchEvent(Event *event); + void processEvent(Event *event); + void dispatchEvent(Event *event); - //! @return the EventType enum - static QMetaEnum eventEnum(); + //! @return the EventType enum + static QMetaEnum eventEnum(); - HandlerHash _registeredHandlers; - HandlerHash _registeredFilters; - QList _eventQueue; - static QMetaEnum _enum; + HandlerHash _registeredHandlers; + HandlerHash _registeredFilters; + QList _eventQueue; + static QMetaEnum _enum; }; + Q_DECLARE_OPERATORS_FOR_FLAGS(EventManager::EventFlags); #endif diff --git a/src/common/genversion.cpp b/src/common/genversion.cpp index f0f746bb..69dfb542 100644 --- a/src/common/genversion.cpp +++ b/src/common/genversion.cpp @@ -29,107 +29,108 @@ #include #include -int main(int argc, char **argv) { - if(argc < 3) { - qFatal("Usage: ./genversion "); - return 255; - } - QString gitroot = argv[1]; - QString target = argv[2]; - QString basever, protover, clientneeds, coreneeds, descrver, dirty; - QString committish, commitdate; +int main(int argc, char **argv) +{ + if (argc < 3) { + qFatal("Usage: ./genversion "); + return 255; + } + QString gitroot = argv[1]; + QString target = argv[2]; + QString basever, protover, clientneeds, coreneeds, descrver, dirty; + QString committish, commitdate; - // check Git for information if present - if(QFile::exists(gitroot + "/.git")) { - // try to execute git-describe to get a version string - QProcess git; - git.setWorkingDirectory(gitroot); + // check Git for information if present + if (QFile::exists(gitroot + "/.git")) { + // try to execute git-describe to get a version string + QProcess git; + git.setWorkingDirectory(gitroot); #ifdef Q_OS_WIN - git.start("cmd.exe", QStringList() << "/C" << "git" << "describe" << "--long"); + git.start("cmd.exe", QStringList() << "/C" << "git" << "describe" << "--long"); #else - git.start("git", QStringList() << "describe" << "--long"); + git.start("git", QStringList() << "describe" << "--long"); #endif - if(git.waitForFinished(10000)) { - QString descr = git.readAllStandardOutput().trimmed(); - if(!descr.isEmpty() && !descr.contains("fatal")) { - // seems we have a valid git describe string - descrver = descr; - // check if the workdir is dirty + if (git.waitForFinished(10000)) { + QString descr = git.readAllStandardOutput().trimmed(); + if (!descr.isEmpty() && !descr.contains("fatal")) { + // seems we have a valid git describe string + descrver = descr; + // check if the workdir is dirty #ifdef Q_OS_WIN - git.start("cmd.exe", QStringList() << "/C" << "git" << "diff-index" << "--name-only" << "HEAD"); + git.start("cmd.exe", QStringList() << "/C" << "git" << "diff-index" << "--name-only" << "HEAD"); #else - git.start("git", QStringList() << "diff-index" << "--name-only" << "HEAD"); + git.start("git", QStringList() << "diff-index" << "--name-only" << "HEAD"); #endif - if(git.waitForFinished(10000)) { - if(!git.readAllStandardOutput().isEmpty()) dirty = "*"; - } - // get a full committish + if (git.waitForFinished(10000)) { + if (!git.readAllStandardOutput().isEmpty()) dirty = "*"; + } + // get a full committish #ifdef Q_OS_WIN - git.start("cmd.exe", QStringList() << "/C" << "git" << "rev-parse" << "HEAD"); + git.start("cmd.exe", QStringList() << "/C" << "git" << "rev-parse" << "HEAD"); #else - git.start("git", QStringList() << "rev-parse" << "HEAD"); + git.start("git", QStringList() << "rev-parse" << "HEAD"); #endif - if(git.waitForFinished(10000)) { - committish = git.readAllStandardOutput().trimmed(); + if (git.waitForFinished(10000)) { + committish = git.readAllStandardOutput().trimmed(); + } + // Now we do some replacement magic... + //QRegExp rxCheckTag("(.*)-0-g[0-9a-f]+\n$"); + //QRegExp rxGittify("(.*)-(\\d+)-g([0-9a-f]+)\n$"); + //gitversion.replace(rxCheckTag, QString("\\1%1").arg(dirty)); + //gitversion.replace(rxGittify, QString("\\1:git-\\3+\\2%1").arg(dirty)); + } } - // Now we do some replacement magic... - //QRegExp rxCheckTag("(.*)-0-g[0-9a-f]+\n$"); - //QRegExp rxGittify("(.*)-(\\d+)-g([0-9a-f]+)\n$"); - //gitversion.replace(rxCheckTag, QString("\\1%1").arg(dirty)); - //gitversion.replace(rxGittify, QString("\\1:git-\\3+\\2%1").arg(dirty)); - } } - } - // parse version.inc - QFile verfile(gitroot + "/version.inc"); - if(verfile.open(QIODevice::ReadOnly | QIODevice::Text)) { - QString ver = verfile.readAll(); + // parse version.inc + QFile verfile(gitroot + "/version.inc"); + if (verfile.open(QIODevice::ReadOnly | QIODevice::Text)) { + QString ver = verfile.readAll(); - QRegExp rxBasever("baseVersion\\s*=\\s*\"(.*)\";"); - if(rxBasever.indexIn(ver) >= 0) - basever = rxBasever.cap(1); + QRegExp rxBasever("baseVersion\\s*=\\s*\"(.*)\";"); + if (rxBasever.indexIn(ver) >= 0) + basever = rxBasever.cap(1); - QRegExp rxProtover("protocolVersion\\s*=\\s*(\\d+)"); - if(rxProtover.indexIn(ver) >= 0) - protover = rxProtover.cap(1); + QRegExp rxProtover("protocolVersion\\s*=\\s*(\\d+)"); + if (rxProtover.indexIn(ver) >= 0) + protover = rxProtover.cap(1); - QRegExp rxClientneeds("clientNeedsProtocol\\s*=\\s*(\\d+)"); - if(rxClientneeds.indexIn(ver) >= 0) - clientneeds = rxClientneeds.cap(1); + QRegExp rxClientneeds("clientNeedsProtocol\\s*=\\s*(\\d+)"); + if (rxClientneeds.indexIn(ver) >= 0) + clientneeds = rxClientneeds.cap(1); - QRegExp rxCoreneeds("coreNeedsProtocol\\s*=\\s*(\\d+)"); - if(rxCoreneeds.indexIn(ver) >= 0) - coreneeds = rxCoreneeds.cap(1); + QRegExp rxCoreneeds("coreNeedsProtocol\\s*=\\s*(\\d+)"); + if (rxCoreneeds.indexIn(ver) >= 0) + coreneeds = rxCoreneeds.cap(1); - if(committish.isEmpty()) { - QRegExp rxCommit("distCommittish\\s*=\\s*([0-9a-f]+)"); - if(rxCommit.indexIn(ver) >= 0) committish = rxCommit.cap(1); - } + if (committish.isEmpty()) { + QRegExp rxCommit("distCommittish\\s*=\\s*([0-9a-f]+)"); + if (rxCommit.indexIn(ver) >= 0) committish = rxCommit.cap(1); + } - QRegExp rxTimestamp("distCommitDate\\s*=\\s*([0-9]+)"); - if(rxTimestamp.indexIn(ver) >= 0) commitdate = rxTimestamp.cap(1); - verfile.close(); - } + QRegExp rxTimestamp("distCommitDate\\s*=\\s*([0-9]+)"); + if (rxTimestamp.indexIn(ver) >= 0) commitdate = rxTimestamp.cap(1); + verfile.close(); + } - // generate the contents for version.gen - QByteArray contents = QString("QString buildinfo = \"%1,%2,%3,%4,%5,%6,%7,%8\";\n") - .arg(basever, descrver, dirty, committish, commitdate, protover, clientneeds, coreneeds) - .toAscii(); + // generate the contents for version.gen + QByteArray contents = QString("QString buildinfo = \"%1,%2,%3,%4,%5,%6,%7,%8\";\n") + .arg(basever, descrver, dirty, committish, commitdate, protover, clientneeds, coreneeds) + .toAscii(); - QFile gen(target); - if(!gen.open(QIODevice::ReadWrite | QIODevice::Text)) { - qFatal("%s", qPrintable(QString("Could not write %1!").arg(target))); - return EXIT_FAILURE; - } - QByteArray oldContents = gen.readAll(); - if(oldContents != contents) { // only touch the file if something changed - gen.seek(0); - gen.resize(0); - gen.write(contents); - gen.waitForBytesWritten(10000); - } - gen.close(); + QFile gen(target); + if (!gen.open(QIODevice::ReadWrite | QIODevice::Text)) { + qFatal("%s", qPrintable(QString("Could not write %1!").arg(target))); + return EXIT_FAILURE; + } + QByteArray oldContents = gen.readAll(); + if (oldContents != contents) { // only touch the file if something changed + gen.seek(0); + gen.resize(0); + gen.write(contents); + gen.waitForBytesWritten(10000); + } + gen.close(); - return EXIT_SUCCESS; + return EXIT_SUCCESS; } diff --git a/src/common/identity.cpp b/src/common/identity.cpp index 6cb37808..20f43871 100644 --- a/src/common/identity.cpp +++ b/src/common/identity.cpp @@ -44,15 +44,16 @@ INIT_SYNCABLE_OBJECT(Identity) Identity::Identity(IdentityId id, QObject *parent) - : SyncableObject(parent), + : SyncableObject(parent), _identityId(id) { - init(); - setToDefaults(); + init(); + setToDefaults(); } + Identity::Identity(const Identity &other, QObject *parent) - : SyncableObject(parent), + : SyncableObject(parent), _identityId(other.id()), _identityName(other.identityName()), _realName(other.realName()), @@ -73,260 +74,323 @@ Identity::Identity(const Identity &other, QObject *parent) _partReason(other.partReason()), _quitReason(other.quitReason()) { - init(); + init(); } + #ifdef Q_WS_WIN #ifdef UNICODE -QString tcharToQString(TCHAR *tchar){ - return QString::fromUtf16( reinterpret_cast(tchar)); +QString tcharToQString(TCHAR *tchar) +{ + return QString::fromUtf16(reinterpret_cast(tchar)); } + + #else -QString tcharToQString(TCHAR *tchar){ - return QString::fromLocal8Bit(tchar); +QString tcharToQString(TCHAR *tchar) +{ + return QString::fromLocal8Bit(tchar); } + + #endif #endif -void Identity::init() { - setObjectName(QString::number(id().toInt())); - setAllowClientUpdates(true); +void Identity::init() +{ + setObjectName(QString::number(id().toInt())); + setAllowClientUpdates(true); } -QString Identity::defaultNick() { - QString nick = QString("quassel%1").arg(qrand() & 0xff); // FIXME provide more sensible default nicks + +QString Identity::defaultNick() +{ + QString nick = QString("quassel%1").arg(qrand() & 0xff); // FIXME provide more sensible default nicks #ifdef Q_OS_MAC - QString shortUserName = CFStringToQString(CSCopyUserName(true)); - if(!shortUserName.isEmpty()) - nick = shortUserName; + QString shortUserName = CFStringToQString(CSCopyUserName(true)); + if (!shortUserName.isEmpty()) + nick = shortUserName; #elif defined(Q_OS_UNIX) - QString userName; - struct passwd *pwd = getpwuid(getuid()); - if(pwd) - userName = pwd->pw_name; - if(!userName.isEmpty()) - nick = userName; + QString userName; + struct passwd *pwd = getpwuid(getuid()); + if (pwd) + userName = pwd->pw_name; + if (!userName.isEmpty()) + nick = userName; #elif defined(Q_OS_WIN32) - TCHAR infoBuf[128]; - DWORD bufCharCount = 128; - //if(GetUserNameEx(/* NameSamCompatible */ 1, infoBuf, &bufCharCount)) - if(GetUserNameEx(NameSamCompatible, infoBuf, &bufCharCount)) { - QString nickName(tcharToQString(infoBuf)); - int lastBs = nickName.lastIndexOf('\\'); - if(lastBs != -1) { - nickName = nickName.mid(lastBs + 1); + TCHAR infoBuf[128]; + DWORD bufCharCount = 128; + //if(GetUserNameEx(/* NameSamCompatible */ 1, infoBuf, &bufCharCount)) + if (GetUserNameEx(NameSamCompatible, infoBuf, &bufCharCount)) { + QString nickName(tcharToQString(infoBuf)); + int lastBs = nickName.lastIndexOf('\\'); + if (lastBs != -1) { + nickName = nickName.mid(lastBs + 1); + } + if (!nickName.isEmpty()) + nick = nickName; } - if(!nickName.isEmpty()) - nick = nickName; - } #endif - // cleaning forbidden characters from nick - QRegExp rx(QString("(^[\\d-]+|[^A-Za-z0-9\x5b-\x60\x7b-\x7d])")); - nick.remove(rx); - return nick; + // cleaning forbidden characters from nick + QRegExp rx(QString("(^[\\d-]+|[^A-Za-z0-9\x5b-\x60\x7b-\x7d])")); + nick.remove(rx); + return nick; } -QString Identity::defaultRealName() { - QString generalDefault = tr("Quassel IRC User"); + +QString Identity::defaultRealName() +{ + QString generalDefault = tr("Quassel IRC User"); #ifdef Q_OS_MAC - return CFStringToQString(CSCopyUserName(false)); + return CFStringToQString(CSCopyUserName(false)); #elif defined(Q_OS_UNIX) - QString realName; - struct passwd *pwd = getpwuid(getuid()); - if(pwd) - realName = QString::fromUtf8(pwd->pw_gecos); - if(!realName.isEmpty()) - return realName; - else - return generalDefault; + QString realName; + struct passwd *pwd = getpwuid(getuid()); + if (pwd) + realName = QString::fromUtf8(pwd->pw_gecos); + if (!realName.isEmpty()) + return realName; + else + return generalDefault; #elif defined(Q_OS_WIN32) - TCHAR infoBuf[128]; - DWORD bufCharCount = 128; - if(GetUserName(infoBuf, &bufCharCount)) - return tcharToQString(infoBuf); - else - return generalDefault; + TCHAR infoBuf[128]; + DWORD bufCharCount = 128; + if (GetUserName(infoBuf, &bufCharCount)) + return tcharToQString(infoBuf); + else + return generalDefault; #else - return generalDefault; + return generalDefault; #endif } -void Identity::setToDefaults() { - setIdentityName(tr("")); - setRealName(defaultRealName()); - QStringList n = QStringList() << defaultNick(); - setNicks(n); - setAwayNick(""); - setAwayNickEnabled(false); - setAwayReason(tr("Gone fishing.")); - setAwayReasonEnabled(true); - setAutoAwayEnabled(false); - setAutoAwayTime(10); - setAutoAwayReason(tr("Not here. No, really. not here!")); - setAutoAwayReasonEnabled(false); - setDetachAwayEnabled(false); - setDetachAwayReason(tr("All Quassel clients vanished from the face of the earth...")); - setDetachAwayReasonEnabled(false); - setIdent("quassel"); - setKickReason(tr("Kindergarten is elsewhere!")); - setPartReason(tr("http://quassel-irc.org - Chat comfortably. Anywhere.")); - setQuitReason(tr("http://quassel-irc.org - Chat comfortably. Anywhere.")); + +void Identity::setToDefaults() +{ + setIdentityName(tr("")); + setRealName(defaultRealName()); + QStringList n = QStringList() << defaultNick(); + setNicks(n); + setAwayNick(""); + setAwayNickEnabled(false); + setAwayReason(tr("Gone fishing.")); + setAwayReasonEnabled(true); + setAutoAwayEnabled(false); + setAutoAwayTime(10); + setAutoAwayReason(tr("Not here. No, really. not here!")); + setAutoAwayReasonEnabled(false); + setDetachAwayEnabled(false); + setDetachAwayReason(tr("All Quassel clients vanished from the face of the earth...")); + setDetachAwayReasonEnabled(false); + setIdent("quassel"); + setKickReason(tr("Kindergarten is elsewhere!")); + setPartReason(tr("http://quassel-irc.org - Chat comfortably. Anywhere.")); + setQuitReason(tr("http://quassel-irc.org - Chat comfortably. Anywhere.")); } + /*** setters ***/ -void Identity::setId(IdentityId _id) { - _identityId = _id; - SYNC(ARG(_id)) - emit idSet(_id); - renameObject(QString::number(id().toInt())); +void Identity::setId(IdentityId _id) +{ + _identityId = _id; + SYNC(ARG(_id)) + emit idSet(_id); + renameObject(QString::number(id().toInt())); } -void Identity::setIdentityName(const QString &identityName) { - _identityName = identityName; - SYNC(ARG(identityName)) + +void Identity::setIdentityName(const QString &identityName) +{ + _identityName = identityName; + SYNC(ARG(identityName)) } -void Identity::setRealName(const QString &realName) { - _realName = realName; - SYNC(ARG(realName)) + +void Identity::setRealName(const QString &realName) +{ + _realName = realName; + SYNC(ARG(realName)) } -void Identity::setNicks(const QStringList &nicks) { - _nicks = nicks; - SYNC(ARG(nicks)) - emit nicksSet(nicks); + +void Identity::setNicks(const QStringList &nicks) +{ + _nicks = nicks; + SYNC(ARG(nicks)) + emit nicksSet(nicks); } -void Identity::setAwayNick(const QString &nick) { - _awayNick = nick; - SYNC(ARG(nick)) + +void Identity::setAwayNick(const QString &nick) +{ + _awayNick = nick; + SYNC(ARG(nick)) } -void Identity::setAwayReason(const QString &reason) { - _awayReason = reason; - SYNC(ARG(reason)) + +void Identity::setAwayReason(const QString &reason) +{ + _awayReason = reason; + SYNC(ARG(reason)) } -void Identity::setAwayNickEnabled(bool enabled) { - _awayNickEnabled = enabled; - SYNC(ARG(enabled)) + +void Identity::setAwayNickEnabled(bool enabled) +{ + _awayNickEnabled = enabled; + SYNC(ARG(enabled)) } -void Identity::setAwayReasonEnabled(bool enabled) { - _awayReasonEnabled = enabled; - SYNC(ARG(enabled)) + +void Identity::setAwayReasonEnabled(bool enabled) +{ + _awayReasonEnabled = enabled; + SYNC(ARG(enabled)) } -void Identity::setAutoAwayEnabled(bool enabled) { - _autoAwayEnabled = enabled; - SYNC(ARG(enabled)) + +void Identity::setAutoAwayEnabled(bool enabled) +{ + _autoAwayEnabled = enabled; + SYNC(ARG(enabled)) } -void Identity::setAutoAwayTime(int time) { - _autoAwayTime = time; - SYNC(ARG(time)) + +void Identity::setAutoAwayTime(int time) +{ + _autoAwayTime = time; + SYNC(ARG(time)) } -void Identity::setAutoAwayReason(const QString &reason) { - _autoAwayReason = reason; - SYNC(ARG(reason)) + +void Identity::setAutoAwayReason(const QString &reason) +{ + _autoAwayReason = reason; + SYNC(ARG(reason)) } -void Identity::setAutoAwayReasonEnabled(bool enabled) { - _autoAwayReasonEnabled = enabled; - SYNC(ARG(enabled)) + +void Identity::setAutoAwayReasonEnabled(bool enabled) +{ + _autoAwayReasonEnabled = enabled; + SYNC(ARG(enabled)) } -void Identity::setDetachAwayEnabled(bool enabled) { - _detachAwayEnabled = enabled; - SYNC(ARG(enabled)) + +void Identity::setDetachAwayEnabled(bool enabled) +{ + _detachAwayEnabled = enabled; + SYNC(ARG(enabled)) } -void Identity::setDetachAwayReason(const QString &reason) { - _detachAwayReason = reason; - SYNC(ARG(reason)) + +void Identity::setDetachAwayReason(const QString &reason) +{ + _detachAwayReason = reason; + SYNC(ARG(reason)) } -void Identity::setDetachAwayReasonEnabled(bool enabled) { - _detachAwayReasonEnabled = enabled; - SYNC(ARG(enabled)) + +void Identity::setDetachAwayReasonEnabled(bool enabled) +{ + _detachAwayReasonEnabled = enabled; + SYNC(ARG(enabled)) } -void Identity::setIdent(const QString &ident) { - _ident = ident; - SYNC(ARG(ident)) + +void Identity::setIdent(const QString &ident) +{ + _ident = ident; + SYNC(ARG(ident)) } -void Identity::setKickReason(const QString &reason) { - _kickReason = reason; - SYNC(ARG(reason)) + +void Identity::setKickReason(const QString &reason) +{ + _kickReason = reason; + SYNC(ARG(reason)) } -void Identity::setPartReason(const QString &reason) { - _partReason = reason; - SYNC(ARG(reason)) + +void Identity::setPartReason(const QString &reason) +{ + _partReason = reason; + SYNC(ARG(reason)) } -void Identity::setQuitReason(const QString &reason) { - _quitReason = reason; - SYNC(ARG(reason)) + +void Identity::setQuitReason(const QString &reason) +{ + _quitReason = reason; + SYNC(ARG(reason)) } + /*** ***/ -void Identity::copyFrom(const Identity &other) { - for(int idx = staticMetaObject.propertyOffset(); idx < staticMetaObject.propertyCount(); idx++) { - QMetaProperty metaProp = staticMetaObject.property(idx); - Q_ASSERT(metaProp.isValid()); - if(this->property(metaProp.name()) != other.property(metaProp.name())) { - setProperty(metaProp.name(), other.property(metaProp.name())); +void Identity::copyFrom(const Identity &other) +{ + for (int idx = staticMetaObject.propertyOffset(); idx < staticMetaObject.propertyCount(); idx++) { + QMetaProperty metaProp = staticMetaObject.property(idx); + Q_ASSERT(metaProp.isValid()); + if (this->property(metaProp.name()) != other.property(metaProp.name())) { + setProperty(metaProp.name(), other.property(metaProp.name())); + } } - } -} - -bool Identity::operator==(const Identity &other) const { - for(int idx = staticMetaObject.propertyOffset(); idx < staticMetaObject.propertyCount(); idx++) { - QMetaProperty metaProp = staticMetaObject.property(idx); - Q_ASSERT(metaProp.isValid()); - QVariant v1 = this->property(metaProp.name()); - QVariant v2 = other.property(metaProp.name()); // qDebug() << v1 << v2; - // QVariant cannot compare custom types, so we need to check for this special case - if(QString(v1.typeName()) == "IdentityId") { - if(v1.value() != v2.value()) return false; - } else { - if(v1 != v2) return false; +} + + +bool Identity::operator==(const Identity &other) const +{ + for (int idx = staticMetaObject.propertyOffset(); idx < staticMetaObject.propertyCount(); idx++) { + QMetaProperty metaProp = staticMetaObject.property(idx); + Q_ASSERT(metaProp.isValid()); + QVariant v1 = this->property(metaProp.name()); + QVariant v2 = other.property(metaProp.name()); // qDebug() << v1 << v2; + // QVariant cannot compare custom types, so we need to check for this special case + if (QString(v1.typeName()) == "IdentityId") { + if (v1.value() != v2.value()) return false; + } + else { + if (v1 != v2) return false; + } } - } - return true; + return true; } -bool Identity::operator!=(const Identity &other) const { - return !(*this == other); + +bool Identity::operator!=(const Identity &other) const +{ + return !(*this == other); } + /////////////////////////////// -QDataStream &operator<<(QDataStream &out, Identity id) { - out << id.toVariantMap(); - return out; +QDataStream &operator<<(QDataStream &out, Identity id) +{ + out << id.toVariantMap(); + return out; } -QDataStream &operator>>(QDataStream &in, Identity &id) { - QVariantMap i; - in >> i; - id.fromVariantMap(i); - return in; +QDataStream &operator>>(QDataStream &in, Identity &id) +{ + QVariantMap i; + in >> i; + id.fromVariantMap(i); + return in; } + #ifdef HAVE_SSL INIT_SYNCABLE_OBJECT(CertManager) #endif // HAVE_SSL diff --git a/src/common/identity.h b/src/common/identity.h index 63450462..66305e4e 100644 --- a/src/common/identity.h +++ b/src/common/identity.h @@ -30,90 +30,91 @@ #include "types.h" #include "syncableobject.h" -class Identity : public SyncableObject { - SYNCABLE_OBJECT - Q_OBJECT - - Q_PROPERTY(IdentityId identityId READ id WRITE setId STORED false) - Q_PROPERTY(QString identityName READ identityName WRITE setIdentityName STORED false) - Q_PROPERTY(QString realName READ realName WRITE setRealName STORED false) - Q_PROPERTY(QStringList nicks READ nicks WRITE setNicks STORED false) - Q_PROPERTY(QString awayNick READ awayNick WRITE setAwayNick STORED false) - Q_PROPERTY(bool awayNickEnabled READ awayNickEnabled WRITE setAwayNickEnabled STORED false) - Q_PROPERTY(QString awayReason READ awayReason WRITE setAwayReason STORED false) - Q_PROPERTY(bool awayReasonEnabled READ awayReasonEnabled WRITE setAwayReasonEnabled STORED false) - Q_PROPERTY(bool autoAwayEnabled READ autoAwayEnabled WRITE setAutoAwayEnabled STORED false) - Q_PROPERTY(int autoAwayTime READ autoAwayTime WRITE setAutoAwayTime STORED false) - Q_PROPERTY(QString autoAwayReason READ autoAwayReason WRITE setAutoAwayReason STORED false) - Q_PROPERTY(bool autoAwayReasonEnabled READ autoAwayReasonEnabled WRITE setAutoAwayReasonEnabled STORED false) - Q_PROPERTY(bool detachAwayEnabled READ detachAwayEnabled WRITE setDetachAwayEnabled STORED false) - Q_PROPERTY(QString detachAwayReason READ detachAwayReason WRITE setDetachAwayReason STORED false) - Q_PROPERTY(bool detachAwayReasonEnabled READ detachAwayReasonEnabled WRITE setDetachAwayReasonEnabled STORED false) - Q_PROPERTY(QString ident READ ident WRITE setIdent STORED false) - Q_PROPERTY(QString kickReason READ kickReason WRITE setKickReason STORED false) - Q_PROPERTY(QString partReason READ partReason WRITE setPartReason STORED false) - Q_PROPERTY(QString quitReason READ quitReason WRITE setQuitReason STORED false) - -public: - Identity(IdentityId id = 0, QObject *parent = 0); - Identity(const Identity &other, QObject *parent = 0); - inline virtual const QMetaObject *syncMetaObject() const { return &staticMetaObject; } - - void setToDefaults(); - - bool operator==(const Identity &other) const; - bool operator!=(const Identity &other) const; - - inline bool isValid() const { return id().isValid(); } - - inline IdentityId id() const { return _identityId; } - inline const QString &identityName() const { return _identityName; } - inline const QString &realName() const { return _realName; } - inline const QStringList &nicks() const { return _nicks; } - inline const QString &awayNick() const { return _awayNick; } - inline bool awayNickEnabled() const { return _awayNickEnabled; } - inline const QString &awayReason() const { return _awayReason; } - inline bool awayReasonEnabled() const { return _awayReasonEnabled; } - inline bool autoAwayEnabled() const { return _autoAwayEnabled; } - inline int autoAwayTime() const { return _autoAwayTime; } - inline const QString &autoAwayReason() const { return _autoAwayReason; } - inline bool autoAwayReasonEnabled() const { return _autoAwayReasonEnabled; } - inline bool detachAwayEnabled() const { return _detachAwayEnabled; } - inline const QString &detachAwayReason() const { return _detachAwayReason; } - inline bool detachAwayReasonEnabled() const { return _detachAwayReasonEnabled; } - inline const QString &ident() const { return _ident; } - inline const QString &kickReason() const { return _kickReason; } - inline const QString &partReason() const { return _partReason; } - inline const QString &quitReason() const { return _quitReason; } +class Identity : public SyncableObject +{ + SYNCABLE_OBJECT + Q_OBJECT + + Q_PROPERTY(IdentityId identityId READ id WRITE setId STORED false) + Q_PROPERTY(QString identityName READ identityName WRITE setIdentityName STORED false) + Q_PROPERTY(QString realName READ realName WRITE setRealName STORED false) + Q_PROPERTY(QStringList nicks READ nicks WRITE setNicks STORED false) + Q_PROPERTY(QString awayNick READ awayNick WRITE setAwayNick STORED false) + Q_PROPERTY(bool awayNickEnabled READ awayNickEnabled WRITE setAwayNickEnabled STORED false) + Q_PROPERTY(QString awayReason READ awayReason WRITE setAwayReason STORED false) + Q_PROPERTY(bool awayReasonEnabled READ awayReasonEnabled WRITE setAwayReasonEnabled STORED false) + Q_PROPERTY(bool autoAwayEnabled READ autoAwayEnabled WRITE setAutoAwayEnabled STORED false) + Q_PROPERTY(int autoAwayTime READ autoAwayTime WRITE setAutoAwayTime STORED false) + Q_PROPERTY(QString autoAwayReason READ autoAwayReason WRITE setAutoAwayReason STORED false) + Q_PROPERTY(bool autoAwayReasonEnabled READ autoAwayReasonEnabled WRITE setAutoAwayReasonEnabled STORED false) + Q_PROPERTY(bool detachAwayEnabled READ detachAwayEnabled WRITE setDetachAwayEnabled STORED false) + Q_PROPERTY(QString detachAwayReason READ detachAwayReason WRITE setDetachAwayReason STORED false) + Q_PROPERTY(bool detachAwayReasonEnabled READ detachAwayReasonEnabled WRITE setDetachAwayReasonEnabled STORED false) + Q_PROPERTY(QString ident READ ident WRITE setIdent STORED false) + Q_PROPERTY(QString kickReason READ kickReason WRITE setKickReason STORED false) + Q_PROPERTY(QString partReason READ partReason WRITE setPartReason STORED false) + Q_PROPERTY(QString quitReason READ quitReason WRITE setQuitReason STORED false) + +public : + Identity(IdentityId id = 0, QObject *parent = 0); + Identity(const Identity &other, QObject *parent = 0); + inline virtual const QMetaObject *syncMetaObject() const { return &staticMetaObject; } + + void setToDefaults(); + + bool operator==(const Identity &other) const; + bool operator!=(const Identity &other) const; + + inline bool isValid() const { return id().isValid(); } + + inline IdentityId id() const { return _identityId; } + inline const QString &identityName() const { return _identityName; } + inline const QString &realName() const { return _realName; } + inline const QStringList &nicks() const { return _nicks; } + inline const QString &awayNick() const { return _awayNick; } + inline bool awayNickEnabled() const { return _awayNickEnabled; } + inline const QString &awayReason() const { return _awayReason; } + inline bool awayReasonEnabled() const { return _awayReasonEnabled; } + inline bool autoAwayEnabled() const { return _autoAwayEnabled; } + inline int autoAwayTime() const { return _autoAwayTime; } + inline const QString &autoAwayReason() const { return _autoAwayReason; } + inline bool autoAwayReasonEnabled() const { return _autoAwayReasonEnabled; } + inline bool detachAwayEnabled() const { return _detachAwayEnabled; } + inline const QString &detachAwayReason() const { return _detachAwayReason; } + inline bool detachAwayReasonEnabled() const { return _detachAwayReasonEnabled; } + inline const QString &ident() const { return _ident; } + inline const QString &kickReason() const { return _kickReason; } + inline const QString &partReason() const { return _partReason; } + inline const QString &quitReason() const { return _quitReason; } public slots: - void setId(IdentityId id); - void setIdentityName(const QString &name); - void setRealName(const QString &realName); - void setNicks(const QStringList &nicks); - void setAwayNick(const QString &awayNick); - void setAwayNickEnabled(bool enabled); - void setAwayReason(const QString &awayReason); - void setAwayReasonEnabled(bool enabled); - void setAutoAwayEnabled(bool enabled); - void setAutoAwayTime(int time); - void setAutoAwayReason(const QString &reason); - void setAutoAwayReasonEnabled(bool enabled); - void setDetachAwayEnabled(bool enabled); - void setDetachAwayReason(const QString &reason); - void setDetachAwayReasonEnabled(bool enabled); - void setIdent(const QString &ident); - void setKickReason(const QString &reason); - void setPartReason(const QString &reason); - void setQuitReason(const QString &reason); - - void copyFrom(const Identity &other); + void setId(IdentityId id); + void setIdentityName(const QString &name); + void setRealName(const QString &realName); + void setNicks(const QStringList &nicks); + void setAwayNick(const QString &awayNick); + void setAwayNickEnabled(bool enabled); + void setAwayReason(const QString &awayReason); + void setAwayReasonEnabled(bool enabled); + void setAutoAwayEnabled(bool enabled); + void setAutoAwayTime(int time); + void setAutoAwayReason(const QString &reason); + void setAutoAwayReasonEnabled(bool enabled); + void setDetachAwayEnabled(bool enabled); + void setDetachAwayReason(const QString &reason); + void setDetachAwayReasonEnabled(bool enabled); + void setIdent(const QString &ident); + void setKickReason(const QString &reason); + void setPartReason(const QString &reason); + void setQuitReason(const QString &reason); + + void copyFrom(const Identity &other); signals: - void idSet(IdentityId id); + void idSet(IdentityId id); // void identityNameSet(const QString &name); // void realNameSet(const QString &realName); - void nicksSet(const QStringList &nicks); + void nicksSet(const QStringList &nicks); // void awayNickSet(const QString &awayNick); // void awayNickEnabledSet(bool); // void awayReasonSet(const QString &awayReason); @@ -131,29 +132,30 @@ signals: // void quitReasonSet(const QString &); private: - IdentityId _identityId; - QString _identityName, _realName; - QStringList _nicks; - QString _awayNick; - bool _awayNickEnabled; - QString _awayReason; - bool _awayReasonEnabled; - bool _autoAwayEnabled; - int _autoAwayTime; - QString _autoAwayReason; - bool _autoAwayReasonEnabled; - bool _detachAwayEnabled; - QString _detachAwayReason; - bool _detachAwayReasonEnabled; - QString _ident, _kickReason, _partReason, _quitReason; - - void init(); - QString defaultNick(); - QString defaultRealName(); - - friend QDataStream &operator>>(QDataStream &in, Identity &identity); + IdentityId _identityId; + QString _identityName, _realName; + QStringList _nicks; + QString _awayNick; + bool _awayNickEnabled; + QString _awayReason; + bool _awayReasonEnabled; + bool _autoAwayEnabled; + int _autoAwayTime; + QString _autoAwayReason; + bool _autoAwayReasonEnabled; + bool _detachAwayEnabled; + QString _detachAwayReason; + bool _detachAwayReasonEnabled; + QString _ident, _kickReason, _partReason, _quitReason; + + void init(); + QString defaultNick(); + QString defaultRealName(); + + friend QDataStream &operator>>(QDataStream &in, Identity &identity); }; + QDataStream &operator<<(QDataStream &out, Identity identity); QDataStream &operator>>(QDataStream &in, Identity &identity); @@ -163,26 +165,28 @@ Q_DECLARE_METATYPE(Identity) #include #include -class CertManager : public SyncableObject { - SYNCABLE_OBJECT - Q_OBJECT - Q_PROPERTY(QByteArray sslKey READ sslKeyPem WRITE setSslKey STORED false) - Q_PROPERTY(QByteArray sslCert READ sslCertPem WRITE setSslCert STORED false) +class CertManager : public SyncableObject +{ + SYNCABLE_OBJECT + Q_OBJECT + Q_PROPERTY(QByteArray sslKey READ sslKeyPem WRITE setSslKey STORED false) + Q_PROPERTY(QByteArray sslCert READ sslCertPem WRITE setSslCert STORED false) -public: - CertManager(IdentityId id, QObject *parent = 0) : SyncableObject(QString::number(id.toInt()), parent) {} - inline virtual const QMetaObject *syncMetaObject() const { return &staticMetaObject; } +public : + CertManager(IdentityId id, QObject *parent = 0) : SyncableObject(QString::number(id.toInt()), parent) {} + inline virtual const QMetaObject *syncMetaObject() const { return &staticMetaObject; } - virtual const QSslKey &sslKey() const = 0; - inline QByteArray sslKeyPem() const { return sslKey().toPem(); } - virtual const QSslCertificate &sslCert() const = 0; - inline QByteArray sslCertPem() const { return sslCert().toPem(); } + virtual const QSslKey &sslKey() const = 0; + inline QByteArray sslKeyPem() const { return sslKey().toPem(); } + virtual const QSslCertificate &sslCert() const = 0; + inline QByteArray sslCertPem() const { return sslCert().toPem(); } public slots: - inline virtual void setSslKey(const QByteArray &encoded) { SYNC(ARG(encoded)) } - inline virtual void setSslCert(const QByteArray &encoded) { SYNC(ARG(encoded)) } + inline virtual void setSslKey(const QByteArray &encoded) { SYNC(ARG(encoded)) } + inline virtual void setSslCert(const QByteArray &encoded) { SYNC(ARG(encoded)) } }; + #endif // HAVE_SSL #endif // IDENTITY_H diff --git a/src/common/ignorelistmanager.cpp b/src/common/ignorelistmanager.cpp index a6a47186..24fae943 100644 --- a/src/common/ignorelistmanager.cpp +++ b/src/common/ignorelistmanager.cpp @@ -26,183 +26,199 @@ #include INIT_SYNCABLE_OBJECT(IgnoreListManager) -IgnoreListManager &IgnoreListManager::operator=(const IgnoreListManager &other) { - if(this == &other) - return *this; +IgnoreListManager &IgnoreListManager::operator=(const IgnoreListManager &other) +{ + if (this == &other) + return *this; - SyncableObject::operator=(other); - _ignoreList = other._ignoreList; - return *this; + SyncableObject::operator=(other); + _ignoreList = other._ignoreList; + return *this; } -int IgnoreListManager::indexOf(const QString &ignore) const { - for(int i = 0; i < _ignoreList.count(); i++) { - if(_ignoreList[i].ignoreRule == ignore) - return i; - } - return -1; + +int IgnoreListManager::indexOf(const QString &ignore) const +{ + for (int i = 0; i < _ignoreList.count(); i++) { + if (_ignoreList[i].ignoreRule == ignore) + return i; + } + return -1; } -QVariantMap IgnoreListManager::initIgnoreList() const { - QVariantMap ignoreListMap; - QVariantList ignoreTypeList; - QStringList ignoreRuleList; - QStringList scopeRuleList; - QVariantList isRegExList; - QVariantList scopeList; - QVariantList strictnessList; - QVariantList isActiveList; - - for(int i = 0; i < _ignoreList.count(); i++) { - ignoreTypeList << _ignoreList[i].type; - ignoreRuleList << _ignoreList[i].ignoreRule; - scopeRuleList << _ignoreList[i].scopeRule; - isRegExList << _ignoreList[i].isRegEx; - scopeList << _ignoreList[i].scope; - strictnessList << _ignoreList[i].strictness; - isActiveList << _ignoreList[i].isActive; - } - - ignoreListMap["ignoreType"] = ignoreTypeList; - ignoreListMap["ignoreRule"] = ignoreRuleList; - ignoreListMap["scopeRule"] = scopeRuleList; - ignoreListMap["isRegEx"] = isRegExList; - ignoreListMap["scope"] = scopeList; - ignoreListMap["strictness"] = strictnessList; - ignoreListMap["isActive"] = isActiveList; - return ignoreListMap; + +QVariantMap IgnoreListManager::initIgnoreList() const +{ + QVariantMap ignoreListMap; + QVariantList ignoreTypeList; + QStringList ignoreRuleList; + QStringList scopeRuleList; + QVariantList isRegExList; + QVariantList scopeList; + QVariantList strictnessList; + QVariantList isActiveList; + + for (int i = 0; i < _ignoreList.count(); i++) { + ignoreTypeList << _ignoreList[i].type; + ignoreRuleList << _ignoreList[i].ignoreRule; + scopeRuleList << _ignoreList[i].scopeRule; + isRegExList << _ignoreList[i].isRegEx; + scopeList << _ignoreList[i].scope; + strictnessList << _ignoreList[i].strictness; + isActiveList << _ignoreList[i].isActive; + } + + ignoreListMap["ignoreType"] = ignoreTypeList; + ignoreListMap["ignoreRule"] = ignoreRuleList; + ignoreListMap["scopeRule"] = scopeRuleList; + ignoreListMap["isRegEx"] = isRegExList; + ignoreListMap["scope"] = scopeList; + ignoreListMap["strictness"] = strictnessList; + ignoreListMap["isActive"] = isActiveList; + return ignoreListMap; } -void IgnoreListManager::initSetIgnoreList(const QVariantMap &ignoreList) { - QVariantList ignoreType = ignoreList["ignoreType"].toList(); - QStringList ignoreRule = ignoreList["ignoreRule"].toStringList(); - QStringList scopeRule = ignoreList["scopeRule"].toStringList(); - QVariantList isRegEx = ignoreList["isRegEx"].toList(); - QVariantList scope = ignoreList["scope"].toList(); - QVariantList strictness = ignoreList["strictness"].toList(); - QVariantList isActive = ignoreList["isActive"].toList(); - - int count = ignoreRule.count(); - if(count != scopeRule.count() || count != isRegEx.count() || - count != scope.count() || count != strictness.count() || count != ignoreType.count() || count != isActive.count()) { - qWarning() << "Corrupted IgnoreList settings! (Count missmatch)"; - return; - } - - _ignoreList.clear(); - for(int i = 0; i < ignoreRule.count(); i++) { - _ignoreList << IgnoreListItem(static_cast(ignoreType[i].toInt()), ignoreRule[i], isRegEx[i].toBool(), - static_cast(strictness[i].toInt()), static_cast(scope[i].toInt()), - scopeRule[i], isActive[i].toBool()); - } + +void IgnoreListManager::initSetIgnoreList(const QVariantMap &ignoreList) +{ + QVariantList ignoreType = ignoreList["ignoreType"].toList(); + QStringList ignoreRule = ignoreList["ignoreRule"].toStringList(); + QStringList scopeRule = ignoreList["scopeRule"].toStringList(); + QVariantList isRegEx = ignoreList["isRegEx"].toList(); + QVariantList scope = ignoreList["scope"].toList(); + QVariantList strictness = ignoreList["strictness"].toList(); + QVariantList isActive = ignoreList["isActive"].toList(); + + int count = ignoreRule.count(); + if (count != scopeRule.count() || count != isRegEx.count() || + count != scope.count() || count != strictness.count() || count != ignoreType.count() || count != isActive.count()) { + qWarning() << "Corrupted IgnoreList settings! (Count missmatch)"; + return; + } + + _ignoreList.clear(); + for (int i = 0; i < ignoreRule.count(); i++) { + _ignoreList << IgnoreListItem(static_cast(ignoreType[i].toInt()), ignoreRule[i], isRegEx[i].toBool(), + static_cast(strictness[i].toInt()), static_cast(scope[i].toInt()), + scopeRule[i], isActive[i].toBool()); + } } + /* since overloaded methods aren't syncable (yet?) we can't use that anymore void IgnoreListManager::addIgnoreListItem(const IgnoreListItem &item) { addIgnoreListItem(item.type, item.ignoreRule, item.isRegEx, item.strictness, item.scope, item.scopeRule, item.isActive); } */ void IgnoreListManager::addIgnoreListItem(int type, const QString &ignoreRule, bool isRegEx, int strictness, - int scope, const QString &scopeRule, bool isActive) { - if(contains(ignoreRule)) { - return; - } + int scope, const QString &scopeRule, bool isActive) +{ + if (contains(ignoreRule)) { + return; + } - IgnoreListItem newItem = IgnoreListItem(static_cast(type), ignoreRule, isRegEx, static_cast(strictness), - static_cast(scope), scopeRule, isActive); - _ignoreList << newItem; + IgnoreListItem newItem = IgnoreListItem(static_cast(type), ignoreRule, isRegEx, static_cast(strictness), + static_cast(scope), scopeRule, isActive); + _ignoreList << newItem; - SYNC(ARG(type), ARG(ignoreRule), ARG(isRegEx), ARG(strictness), ARG(scope), ARG(scopeRule), ARG(isActive)) + SYNC(ARG(type), ARG(ignoreRule), ARG(isRegEx), ARG(strictness), ARG(scope), ARG(scopeRule), ARG(isActive)) } -IgnoreListManager::StrictnessType IgnoreListManager::_match(const QString &msgContents, const QString &msgSender, Message::Type msgType, const QString &network, const QString &bufferName) { - // We method don't rely on a proper Message object to make this method more versatile. - // This allows us to use it in the core with unprocessed Messages or in the Client - // with properly preprocessed Messages. - if(!(msgType & (Message::Plain | Message::Notice | Message::Action))) - return UnmatchedStrictness; - foreach(IgnoreListItem item, _ignoreList) { - if(!item.isActive || item.type == CtcpIgnore) - continue; - if(item.scope == GlobalScope - || (item.scope == NetworkScope && scopeMatch(item.scopeRule, network)) - || (item.scope == ChannelScope && scopeMatch(item.scopeRule, bufferName))) { - - QString str; - if(item.type == MessageIgnore) - str = msgContents; - else - str = msgSender; - - QRegExp ruleRx = QRegExp(item.ignoreRule); - ruleRx.setCaseSensitivity(Qt::CaseInsensitive); - if(!item.isRegEx) { - ruleRx.setPatternSyntax(QRegExp::Wildcard); - } +IgnoreListManager::StrictnessType IgnoreListManager::_match(const QString &msgContents, const QString &msgSender, Message::Type msgType, const QString &network, const QString &bufferName) +{ + // We method don't rely on a proper Message object to make this method more versatile. + // This allows us to use it in the core with unprocessed Messages or in the Client + // with properly preprocessed Messages. + if (!(msgType & (Message::Plain | Message::Notice | Message::Action))) + return UnmatchedStrictness; + + foreach(IgnoreListItem item, _ignoreList) { + if (!item.isActive || item.type == CtcpIgnore) + continue; + if (item.scope == GlobalScope + || (item.scope == NetworkScope && scopeMatch(item.scopeRule, network)) + || (item.scope == ChannelScope && scopeMatch(item.scopeRule, bufferName))) { + QString str; + if (item.type == MessageIgnore) + str = msgContents; + else + str = msgSender; + + QRegExp ruleRx = QRegExp(item.ignoreRule); + ruleRx.setCaseSensitivity(Qt::CaseInsensitive); + if (!item.isRegEx) { + ruleRx.setPatternSyntax(QRegExp::Wildcard); + } // qDebug() << "IgnoreListManager::match: "; // qDebug() << "string: " << str; // qDebug() << "pattern: " << ruleRx.pattern(); // qDebug() << "scopeRule: " << item.scopeRule; // qDebug() << "now testing"; - if((!item.isRegEx && ruleRx.exactMatch(str)) || - (item.isRegEx && ruleRx.indexIn(str) != -1)) { + if ((!item.isRegEx && ruleRx.exactMatch(str)) || + (item.isRegEx && ruleRx.indexIn(str) != -1)) { // qDebug() << "MATCHED!"; - return item.strictness; - } + return item.strictness; + } + } } - } - return UnmatchedStrictness; + return UnmatchedStrictness; } -bool IgnoreListManager::scopeMatch(const QString &scopeRule, const QString &string) const { - foreach(QString rule, scopeRule.split(";")) { - QRegExp ruleRx = QRegExp(rule.trimmed()); - ruleRx.setCaseSensitivity(Qt::CaseInsensitive); - ruleRx.setPatternSyntax(QRegExp::Wildcard); - if(ruleRx.exactMatch(string)) { - return true; +bool IgnoreListManager::scopeMatch(const QString &scopeRule, const QString &string) const +{ + foreach(QString rule, scopeRule.split(";")) { + QRegExp ruleRx = QRegExp(rule.trimmed()); + ruleRx.setCaseSensitivity(Qt::CaseInsensitive); + ruleRx.setPatternSyntax(QRegExp::Wildcard); + if (ruleRx.exactMatch(string)) { + return true; + } } - } - return false; + return false; } -void IgnoreListManager::removeIgnoreListItem(const QString &ignoreRule) { - removeAt(indexOf(ignoreRule)); - SYNC(ARG(ignoreRule)) -} -void IgnoreListManager::toggleIgnoreRule(const QString &ignoreRule) { - int idx = indexOf(ignoreRule); - if(idx == -1) - return; - _ignoreList[idx].isActive = !_ignoreList[idx].isActive; - SYNC(ARG(ignoreRule)) +void IgnoreListManager::removeIgnoreListItem(const QString &ignoreRule) +{ + removeAt(indexOf(ignoreRule)); + SYNC(ARG(ignoreRule)) } -bool IgnoreListManager::ctcpMatch(const QString sender, const QString &network, const QString &type) { - foreach(IgnoreListItem item, _ignoreList) { - if(!item.isActive) - continue; - if(item.scope == GlobalScope || (item.scope == NetworkScope && scopeMatch(item.scopeRule, network))) { - QString sender_; - QStringList types = item.ignoreRule.split(QRegExp("\\s+"), QString::SkipEmptyParts); - sender_ = types.takeAt(0); +void IgnoreListManager::toggleIgnoreRule(const QString &ignoreRule) +{ + int idx = indexOf(ignoreRule); + if (idx == -1) + return; + _ignoreList[idx].isActive = !_ignoreList[idx].isActive; + SYNC(ARG(ignoreRule)) +} - QRegExp ruleRx = QRegExp(sender_); - ruleRx.setCaseSensitivity(Qt::CaseInsensitive); - if(!item.isRegEx) - ruleRx.setPatternSyntax(QRegExp::Wildcard); - if((!item.isRegEx && ruleRx.exactMatch(sender)) || - (item.isRegEx && ruleRx.indexIn(sender) != -1)) { - if(types.isEmpty() || types.contains(type, Qt::CaseInsensitive)) - return true; - } +bool IgnoreListManager::ctcpMatch(const QString sender, const QString &network, const QString &type) +{ + foreach(IgnoreListItem item, _ignoreList) { + if (!item.isActive) + continue; + if (item.scope == GlobalScope || (item.scope == NetworkScope && scopeMatch(item.scopeRule, network))) { + QString sender_; + QStringList types = item.ignoreRule.split(QRegExp("\\s+"), QString::SkipEmptyParts); + + sender_ = types.takeAt(0); + + QRegExp ruleRx = QRegExp(sender_); + ruleRx.setCaseSensitivity(Qt::CaseInsensitive); + if (!item.isRegEx) + ruleRx.setPatternSyntax(QRegExp::Wildcard); + if ((!item.isRegEx && ruleRx.exactMatch(sender)) || + (item.isRegEx && ruleRx.indexIn(sender) != -1)) { + if (types.isEmpty() || types.contains(type, Qt::CaseInsensitive)) + return true; + } + } } - } - return false; + return false; } diff --git a/src/common/ignorelistmanager.h b/src/common/ignorelistmanager.h index b5bdf227..d875cc4f 100644 --- a/src/common/ignorelistmanager.h +++ b/src/common/ignorelistmanager.h @@ -28,124 +28,128 @@ class IgnoreListManager : public SyncableObject { - SYNCABLE_OBJECT - Q_OBJECT + SYNCABLE_OBJECT + Q_OBJECT public: - inline IgnoreListManager(QObject *parent = 0) : SyncableObject(parent) { setAllowClientUpdates(true); } - IgnoreListManager &operator=(const IgnoreListManager &other); - - enum IgnoreType { - SenderIgnore, - MessageIgnore, - CtcpIgnore - }; - - enum StrictnessType { - UnmatchedStrictness = 0, - SoftStrictness = 1, - HardStrictness = 2 - }; - - enum ScopeType { - GlobalScope, - NetworkScope, - ChannelScope, - }; - - struct IgnoreListItem { - IgnoreType type; - QString ignoreRule; - bool isRegEx; - StrictnessType strictness; - ScopeType scope; - QString scopeRule; - bool isActive; - IgnoreListItem() {} - IgnoreListItem(IgnoreType type_, const QString &ignoreRule_, bool isRegEx_, StrictnessType strictness_, - ScopeType scope_, const QString &scopeRule_, bool isActive_) - : type(type_), ignoreRule(ignoreRule_), isRegEx(isRegEx_), strictness(strictness_), scope(scope_), scopeRule(scopeRule_), isActive(isActive_) {} - bool operator!=(const IgnoreListItem &other) { - return (type != other.type || - ignoreRule != other.ignoreRule || - isRegEx != other.isRegEx || - strictness != other.strictness || - scope != other.scope || - scopeRule != other.scopeRule || - isActive != other.isActive); - } - }; - typedef QList IgnoreList; - - int indexOf(const QString &ignore) const; - inline bool contains(const QString &ignore) const { return indexOf(ignore) != -1; } - inline bool isEmpty() const { return _ignoreList.isEmpty(); } - inline int count() const { return _ignoreList.count(); } - inline void removeAt(int index) { _ignoreList.removeAt(index); } - inline IgnoreListItem &operator[](int i) { return _ignoreList[i]; } - inline const IgnoreListItem &operator[](int i) const { return _ignoreList.at(i); } - inline const IgnoreList &ignoreList() const { return _ignoreList; } - - //! Check if a message matches the IgnoreRule - /** This method checks if a message matches the users ignorelist. - * \param msg The Message that should be checked - * \param network The networkname the message belongs to - * \return UnmatchedStrictness, HardStrictness or SoftStrictness representing the match type - */ - inline StrictnessType match(const Message &msg, const QString &network = QString()) { return _match(msg.contents(), msg.sender(), msg.type(), network, msg.bufferInfo().bufferName()); } - - bool ctcpMatch(const QString sender, const QString &network, const QString &type = QString()); + inline IgnoreListManager(QObject *parent = 0) : SyncableObject(parent) { setAllowClientUpdates(true); } + IgnoreListManager &operator=(const IgnoreListManager &other); + + enum IgnoreType { + SenderIgnore, + MessageIgnore, + CtcpIgnore + }; + + enum StrictnessType { + UnmatchedStrictness = 0, + SoftStrictness = 1, + HardStrictness = 2 + }; + + enum ScopeType { + GlobalScope, + NetworkScope, + ChannelScope, + }; + + struct IgnoreListItem { + IgnoreType type; + QString ignoreRule; + bool isRegEx; + StrictnessType strictness; + ScopeType scope; + QString scopeRule; + bool isActive; + IgnoreListItem() {} + IgnoreListItem(IgnoreType type_, const QString &ignoreRule_, bool isRegEx_, StrictnessType strictness_, + ScopeType scope_, const QString &scopeRule_, bool isActive_) + : type(type_), ignoreRule(ignoreRule_), isRegEx(isRegEx_), strictness(strictness_), scope(scope_), scopeRule(scopeRule_), isActive(isActive_) {} + bool operator!=(const IgnoreListItem &other) + { + return (type != other.type || + ignoreRule != other.ignoreRule || + isRegEx != other.isRegEx || + strictness != other.strictness || + scope != other.scope || + scopeRule != other.scopeRule || + isActive != other.isActive); + } + }; + typedef QList IgnoreList; + + int indexOf(const QString &ignore) const; + inline bool contains(const QString &ignore) const { return indexOf(ignore) != -1; } + inline bool isEmpty() const { return _ignoreList.isEmpty(); } + inline int count() const { return _ignoreList.count(); } + inline void removeAt(int index) { _ignoreList.removeAt(index); } + inline IgnoreListItem &operator[](int i) { return _ignoreList[i]; } + inline const IgnoreListItem &operator[](int i) const { return _ignoreList.at(i); } + inline const IgnoreList &ignoreList() const { return _ignoreList; } + + //! Check if a message matches the IgnoreRule + /** This method checks if a message matches the users ignorelist. + * \param msg The Message that should be checked + * \param network The networkname the message belongs to + * \return UnmatchedStrictness, HardStrictness or SoftStrictness representing the match type + */ + inline StrictnessType match(const Message &msg, const QString &network = QString()) { return _match(msg.contents(), msg.sender(), msg.type(), network, msg.bufferInfo().bufferName()); } + + bool ctcpMatch(const QString sender, const QString &network, const QString &type = QString()); // virtual void addIgnoreListItem(const IgnoreListItem &item); public slots: - virtual QVariantMap initIgnoreList() const; - virtual void initSetIgnoreList(const QVariantMap &ignoreList); - - //! Request removal of an ignore rule based on the rule itself. - /** Use this method if you want to remove a single ignore rule - * and get that synced with the core immediately. - * \param ignoreRule A valid ignore rule - */ - virtual inline void requestRemoveIgnoreListItem(const QString &ignoreRule) { REQUEST(ARG(ignoreRule)) } - virtual void removeIgnoreListItem(const QString &ignoreRule); - - //! Request toggling of "isActive" flag of a given ignore rule. - /** Use this method if you want to toggle the "isActive" flag of a single ignore rule - * and get that synced with the core immediately. - * \param ignoreRule A valid ignore rule - */ - virtual inline void requestToggleIgnoreRule(const QString &ignoreRule) { REQUEST(ARG(ignoreRule)) } - virtual void toggleIgnoreRule(const QString &ignoreRule); - - //! Request an IgnoreListItem to be added to the ignore list - /** Items added to the list with this method, get immediately synced with the core - * \param type The IgnoreType of the new rule - * \param ignoreRule The rule itself - * \param isRegEx Signals if the rule should be interpreted as a regular expression - * \param strictness Th StrictnessType that should be applied - * \param scope The ScopeType that should be set - * \param scopeRule A string of semi-colon separated network- or channelnames - * \param isActive Signals if the rule is enabled or not - */ - virtual inline void requestAddIgnoreListItem(int type, const QString &ignoreRule, bool isRegEx, int strictness, - int scope, const QString &scopeRule, bool isActive) { - REQUEST(ARG(type), ARG(ignoreRule), ARG(isRegEx), ARG(strictness), ARG(scope), ARG(scopeRule), ARG(isActive)) - } - virtual void addIgnoreListItem(int type, const QString &ignoreRule, bool isRegEx, int strictness, - int scope, const QString &scopeRule, bool isActive); + virtual QVariantMap initIgnoreList() const; + virtual void initSetIgnoreList(const QVariantMap &ignoreList); + + //! Request removal of an ignore rule based on the rule itself. + /** Use this method if you want to remove a single ignore rule + * and get that synced with the core immediately. + * \param ignoreRule A valid ignore rule + */ + virtual inline void requestRemoveIgnoreListItem(const QString &ignoreRule) { REQUEST(ARG(ignoreRule)) } + virtual void removeIgnoreListItem(const QString &ignoreRule); + + //! Request toggling of "isActive" flag of a given ignore rule. + /** Use this method if you want to toggle the "isActive" flag of a single ignore rule + * and get that synced with the core immediately. + * \param ignoreRule A valid ignore rule + */ + virtual inline void requestToggleIgnoreRule(const QString &ignoreRule) { REQUEST(ARG(ignoreRule)) } + virtual void toggleIgnoreRule(const QString &ignoreRule); + + //! Request an IgnoreListItem to be added to the ignore list + /** Items added to the list with this method, get immediately synced with the core + * \param type The IgnoreType of the new rule + * \param ignoreRule The rule itself + * \param isRegEx Signals if the rule should be interpreted as a regular expression + * \param strictness Th StrictnessType that should be applied + * \param scope The ScopeType that should be set + * \param scopeRule A string of semi-colon separated network- or channelnames + * \param isActive Signals if the rule is enabled or not + */ + virtual inline void requestAddIgnoreListItem(int type, const QString &ignoreRule, bool isRegEx, int strictness, + int scope, const QString &scopeRule, bool isActive) + { + REQUEST(ARG(type), ARG(ignoreRule), ARG(isRegEx), ARG(strictness), ARG(scope), ARG(scopeRule), ARG(isActive)) + } -protected: - void setIgnoreList(const QList &ignoreList) { _ignoreList = ignoreList; } - bool scopeMatch(const QString &scopeRule, const QString &string) const; // scopeRule is a ';'-separated list, string is a network/channel-name - StrictnessType _match(const QString &msgContents, const QString &msgSender, Message::Type msgType, const QString &network, const QString &bufferName); + virtual void addIgnoreListItem(int type, const QString &ignoreRule, bool isRegEx, int strictness, + int scope, const QString &scopeRule, bool isActive); +protected: + void setIgnoreList(const QList &ignoreList) { _ignoreList = ignoreList; } + bool scopeMatch(const QString &scopeRule, const QString &string) const; // scopeRule is a ';'-separated list, string is a network/channel-name + + StrictnessType _match(const QString &msgContents, const QString &msgSender, Message::Type msgType, const QString &network, const QString &bufferName); signals: - void ignoreAdded(IgnoreType type, const QString &ignoreRule, bool isRegex, StrictnessType strictness, ScopeType scope, const QVariant &scopeRule, bool isActive); + void ignoreAdded(IgnoreType type, const QString &ignoreRule, bool isRegex, StrictnessType strictness, ScopeType scope, const QVariant &scopeRule, bool isActive); private: - IgnoreList _ignoreList; + IgnoreList _ignoreList; }; + #endif // IGNORELISTMANAGER_H diff --git a/src/common/ircchannel.cpp b/src/common/ircchannel.cpp index 3c5d7f9d..a19b9541 100644 --- a/src/common/ircchannel.cpp +++ b/src/common/ircchannel.cpp @@ -32,7 +32,7 @@ INIT_SYNCABLE_OBJECT(IrcChannel) IrcChannel::IrcChannel(const QString &channelname, Network *network) - : SyncableObject(network), + : SyncableObject(network), _initialized(false), _name(channelname), _topic(QString()), @@ -40,328 +40,387 @@ IrcChannel::IrcChannel(const QString &channelname, Network *network) _codecForEncoding(0), _codecForDecoding(0) { - setObjectName(QString::number(network->networkId().toInt()) + "/" + channelname); + setObjectName(QString::number(network->networkId().toInt()) + "/" + channelname); } -IrcChannel::~IrcChannel() { + +IrcChannel::~IrcChannel() +{ } + // ==================== // PUBLIC: // ==================== -bool IrcChannel::isKnownUser(IrcUser *ircuser) const { - if(ircuser == 0) { - qWarning() << "Channel" << name() << "received IrcUser Nullpointer!"; - return false; - } +bool IrcChannel::isKnownUser(IrcUser *ircuser) const +{ + if (ircuser == 0) { + qWarning() << "Channel" << name() << "received IrcUser Nullpointer!"; + return false; + } - if(!_userModes.contains(ircuser)) { - qWarning() << "Channel" << name() << "received data for unknown User" << ircuser->nick(); - return false; - } + if (!_userModes.contains(ircuser)) { + qWarning() << "Channel" << name() << "received data for unknown User" << ircuser->nick(); + return false; + } - return true; + return true; } -bool IrcChannel::isValidChannelUserMode(const QString &mode) const { - bool isvalid = true; - if(mode.size() > 1) { - qWarning() << "Channel" << name() << "received Channel User Mode which is longer then 1 Char:" << mode; - isvalid = false; - } - return isvalid; + +bool IrcChannel::isValidChannelUserMode(const QString &mode) const +{ + bool isvalid = true; + if (mode.size() > 1) { + qWarning() << "Channel" << name() << "received Channel User Mode which is longer then 1 Char:" << mode; + isvalid = false; + } + return isvalid; } -QString IrcChannel::userModes(IrcUser *ircuser) const { - if(_userModes.contains(ircuser)) - return _userModes[ircuser]; - else - return QString(); + +QString IrcChannel::userModes(IrcUser *ircuser) const +{ + if (_userModes.contains(ircuser)) + return _userModes[ircuser]; + else + return QString(); } -QString IrcChannel::userModes(const QString &nick) const { - return userModes(network()->ircUser(nick)); + +QString IrcChannel::userModes(const QString &nick) const +{ + return userModes(network()->ircUser(nick)); } -void IrcChannel::setCodecForEncoding(const QString &name) { - setCodecForEncoding(QTextCodec::codecForName(name.toAscii())); + +void IrcChannel::setCodecForEncoding(const QString &name) +{ + setCodecForEncoding(QTextCodec::codecForName(name.toAscii())); } -void IrcChannel::setCodecForEncoding(QTextCodec *codec) { - _codecForEncoding = codec; + +void IrcChannel::setCodecForEncoding(QTextCodec *codec) +{ + _codecForEncoding = codec; } -void IrcChannel::setCodecForDecoding(const QString &name) { - setCodecForDecoding(QTextCodec::codecForName(name.toAscii())); + +void IrcChannel::setCodecForDecoding(const QString &name) +{ + setCodecForDecoding(QTextCodec::codecForName(name.toAscii())); } -void IrcChannel::setCodecForDecoding(QTextCodec *codec) { - _codecForDecoding = codec; + +void IrcChannel::setCodecForDecoding(QTextCodec *codec) +{ + _codecForDecoding = codec; } -QString IrcChannel::decodeString(const QByteArray &text) const { - if(!codecForDecoding()) return network()->decodeString(text); - return ::decodeString(text, _codecForDecoding); + +QString IrcChannel::decodeString(const QByteArray &text) const +{ + if (!codecForDecoding()) return network()->decodeString(text); + return ::decodeString(text, _codecForDecoding); } -QByteArray IrcChannel::encodeString(const QString &string) const { - if(codecForEncoding()) { - return _codecForEncoding->fromUnicode(string); - } - return network()->encodeString(string); + +QByteArray IrcChannel::encodeString(const QString &string) const +{ + if (codecForEncoding()) { + return _codecForEncoding->fromUnicode(string); + } + return network()->encodeString(string); } + // ==================== // PUBLIC SLOTS: // ==================== -void IrcChannel::setTopic(const QString &topic) { - _topic = topic; - SYNC(ARG(topic)) - emit topicSet(topic); +void IrcChannel::setTopic(const QString &topic) +{ + _topic = topic; + SYNC(ARG(topic)) + emit topicSet(topic); } -void IrcChannel::setPassword(const QString &password) { - _password = password; - SYNC(ARG(password)) + +void IrcChannel::setPassword(const QString &password) +{ + _password = password; + SYNC(ARG(password)) } -void IrcChannel::joinIrcUsers(const QList &users, const QStringList &modes) { - if(users.isEmpty()) - return; - if(users.count() != modes.count()) { - qWarning() << "IrcChannel::addUsers(): number of nicks does not match number of modes!"; - return; - } +void IrcChannel::joinIrcUsers(const QList &users, const QStringList &modes) +{ + if (users.isEmpty()) + return; - QStringList newNicks; - QStringList newModes; - QList newUsers; + if (users.count() != modes.count()) { + qWarning() << "IrcChannel::addUsers(): number of nicks does not match number of modes!"; + return; + } - IrcUser *ircuser; - for(int i = 0; i < users.count(); i++) { - ircuser = users[i]; - if(!ircuser || _userModes.contains(ircuser)) { - addUserMode(ircuser, modes[i]); - continue; + QStringList newNicks; + QStringList newModes; + QList newUsers; + + IrcUser *ircuser; + for (int i = 0; i < users.count(); i++) { + ircuser = users[i]; + if (!ircuser || _userModes.contains(ircuser)) { + addUserMode(ircuser, modes[i]); + continue; + } + + _userModes[ircuser] = modes[i]; + ircuser->joinChannel(this); + connect(ircuser, SIGNAL(nickSet(QString)), this, SLOT(ircUserNickSet(QString))); + + // connect(ircuser, SIGNAL(destroyed()), this, SLOT(ircUserDestroyed())); + // if you wonder why there is no counterpart to ircUserJoined: + // the joines are propagted by the ircuser. the signal ircUserJoined is only for convenience + + newNicks << ircuser->nick(); + newModes << modes[i]; + newUsers << ircuser; } - _userModes[ircuser] = modes[i]; - ircuser->joinChannel(this); - connect(ircuser, SIGNAL(nickSet(QString)), this, SLOT(ircUserNickSet(QString))); + if (newNicks.isEmpty()) + return; + + SYNC_OTHER(joinIrcUsers, ARG(newNicks), ARG(newModes)); + emit ircUsersJoined(newUsers); +} - // connect(ircuser, SIGNAL(destroyed()), this, SLOT(ircUserDestroyed())); - // if you wonder why there is no counterpart to ircUserJoined: - // the joines are propagted by the ircuser. the signal ircUserJoined is only for convenience - newNicks << ircuser->nick(); - newModes << modes[i]; - newUsers << ircuser; - } +void IrcChannel::joinIrcUsers(const QStringList &nicks, const QStringList &modes) +{ + QList users; + foreach(QString nick, nicks) + users << network()->newIrcUser(nick); + joinIrcUsers(users, modes); +} - if(newNicks.isEmpty()) - return; - SYNC_OTHER(joinIrcUsers, ARG(newNicks), ARG(newModes)); - emit ircUsersJoined(newUsers); +void IrcChannel::joinIrcUser(IrcUser *ircuser) +{ + QList users; + users << ircuser; + QStringList modes; + modes << QString(); + joinIrcUsers(users, modes); } -void IrcChannel::joinIrcUsers(const QStringList &nicks, const QStringList &modes) { - QList users; - foreach(QString nick, nicks) - users << network()->newIrcUser(nick); - joinIrcUsers(users, modes); -} - -void IrcChannel::joinIrcUser(IrcUser *ircuser) { - QList users; - users << ircuser; - QStringList modes; - modes << QString(); - joinIrcUsers(users, modes); -} - -void IrcChannel::part(IrcUser *ircuser) { - if(isKnownUser(ircuser)) { - _userModes.remove(ircuser); - ircuser->partChannel(this); - // if you wonder why there is no counterpart to ircUserParted: - // the joines are propagted by the ircuser. the signal ircUserParted is only for convenience - disconnect(ircuser, 0, this, 0); - emit ircUserParted(ircuser); - - if(network()->isMe(ircuser) || _userModes.isEmpty()) { - // in either case we're no longer in the channel - // -> clean up the channel and destroy it - QList users = _userModes.keys(); - _userModes.clear(); - foreach(IrcUser *user, users) { - disconnect(user, 0, this, 0); - user->partChannel(this); - } - emit parted(); - network()->removeIrcChannel(this); + +void IrcChannel::part(IrcUser *ircuser) +{ + if (isKnownUser(ircuser)) { + _userModes.remove(ircuser); + ircuser->partChannel(this); + // if you wonder why there is no counterpart to ircUserParted: + // the joines are propagted by the ircuser. the signal ircUserParted is only for convenience + disconnect(ircuser, 0, this, 0); + emit ircUserParted(ircuser); + + if (network()->isMe(ircuser) || _userModes.isEmpty()) { + // in either case we're no longer in the channel + // -> clean up the channel and destroy it + QList users = _userModes.keys(); + _userModes.clear(); + foreach(IrcUser *user, users) { + disconnect(user, 0, this, 0); + user->partChannel(this); + } + emit parted(); + network()->removeIrcChannel(this); + } } - } } -void IrcChannel::part(const QString &nick) { - part(network()->ircUser(nick)); + +void IrcChannel::part(const QString &nick) +{ + part(network()->ircUser(nick)); } + // SET USER MODE -void IrcChannel::setUserModes(IrcUser *ircuser, const QString &modes) { - if(isKnownUser(ircuser)) { - _userModes[ircuser] = modes; - QString nick = ircuser->nick(); - SYNC_OTHER(setUserModes, ARG(nick), ARG(modes)) - emit ircUserModesSet(ircuser, modes); - } +void IrcChannel::setUserModes(IrcUser *ircuser, const QString &modes) +{ + if (isKnownUser(ircuser)) { + _userModes[ircuser] = modes; + QString nick = ircuser->nick(); + SYNC_OTHER(setUserModes, ARG(nick), ARG(modes)) + emit ircUserModesSet(ircuser, modes); + } } -void IrcChannel::setUserModes(const QString &nick, const QString &modes) { - setUserModes(network()->ircUser(nick), modes); + +void IrcChannel::setUserModes(const QString &nick, const QString &modes) +{ + setUserModes(network()->ircUser(nick), modes); } + // ADD USER MODE -void IrcChannel::addUserMode(IrcUser *ircuser, const QString &mode) { - if(!isKnownUser(ircuser) || !isValidChannelUserMode(mode)) - return; +void IrcChannel::addUserMode(IrcUser *ircuser, const QString &mode) +{ + if (!isKnownUser(ircuser) || !isValidChannelUserMode(mode)) + return; + + if (!_userModes[ircuser].contains(mode)) { + _userModes[ircuser] += mode; + QString nick = ircuser->nick(); + SYNC_OTHER(addUserMode, ARG(nick), ARG(mode)) + emit ircUserModeAdded(ircuser, mode); + } +} - if(!_userModes[ircuser].contains(mode)) { - _userModes[ircuser] += mode; - QString nick = ircuser->nick(); - SYNC_OTHER(addUserMode, ARG(nick), ARG(mode)) - emit ircUserModeAdded(ircuser, mode); - } +void IrcChannel::addUserMode(const QString &nick, const QString &mode) +{ + addUserMode(network()->ircUser(nick), mode); } -void IrcChannel::addUserMode(const QString &nick, const QString &mode) { - addUserMode(network()->ircUser(nick), mode); -} // REMOVE USER MODE -void IrcChannel::removeUserMode(IrcUser *ircuser, const QString &mode) { - if(!isKnownUser(ircuser) || !isValidChannelUserMode(mode)) - return; - - if(_userModes[ircuser].contains(mode)) { - _userModes[ircuser].remove(mode); - QString nick = ircuser->nick(); - SYNC_OTHER(removeUserMode, ARG(nick), ARG(mode)); - emit ircUserModeRemoved(ircuser, mode); - } +void IrcChannel::removeUserMode(IrcUser *ircuser, const QString &mode) +{ + if (!isKnownUser(ircuser) || !isValidChannelUserMode(mode)) + return; + + if (_userModes[ircuser].contains(mode)) { + _userModes[ircuser].remove(mode); + QString nick = ircuser->nick(); + SYNC_OTHER(removeUserMode, ARG(nick), ARG(mode)); + emit ircUserModeRemoved(ircuser, mode); + } } -void IrcChannel::removeUserMode(const QString &nick, const QString &mode) { - removeUserMode(network()->ircUser(nick), mode); + +void IrcChannel::removeUserMode(const QString &nick, const QString &mode) +{ + removeUserMode(network()->ircUser(nick), mode); } + // INIT SET USER MODES -QVariantMap IrcChannel::initUserModes() const { - QVariantMap usermodes; - QHash::const_iterator iter = _userModes.constBegin(); - while(iter != _userModes.constEnd()) { - usermodes[iter.key()->nick()] = iter.value(); - iter++; - } - return usermodes; -} - -void IrcChannel::initSetUserModes(const QVariantMap &usermodes) { - QList users; - QStringList modes; - QVariantMap::const_iterator iter = usermodes.constBegin(); - while(iter != usermodes.constEnd()) { - users << network()->newIrcUser(iter.key()); - modes << iter.value().toString(); - iter++; - } - joinIrcUsers(users, modes); -} - -QVariantMap IrcChannel::initChanModes() const { - QVariantMap channelModes; - - QVariantMap A_modes; - QHash::const_iterator A_iter = _A_channelModes.constBegin(); - while(A_iter != _A_channelModes.constEnd()) { - A_modes[A_iter.key()] = A_iter.value(); - A_iter++; - } - channelModes["A"] = A_modes; - - QVariantMap B_modes; - QHash::const_iterator B_iter = _B_channelModes.constBegin(); - while(B_iter != _B_channelModes.constEnd()) { - B_modes[B_iter.key()] = B_iter.value(); - B_iter++; - } - channelModes["B"] = B_modes; - - QVariantMap C_modes; - QHash::const_iterator C_iter = _C_channelModes.constBegin(); - while(C_iter != _C_channelModes.constEnd()) { - C_modes[C_iter.key()] = C_iter.value(); - C_iter++; - } - channelModes["C"] = C_modes; - - QString D_modes; - QSet::const_iterator D_iter = _D_channelModes.constBegin(); - while(D_iter != _D_channelModes.constEnd()) { - D_modes += *D_iter; - D_iter++; - } - channelModes["D"] = D_modes; - - return channelModes; -} - -void IrcChannel::initSetChanModes(const QVariantMap &channelModes) { - QVariantMap::const_iterator iter = channelModes["A"].toMap().constBegin(); - QVariantMap::const_iterator iterEnd = channelModes["A"].toMap().constEnd(); - while(iter != iterEnd) { - _A_channelModes[iter.key()[0]] = iter.value().toStringList(); - iter++; - } - - iter = channelModes["B"].toMap().constBegin(); - iterEnd = channelModes["B"].toMap().constEnd(); - while(iter != iterEnd) { - _B_channelModes[iter.key()[0]] = iter.value().toString(); - iter++; - } - - iter = channelModes["C"].toMap().constBegin(); - iterEnd = channelModes["C"].toMap().constEnd(); - while(iter != iterEnd) { - _C_channelModes[iter.key()[0]] = iter.value().toString(); - iter++; - } - - QString D_modes = channelModes["D"].toString(); - for(int i = 0; i < D_modes.count(); i++) { - _D_channelModes << D_modes[i]; - } - -} - -void IrcChannel::ircUserDestroyed() { - IrcUser *ircUser = static_cast(sender()); - Q_ASSERT(ircUser); - _userModes.remove(ircUser); - // no further propagation. - // this leads only to fuck ups. -} - -void IrcChannel::ircUserNickSet(QString nick) { - IrcUser *ircUser = qobject_cast(sender()); - Q_ASSERT(ircUser); - emit ircUserNickSet(ircUser, nick); +QVariantMap IrcChannel::initUserModes() const +{ + QVariantMap usermodes; + QHash::const_iterator iter = _userModes.constBegin(); + while (iter != _userModes.constEnd()) { + usermodes[iter.key()->nick()] = iter.value(); + iter++; + } + return usermodes; +} + + +void IrcChannel::initSetUserModes(const QVariantMap &usermodes) +{ + QList users; + QStringList modes; + QVariantMap::const_iterator iter = usermodes.constBegin(); + while (iter != usermodes.constEnd()) { + users << network()->newIrcUser(iter.key()); + modes << iter.value().toString(); + iter++; + } + joinIrcUsers(users, modes); } + +QVariantMap IrcChannel::initChanModes() const +{ + QVariantMap channelModes; + + QVariantMap A_modes; + QHash::const_iterator A_iter = _A_channelModes.constBegin(); + while (A_iter != _A_channelModes.constEnd()) { + A_modes[A_iter.key()] = A_iter.value(); + A_iter++; + } + channelModes["A"] = A_modes; + + QVariantMap B_modes; + QHash::const_iterator B_iter = _B_channelModes.constBegin(); + while (B_iter != _B_channelModes.constEnd()) { + B_modes[B_iter.key()] = B_iter.value(); + B_iter++; + } + channelModes["B"] = B_modes; + + QVariantMap C_modes; + QHash::const_iterator C_iter = _C_channelModes.constBegin(); + while (C_iter != _C_channelModes.constEnd()) { + C_modes[C_iter.key()] = C_iter.value(); + C_iter++; + } + channelModes["C"] = C_modes; + + QString D_modes; + QSet::const_iterator D_iter = _D_channelModes.constBegin(); + while (D_iter != _D_channelModes.constEnd()) { + D_modes += *D_iter; + D_iter++; + } + channelModes["D"] = D_modes; + + return channelModes; +} + + +void IrcChannel::initSetChanModes(const QVariantMap &channelModes) +{ + QVariantMap::const_iterator iter = channelModes["A"].toMap().constBegin(); + QVariantMap::const_iterator iterEnd = channelModes["A"].toMap().constEnd(); + while (iter != iterEnd) { + _A_channelModes[iter.key()[0]] = iter.value().toStringList(); + iter++; + } + + iter = channelModes["B"].toMap().constBegin(); + iterEnd = channelModes["B"].toMap().constEnd(); + while (iter != iterEnd) { + _B_channelModes[iter.key()[0]] = iter.value().toString(); + iter++; + } + + iter = channelModes["C"].toMap().constBegin(); + iterEnd = channelModes["C"].toMap().constEnd(); + while (iter != iterEnd) { + _C_channelModes[iter.key()[0]] = iter.value().toString(); + iter++; + } + + QString D_modes = channelModes["D"].toString(); + for (int i = 0; i < D_modes.count(); i++) { + _D_channelModes << D_modes[i]; + } +} + + +void IrcChannel::ircUserDestroyed() +{ + IrcUser *ircUser = static_cast(sender()); + Q_ASSERT(ircUser); + _userModes.remove(ircUser); + // no further propagation. + // this leads only to fuck ups. +} + + +void IrcChannel::ircUserNickSet(QString nick) +{ + IrcUser *ircUser = qobject_cast(sender()); + Q_ASSERT(ircUser); + emit ircUserNickSet(ircUser, nick); +} + + /******************************************************************************* * * 3.3 CHANMODES @@ -394,7 +453,6 @@ void IrcChannel::ircUserNickSet(QString nick) { * ******************************************************************************/ - /******************************************************************************* * Short Version: * A --> add/remove from List @@ -408,136 +466,146 @@ void IrcChannel::ircUserNickSet(QString nick) { // NOTE: the behavior of addChannelMode and removeChannelMode depends on the type of mode // see list above for chanmode types -void IrcChannel::addChannelMode(const QChar &mode, const QString &value) { - Network::ChannelModeType modeType = network()->channelModeType(mode); - - switch(modeType) { - case Network::NOT_A_CHANMODE: - return; - case Network::A_CHANMODE: - if(!_A_channelModes.contains(mode)) - _A_channelModes[mode] = QStringList(value); - else if(!_A_channelModes[mode].contains(value)) - _A_channelModes[mode] << value; - break; - - case Network::B_CHANMODE: - _B_channelModes[mode] = value; - break; - - case Network::C_CHANMODE: - _C_channelModes[mode] = value; - break; - - case Network::D_CHANMODE: - _D_channelModes << mode; - break; - } - SYNC(ARG(mode), ARG(value)) -} - -void IrcChannel::removeChannelMode(const QChar &mode, const QString &value) { - Network::ChannelModeType modeType = network()->channelModeType(mode); - - switch(modeType) { - case Network::NOT_A_CHANMODE: - return; - case Network::A_CHANMODE: - if(_A_channelModes.contains(mode)) - _A_channelModes[mode].removeAll(value); - break; - - case Network::B_CHANMODE: - _B_channelModes.remove(mode); - break; - - case Network::C_CHANMODE: - _C_channelModes.remove(mode); - break; - - case Network::D_CHANMODE: - _D_channelModes.remove(mode); - break; - } - SYNC(ARG(mode), ARG(value)) -} - -bool IrcChannel::hasMode(const QChar &mode) const { - Network::ChannelModeType modeType = network()->channelModeType(mode); - - switch(modeType) { - case Network::NOT_A_CHANMODE: - return false; - case Network::A_CHANMODE: - return _A_channelModes.contains(mode); - case Network::B_CHANMODE: - return _B_channelModes.contains(mode); - case Network::C_CHANMODE: - return _C_channelModes.contains(mode); - case Network::D_CHANMODE: - return _D_channelModes.contains(mode); - default: - return false; - } -} - -QString IrcChannel::modeValue(const QChar &mode) const { - Network::ChannelModeType modeType = network()->channelModeType(mode); - - switch(modeType) { - case Network::B_CHANMODE: - if(_B_channelModes.contains(mode)) - return _B_channelModes[mode]; - else - return QString(); - case Network::C_CHANMODE: - if(_C_channelModes.contains(mode)) - return _C_channelModes[mode]; +void IrcChannel::addChannelMode(const QChar &mode, const QString &value) +{ + Network::ChannelModeType modeType = network()->channelModeType(mode); + + switch (modeType) { + case Network::NOT_A_CHANMODE: + return; + case Network::A_CHANMODE: + if (!_A_channelModes.contains(mode)) + _A_channelModes[mode] = QStringList(value); + else if (!_A_channelModes[mode].contains(value)) + _A_channelModes[mode] << value; + break; + + case Network::B_CHANMODE: + _B_channelModes[mode] = value; + break; + + case Network::C_CHANMODE: + _C_channelModes[mode] = value; + break; + + case Network::D_CHANMODE: + _D_channelModes << mode; + break; + } + SYNC(ARG(mode), ARG(value)) +} + + +void IrcChannel::removeChannelMode(const QChar &mode, const QString &value) +{ + Network::ChannelModeType modeType = network()->channelModeType(mode); + + switch (modeType) { + case Network::NOT_A_CHANMODE: + return; + case Network::A_CHANMODE: + if (_A_channelModes.contains(mode)) + _A_channelModes[mode].removeAll(value); + break; + + case Network::B_CHANMODE: + _B_channelModes.remove(mode); + break; + + case Network::C_CHANMODE: + _C_channelModes.remove(mode); + break; + + case Network::D_CHANMODE: + _D_channelModes.remove(mode); + break; + } + SYNC(ARG(mode), ARG(value)) +} + + +bool IrcChannel::hasMode(const QChar &mode) const +{ + Network::ChannelModeType modeType = network()->channelModeType(mode); + + switch (modeType) { + case Network::NOT_A_CHANMODE: + return false; + case Network::A_CHANMODE: + return _A_channelModes.contains(mode); + case Network::B_CHANMODE: + return _B_channelModes.contains(mode); + case Network::C_CHANMODE: + return _C_channelModes.contains(mode); + case Network::D_CHANMODE: + return _D_channelModes.contains(mode); + default: + return false; + } +} + + +QString IrcChannel::modeValue(const QChar &mode) const +{ + Network::ChannelModeType modeType = network()->channelModeType(mode); + + switch (modeType) { + case Network::B_CHANMODE: + if (_B_channelModes.contains(mode)) + return _B_channelModes[mode]; + else + return QString(); + case Network::C_CHANMODE: + if (_C_channelModes.contains(mode)) + return _C_channelModes[mode]; + else + return QString(); + default: + return QString(); + } +} + + +QStringList IrcChannel::modeValueList(const QChar &mode) const +{ + Network::ChannelModeType modeType = network()->channelModeType(mode); + + switch (modeType) { + case Network::A_CHANMODE: + if (_A_channelModes.contains(mode)) + return _A_channelModes[mode]; + default: + return QStringList(); + } +} + + +QString IrcChannel::channelModeString() const +{ + QStringList params; + QString modeString; + + QSet::const_iterator D_iter = _D_channelModes.constBegin(); + while (D_iter != _D_channelModes.constEnd()) { + modeString += *D_iter; + D_iter++; + } + + QHash::const_iterator BC_iter = _C_channelModes.constBegin(); + while (BC_iter != _C_channelModes.constEnd()) { + modeString += BC_iter.key(); + params << BC_iter.value(); + BC_iter++; + } + + BC_iter = _B_channelModes.constBegin(); + while (BC_iter != _B_channelModes.constEnd()) { + modeString += BC_iter.key(); + params << BC_iter.value(); + BC_iter++; + } + if (modeString.isEmpty()) + return modeString; else - return QString(); - default: - return QString(); - } - -} - -QStringList IrcChannel::modeValueList(const QChar &mode) const { - Network::ChannelModeType modeType = network()->channelModeType(mode); - - switch(modeType) { - case Network::A_CHANMODE: - if(_A_channelModes.contains(mode)) - return _A_channelModes[mode]; - default: - return QStringList(); - } -} - -QString IrcChannel::channelModeString() const { - QStringList params; - QString modeString; - - QSet::const_iterator D_iter = _D_channelModes.constBegin(); - while(D_iter != _D_channelModes.constEnd()) { - modeString += *D_iter; - D_iter++; - } - - QHash::const_iterator BC_iter = _C_channelModes.constBegin(); - while(BC_iter != _C_channelModes.constEnd()) { - modeString += BC_iter.key(); - params << BC_iter.value(); - BC_iter++; - } - - BC_iter = _B_channelModes.constBegin(); - while(BC_iter != _B_channelModes.constEnd()) { - modeString += BC_iter.key(); - params << BC_iter.value(); - BC_iter++; - } - if(modeString.isEmpty()) - return modeString; - else - return QString("+%1 %2").arg(modeString).arg(params.join(" ")); + return QString("+%1 %2").arg(modeString).arg(params.join(" ")); } diff --git a/src/common/ircchannel.h b/src/common/ircchannel.h index 564eda89..200859cb 100644 --- a/src/common/ircchannel.h +++ b/src/common/ircchannel.h @@ -32,79 +32,80 @@ class IrcUser; class Network; -class IrcChannel : public SyncableObject { - SYNCABLE_OBJECT - Q_OBJECT +class IrcChannel : public SyncableObject +{ + SYNCABLE_OBJECT + Q_OBJECT - Q_PROPERTY(QString name READ name STORED false) - Q_PROPERTY(QString topic READ topic WRITE setTopic STORED false) - Q_PROPERTY(QString password READ password WRITE setPassword STORED false) + Q_PROPERTY(QString name READ name STORED false) + Q_PROPERTY(QString topic READ topic WRITE setTopic STORED false) + Q_PROPERTY(QString password READ password WRITE setPassword STORED false) -public: - IrcChannel(const QString &channelname, Network *network); - ~IrcChannel(); +public : + IrcChannel(const QString &channelname, Network *network); + ~IrcChannel(); - bool isKnownUser(IrcUser *ircuser) const; - bool isValidChannelUserMode(const QString &mode) const; + bool isKnownUser(IrcUser *ircuser) const; + bool isValidChannelUserMode(const QString &mode) const; - inline QString name() const { return _name; } - inline QString topic() const { return _topic; } - inline QString password() const { return _password; } - inline Network *network() const { return _network; } + inline QString name() const { return _name; } + inline QString topic() const { return _topic; } + inline QString password() const { return _password; } + inline Network *network() const { return _network; } - inline QList ircUsers() const { return _userModes.keys(); } + inline QList ircUsers() const { return _userModes.keys(); } - QString userModes(IrcUser *ircuser) const; - QString userModes(const QString &nick) const; + QString userModes(IrcUser *ircuser) const; + QString userModes(const QString &nick) const; - bool hasMode(const QChar &mode) const; - QString modeValue(const QChar &mode) const; - QStringList modeValueList(const QChar &mode) const; - QString channelModeString() const; + bool hasMode(const QChar &mode) const; + QString modeValue(const QChar &mode) const; + QStringList modeValueList(const QChar &mode) const; + QString channelModeString() const; - inline QTextCodec *codecForEncoding() const { return _codecForEncoding; } - inline QTextCodec *codecForDecoding() const { return _codecForDecoding; } - void setCodecForEncoding(const QString &codecName); - void setCodecForEncoding(QTextCodec *codec); - void setCodecForDecoding(const QString &codecName); - void setCodecForDecoding(QTextCodec *codec); + inline QTextCodec *codecForEncoding() const { return _codecForEncoding; } + inline QTextCodec *codecForDecoding() const { return _codecForDecoding; } + void setCodecForEncoding(const QString &codecName); + void setCodecForEncoding(QTextCodec *codec); + void setCodecForDecoding(const QString &codecName); + void setCodecForDecoding(QTextCodec *codec); - QString decodeString(const QByteArray &text) const; - QByteArray encodeString(const QString &string) const; + QString decodeString(const QByteArray &text) const; + QByteArray encodeString(const QString &string) const; public slots: - void setTopic(const QString &topic); - void setPassword(const QString &password); + void setTopic(const QString &topic); + void setPassword(const QString &password); - void joinIrcUsers(const QList &users, const QStringList &modes); - void joinIrcUsers(const QStringList &nicks, const QStringList &modes); - void joinIrcUser(IrcUser *ircuser); + void joinIrcUsers(const QList &users, const QStringList &modes); + void joinIrcUsers(const QStringList &nicks, const QStringList &modes); + void joinIrcUser(IrcUser *ircuser); - void part(IrcUser *ircuser); - void part(const QString &nick); + void part(IrcUser *ircuser); + void part(const QString &nick); - void setUserModes(IrcUser *ircuser, const QString &modes); - void setUserModes(const QString &nick, const QString &modes); + void setUserModes(IrcUser *ircuser, const QString &modes); + void setUserModes(const QString &nick, const QString &modes); - void addUserMode(IrcUser *ircuser, const QString &mode); - void addUserMode(const QString &nick, const QString &mode); + void addUserMode(IrcUser *ircuser, const QString &mode); + void addUserMode(const QString &nick, const QString &mode); - void removeUserMode(IrcUser *ircuser, const QString &mode); - void removeUserMode(const QString &nick, const QString &mode); + void removeUserMode(IrcUser *ircuser, const QString &mode); + void removeUserMode(const QString &nick, const QString &mode); - void addChannelMode(const QChar &mode, const QString &value); - void removeChannelMode(const QChar &mode, const QString &value); + void addChannelMode(const QChar &mode, const QString &value); + void removeChannelMode(const QChar &mode, const QString &value); - // init geters - QVariantMap initUserModes() const; - QVariantMap initChanModes() const; + // init geters + QVariantMap initUserModes() const; + QVariantMap initChanModes() const; - // init seters - void initSetUserModes(const QVariantMap &usermodes); - void initSetChanModes(const QVariantMap &chanModes); + // init seters + void initSetUserModes(const QVariantMap &usermodes); + void initSetChanModes(const QVariantMap &chanModes); signals: - void topicSet(const QString &topic); // needed by NetworkModel + void topicSet(const QString &topic); // needed by NetworkModel // void passwordSet(const QString &password); // void userModesSet(QString nick, QString modes); // void userModeAdded(QString nick, QString mode); @@ -112,37 +113,38 @@ signals: // void channelModeAdded(const QChar &mode, const QString &value); // void channelModeRemoved(const QChar &mode, const QString &value); - void ircUsersJoined(QList ircusers); + void ircUsersJoined(QList ircusers); // void ircUsersJoined(QStringList nicks, QStringList modes); - void ircUserParted(IrcUser *ircuser); - void ircUserNickSet(IrcUser *ircuser, QString nick); - void ircUserModeAdded(IrcUser *ircuser, QString mode); - void ircUserModeRemoved(IrcUser *ircuser, QString mode); - void ircUserModesSet(IrcUser *ircuser, QString modes); + void ircUserParted(IrcUser *ircuser); + void ircUserNickSet(IrcUser *ircuser, QString nick); + void ircUserModeAdded(IrcUser *ircuser, QString mode); + void ircUserModeRemoved(IrcUser *ircuser, QString mode); + void ircUserModesSet(IrcUser *ircuser, QString modes); - void parted(); // convenience signal emitted before channels destruction + void parted(); // convenience signal emitted before channels destruction private slots: - void ircUserDestroyed(); - void ircUserNickSet(QString nick); + void ircUserDestroyed(); + void ircUserNickSet(QString nick); private: - bool _initialized; - QString _name; - QString _topic; - QString _password; + bool _initialized; + QString _name; + QString _topic; + QString _password; - QHash _userModes; + QHash _userModes; - Network *_network; + Network *_network; - QTextCodec *_codecForEncoding; - QTextCodec *_codecForDecoding; + QTextCodec *_codecForEncoding; + QTextCodec *_codecForDecoding; - QHash _A_channelModes; - QHash _B_channelModes; - QHash _C_channelModes; - QSet _D_channelModes; + QHash _A_channelModes; + QHash _B_channelModes; + QHash _C_channelModes; + QSet _D_channelModes; }; + #endif diff --git a/src/common/ircevent.cpp b/src/common/ircevent.cpp index b9f7e45b..fe0ece5f 100644 --- a/src/common/ircevent.cpp +++ b/src/common/ircevent.cpp @@ -20,62 +20,66 @@ #include "ircevent.h" -Event *IrcEvent::create(EventManager::EventType type, QVariantMap &map, Network *network) { - if((type & EventManager::IrcEventNumericMask) == EventManager::IrcEventNumeric) - return new IrcEventNumeric(type, map, network); +Event *IrcEvent::create(EventManager::EventType type, QVariantMap &map, Network *network) +{ + if ((type & EventManager::IrcEventNumericMask) == EventManager::IrcEventNumeric) + return new IrcEventNumeric(type, map, network); - if((type & EventManager::EventGroupMask) != EventManager::IrcEvent) - return 0; + if ((type & EventManager::EventGroupMask) != EventManager::IrcEvent) + return 0; - switch(type) { - case EventManager::IrcEventRawPrivmsg: - case EventManager::IrcEventRawNotice: - return new IrcEventRawMessage(type, map, network); + switch (type) { + case EventManager::IrcEventRawPrivmsg: + case EventManager::IrcEventRawNotice: + return new IrcEventRawMessage(type, map, network); - default: - return new IrcEvent(type, map, network); - } + default: + return new IrcEvent(type, map, network); + } } IrcEvent::IrcEvent(EventManager::EventType type, QVariantMap &map, Network *network) - : NetworkEvent(type, map, network) + : NetworkEvent(type, map, network) { - _prefix = map.take("prefix").toString(); - _params = map.take("params").toStringList(); + _prefix = map.take("prefix").toString(); + _params = map.take("params").toStringList(); } -void IrcEvent::toVariantMap(QVariantMap &map) const { - NetworkEvent::toVariantMap(map); - map["prefix"] = prefix(); - map["params"] = params(); +void IrcEvent::toVariantMap(QVariantMap &map) const +{ + NetworkEvent::toVariantMap(map); + map["prefix"] = prefix(); + map["params"] = params(); } IrcEventNumeric::IrcEventNumeric(EventManager::EventType type, QVariantMap &map, Network *network) - : IrcEvent(type, map, network) + : IrcEvent(type, map, network) { - _number = map.take("number").toUInt(); - _target = map.take("target").toString(); + _number = map.take("number").toUInt(); + _target = map.take("target").toString(); } -void IrcEventNumeric::toVariantMap(QVariantMap &map) const { - IrcEvent::toVariantMap(map); - map["number"] = number(); - map["target"] = target(); +void IrcEventNumeric::toVariantMap(QVariantMap &map) const +{ + IrcEvent::toVariantMap(map); + map["number"] = number(); + map["target"] = target(); } IrcEventRawMessage::IrcEventRawMessage(EventManager::EventType type, QVariantMap &map, Network *network) - : IrcEvent(type, map, network) + : IrcEvent(type, map, network) { - _rawMessage = map.take("rawMessage").toByteArray(); + _rawMessage = map.take("rawMessage").toByteArray(); } -void IrcEventRawMessage::toVariantMap(QVariantMap &map) const { - IrcEvent::toVariantMap(map); - map["rawMessage"] = rawMessage(); +void IrcEventRawMessage::toVariantMap(QVariantMap &map) const +{ + IrcEvent::toVariantMap(map); + map["rawMessage"] = rawMessage(); } diff --git a/src/common/ircevent.h b/src/common/ircevent.h index 71e4ad28..317f4856 100644 --- a/src/common/ircevent.h +++ b/src/common/ircevent.h @@ -24,108 +24,119 @@ #include "networkevent.h" #include "util.h" -class IrcEvent : public NetworkEvent { +class IrcEvent : public NetworkEvent +{ public: - explicit IrcEvent(EventManager::EventType type, Network *network, const QString &prefix, const QStringList ¶ms = QStringList()) - : NetworkEvent(type, network), - _prefix(prefix), - _params(params) - {} + explicit IrcEvent(EventManager::EventType type, Network *network, const QString &prefix, const QStringList ¶ms = QStringList()) + : NetworkEvent(type, network), + _prefix(prefix), + _params(params) + {} - inline QString prefix() const { return _prefix; } - inline void setPrefix(const QString &prefix) { _prefix = prefix; } + inline QString prefix() const { return _prefix; } + inline void setPrefix(const QString &prefix) { _prefix = prefix; } - inline QString nick() const { return nickFromMask(prefix()); } + inline QString nick() const { return nickFromMask(prefix()); } - inline QStringList params() const { return _params; } - inline void setParams(const QStringList ¶ms) { _params = params; } + inline QStringList params() const { return _params; } + inline void setParams(const QStringList ¶ms) { _params = params; } - static Event *create(EventManager::EventType type, QVariantMap &map, Network *network); + static Event *create(EventManager::EventType type, QVariantMap &map, Network *network); protected: - explicit IrcEvent(EventManager::EventType type, QVariantMap &map, Network *network); - void toVariantMap(QVariantMap &map) const; + explicit IrcEvent(EventManager::EventType type, QVariantMap &map, Network *network); + void toVariantMap(QVariantMap &map) const; - virtual inline QString className() const { return "IrcEvent"; } - virtual inline void debugInfo(QDebug &dbg) const { - NetworkEvent::debugInfo(dbg); - dbg << ", prefix = " << qPrintable(prefix()) - << ", params = " << params(); - } + virtual inline QString className() const { return "IrcEvent"; } + virtual inline void debugInfo(QDebug &dbg) const + { + NetworkEvent::debugInfo(dbg); + dbg << ", prefix = " << qPrintable(prefix()) + << ", params = " << params(); + } -private: - QString _prefix; - QStringList _params; +private: + QString _prefix; + QStringList _params; }; -class IrcEventNumeric : public IrcEvent { + +class IrcEventNumeric : public IrcEvent +{ public: - explicit IrcEventNumeric(uint number, Network *network, const QString &prefix, const QString &target, const QStringList ¶ms = QStringList()) - : IrcEvent(EventManager::IrcEventNumeric, network, prefix, params), - _number(number), - _target(target) - {} + explicit IrcEventNumeric(uint number, Network *network, const QString &prefix, const QString &target, const QStringList ¶ms = QStringList()) + : IrcEvent(EventManager::IrcEventNumeric, network, prefix, params), + _number(number), + _target(target) + {} - inline uint number() const { return _number; } + inline uint number() const { return _number; } - inline QString target() const { return _target; } - inline void setTarget(const QString &target) { _target = target; } + inline QString target() const { return _target; } + inline void setTarget(const QString &target) { _target = target; } protected: - explicit IrcEventNumeric(EventManager::EventType type, QVariantMap &map, Network *network); - void toVariantMap(QVariantMap &map) const; - - virtual inline QString className() const { return "IrcEventNumeric"; } - virtual inline void debugInfo(QDebug &dbg) const { - dbg << ", num = " << number(); - NetworkEvent::debugInfo(dbg); - dbg << ", target = " << qPrintable(target()) - << ", prefix = " << qPrintable(prefix()) - << ", params = " << params(); - } + explicit IrcEventNumeric(EventManager::EventType type, QVariantMap &map, Network *network); + void toVariantMap(QVariantMap &map) const; + + virtual inline QString className() const { return "IrcEventNumeric"; } + virtual inline void debugInfo(QDebug &dbg) const + { + dbg << ", num = " << number(); + NetworkEvent::debugInfo(dbg); + dbg << ", target = " << qPrintable(target()) + << ", prefix = " << qPrintable(prefix()) + << ", params = " << params(); + } + private: - uint _number; - QString _target; + uint _number; + QString _target; - friend class IrcEvent; + friend class IrcEvent; }; -class IrcEventRawMessage : public IrcEvent { + +class IrcEventRawMessage : public IrcEvent +{ public: - explicit inline IrcEventRawMessage(EventManager::EventType type, Network *network, - const QByteArray &rawMessage, const QString &prefix, const QString &target, - const QDateTime ×tamp = QDateTime()) - : IrcEvent(type, network, prefix, QStringList() << target), - _rawMessage(rawMessage) - { - setTimestamp(timestamp); - } + explicit inline IrcEventRawMessage(EventManager::EventType type, Network *network, + const QByteArray &rawMessage, const QString &prefix, const QString &target, + const QDateTime ×tamp = QDateTime()) + : IrcEvent(type, network, prefix, QStringList() << target), + _rawMessage(rawMessage) + { + setTimestamp(timestamp); + } - inline QString target() const { return params().at(0); } - inline void setTarget(const QString &target) { setParams(QStringList() << target); } - inline QByteArray rawMessage() const { return _rawMessage; } - inline void setRawMessage(const QByteArray &rawMessage) { _rawMessage = rawMessage; } + inline QString target() const { return params().at(0); } + inline void setTarget(const QString &target) { setParams(QStringList() << target); } + + inline QByteArray rawMessage() const { return _rawMessage; } + inline void setRawMessage(const QByteArray &rawMessage) { _rawMessage = rawMessage; } protected: - explicit IrcEventRawMessage(EventManager::EventType type, QVariantMap &map, Network *network); - void toVariantMap(QVariantMap &map) const; + explicit IrcEventRawMessage(EventManager::EventType type, QVariantMap &map, Network *network); + void toVariantMap(QVariantMap &map) const; - virtual inline QString className() const { return "IrcEventRawMessage"; } - virtual inline void debugInfo(QDebug &dbg) const { - NetworkEvent::debugInfo(dbg); - dbg << ", target = " << qPrintable(target()) - << ", prefix = " << qPrintable(prefix()) - << ", msg = " << rawMessage(); - } + virtual inline QString className() const { return "IrcEventRawMessage"; } + virtual inline void debugInfo(QDebug &dbg) const + { + NetworkEvent::debugInfo(dbg); + dbg << ", target = " << qPrintable(target()) + << ", prefix = " << qPrintable(prefix()) + << ", msg = " << rawMessage(); + } private: - QByteArray _rawMessage; + QByteArray _rawMessage; - friend class IrcEvent; + friend class IrcEvent; }; + #endif diff --git a/src/common/irclisthelper.h b/src/common/irclisthelper.h index 72c37126..c6f5943e 100644 --- a/src/common/irclisthelper.h +++ b/src/common/irclisthelper.h @@ -32,25 +32,26 @@ * when RPL_LISTEND is received the clients will be informed, that they can pull the data * 3.) client pulls the data by calling requestChannelList again. receiving the data in receiveChannelList */ -class IrcListHelper : public SyncableObject { - SYNCABLE_OBJECT - Q_OBJECT +class IrcListHelper : public SyncableObject +{ + SYNCABLE_OBJECT + Q_OBJECT public: - inline IrcListHelper(QObject *parent = 0) : SyncableObject(parent) { setInitialized(); }; + inline IrcListHelper(QObject *parent = 0) : SyncableObject(parent) { setInitialized(); }; - struct ChannelDescription { - QString channelName; - quint32 userCount; - QString topic; - ChannelDescription(const QString &channelName_, quint32 userCount_, const QString &topic_) : channelName(channelName_), userCount(userCount_), topic(topic_) {}; - }; + struct ChannelDescription { + QString channelName; + quint32 userCount; + QString topic; + ChannelDescription(const QString &channelName_, quint32 userCount_, const QString &topic_) : channelName(channelName_), userCount(userCount_), topic(topic_) {}; + }; public slots: - inline virtual QVariantList requestChannelList(const NetworkId &netId, const QStringList &channelFilters) { REQUEST(ARG(netId), ARG(channelFilters)); return QVariantList(); } - inline virtual void receiveChannelList(const NetworkId &, const QStringList &, const QVariantList &) {}; - inline virtual void reportFinishedList(const NetworkId &netId) { SYNC(ARG(netId)) } - inline virtual void reportError(const QString &error) { SYNC(ARG(error)) } + inline virtual QVariantList requestChannelList(const NetworkId &netId, const QStringList &channelFilters) { REQUEST(ARG(netId), ARG(channelFilters)); return QVariantList(); } + inline virtual void receiveChannelList(const NetworkId &, const QStringList &, const QVariantList &) {}; + inline virtual void reportFinishedList(const NetworkId &netId) { SYNC(ARG(netId)) } + inline virtual void reportError(const QString &error) { SYNC(ARG(error)) } }; diff --git a/src/common/ircuser.cpp b/src/common/ircuser.cpp index 95892c49..9e792ba9 100644 --- a/src/common/ircuser.cpp +++ b/src/common/ircuser.cpp @@ -46,268 +46,339 @@ IrcUser::IrcUser(const QString &hostmask, Network *network) : SyncableObject(net _codecForEncoding(0), _codecForDecoding(0) { - updateObjectName(); - + updateObjectName(); } -IrcUser::~IrcUser() { + +IrcUser::~IrcUser() +{ } + // ==================== // PUBLIC: // ==================== -QString IrcUser::hostmask() const { - return QString("%1!%2@%3").arg(nick()).arg(user()).arg(host()); +QString IrcUser::hostmask() const +{ + return QString("%1!%2@%3").arg(nick()).arg(user()).arg(host()); } -QDateTime IrcUser::idleTime() { - if(QDateTime::currentDateTime().toTime_t() - _idleTimeSet.toTime_t() > 1200) - _idleTime = QDateTime(); - return _idleTime; + +QDateTime IrcUser::idleTime() +{ + if (QDateTime::currentDateTime().toTime_t() - _idleTimeSet.toTime_t() > 1200) + _idleTime = QDateTime(); + return _idleTime; } -QStringList IrcUser::channels() const { - QStringList chanList; - IrcChannel *channel; - foreach(channel, _channels) { - chanList << channel->name(); - } - return chanList; + +QStringList IrcUser::channels() const +{ + QStringList chanList; + IrcChannel *channel; + foreach(channel, _channels) { + chanList << channel->name(); + } + return chanList; } -void IrcUser::setCodecForEncoding(const QString &name) { - setCodecForEncoding(QTextCodec::codecForName(name.toAscii())); +void IrcUser::setCodecForEncoding(const QString &name) +{ + setCodecForEncoding(QTextCodec::codecForName(name.toAscii())); } -void IrcUser::setCodecForEncoding(QTextCodec *codec) { - _codecForEncoding = codec; + +void IrcUser::setCodecForEncoding(QTextCodec *codec) +{ + _codecForEncoding = codec; } -void IrcUser::setCodecForDecoding(const QString &name) { - setCodecForDecoding(QTextCodec::codecForName(name.toAscii())); + +void IrcUser::setCodecForDecoding(const QString &name) +{ + setCodecForDecoding(QTextCodec::codecForName(name.toAscii())); } -void IrcUser::setCodecForDecoding(QTextCodec *codec) { - _codecForDecoding = codec; + +void IrcUser::setCodecForDecoding(QTextCodec *codec) +{ + _codecForDecoding = codec; } -QString IrcUser::decodeString(const QByteArray &text) const { - if(!codecForDecoding()) return network()->decodeString(text); - return ::decodeString(text, codecForDecoding()); + +QString IrcUser::decodeString(const QByteArray &text) const +{ + if (!codecForDecoding()) return network()->decodeString(text); + return ::decodeString(text, codecForDecoding()); } -QByteArray IrcUser::encodeString(const QString &string) const { - if(codecForEncoding()) { - return codecForEncoding()->fromUnicode(string); - } - return network()->encodeString(string); + +QByteArray IrcUser::encodeString(const QString &string) const +{ + if (codecForEncoding()) { + return codecForEncoding()->fromUnicode(string); + } + return network()->encodeString(string); } + // ==================== // PUBLIC SLOTS: // ==================== -void IrcUser::setUser(const QString &user) { - if(!user.isEmpty() && _user != user) { - _user = user; - SYNC(ARG(user)); - } +void IrcUser::setUser(const QString &user) +{ + if (!user.isEmpty() && _user != user) { + _user = user; + SYNC(ARG(user)); + } } -void IrcUser::setRealName(const QString &realName) { - if (!realName.isEmpty() && _realName != realName) { - _realName = realName; - SYNC(ARG(realName)) - } + +void IrcUser::setRealName(const QString &realName) +{ + if (!realName.isEmpty() && _realName != realName) { + _realName = realName; + SYNC(ARG(realName)) + } } -void IrcUser::setAway(const bool &away) { - if(away != _away) { - _away = away; - SYNC(ARG(away)) - emit awaySet(away); - } + +void IrcUser::setAway(const bool &away) +{ + if (away != _away) { + _away = away; + SYNC(ARG(away)) + emit awaySet(away); + } } -void IrcUser::setAwayMessage(const QString &awayMessage) { - if(!awayMessage.isEmpty() && _awayMessage != awayMessage) { - _awayMessage = awayMessage; - SYNC(ARG(awayMessage)) - } + +void IrcUser::setAwayMessage(const QString &awayMessage) +{ + if (!awayMessage.isEmpty() && _awayMessage != awayMessage) { + _awayMessage = awayMessage; + SYNC(ARG(awayMessage)) + } } -void IrcUser::setIdleTime(const QDateTime &idleTime) { - if(idleTime.isValid() && _idleTime != idleTime) { - _idleTime = idleTime; - _idleTimeSet = QDateTime::currentDateTime(); - SYNC(ARG(idleTime)) - } + +void IrcUser::setIdleTime(const QDateTime &idleTime) +{ + if (idleTime.isValid() && _idleTime != idleTime) { + _idleTime = idleTime; + _idleTimeSet = QDateTime::currentDateTime(); + SYNC(ARG(idleTime)) + } } -void IrcUser::setLoginTime(const QDateTime &loginTime) { - if(loginTime.isValid() && _loginTime != loginTime) { - _loginTime = loginTime; - SYNC(ARG(loginTime)) - } + +void IrcUser::setLoginTime(const QDateTime &loginTime) +{ + if (loginTime.isValid() && _loginTime != loginTime) { + _loginTime = loginTime; + SYNC(ARG(loginTime)) + } } -void IrcUser::setServer(const QString &server) { - if(!server.isEmpty() && _server != server) { - _server = server; - SYNC(ARG(server)) - } + +void IrcUser::setServer(const QString &server) +{ + if (!server.isEmpty() && _server != server) { + _server = server; + SYNC(ARG(server)) + } } -void IrcUser::setIrcOperator(const QString &ircOperator) { - if(!ircOperator.isEmpty() && _ircOperator != ircOperator) { - _ircOperator = ircOperator; - SYNC(ARG(ircOperator)) - } + +void IrcUser::setIrcOperator(const QString &ircOperator) +{ + if (!ircOperator.isEmpty() && _ircOperator != ircOperator) { + _ircOperator = ircOperator; + SYNC(ARG(ircOperator)) + } } -void IrcUser::setLastAwayMessage(const int &lastAwayMessage) { - if(lastAwayMessage > _lastAwayMessage) { - _lastAwayMessage = lastAwayMessage; - SYNC(ARG(lastAwayMessage)) - } + +void IrcUser::setLastAwayMessage(const int &lastAwayMessage) +{ + if (lastAwayMessage > _lastAwayMessage) { + _lastAwayMessage = lastAwayMessage; + SYNC(ARG(lastAwayMessage)) + } } -void IrcUser::setHost(const QString &host) { - if(!host.isEmpty() && _host != host) { - _host = host; - SYNC(ARG(host)) - } + +void IrcUser::setHost(const QString &host) +{ + if (!host.isEmpty() && _host != host) { + _host = host; + SYNC(ARG(host)) + } } -void IrcUser::setNick(const QString &nick) { - if(!nick.isEmpty() && nick != _nick) { - _nick = nick; - updateObjectName(); - SYNC(ARG(nick)) - emit nickSet(nick); - } + +void IrcUser::setNick(const QString &nick) +{ + if (!nick.isEmpty() && nick != _nick) { + _nick = nick; + updateObjectName(); + SYNC(ARG(nick)) + emit nickSet(nick); + } } -void IrcUser::setWhoisServiceReply(const QString &whoisServiceReply) { - if(!whoisServiceReply.isEmpty() && whoisServiceReply != _whoisServiceReply) { - _whoisServiceReply = whoisServiceReply; - SYNC(ARG(whoisServiceReply)) - } + +void IrcUser::setWhoisServiceReply(const QString &whoisServiceReply) +{ + if (!whoisServiceReply.isEmpty() && whoisServiceReply != _whoisServiceReply) { + _whoisServiceReply = whoisServiceReply; + SYNC(ARG(whoisServiceReply)) + } } -void IrcUser::setSuserHost(const QString &suserHost) { - if(!suserHost.isEmpty() && suserHost != _suserHost) { - _suserHost = suserHost; - SYNC(ARG(suserHost)) - } + +void IrcUser::setSuserHost(const QString &suserHost) +{ + if (!suserHost.isEmpty() && suserHost != _suserHost) { + _suserHost = suserHost; + SYNC(ARG(suserHost)) + } } -void IrcUser::updateObjectName() { - renameObject(QString::number(network()->networkId().toInt()) + "/" + _nick); + +void IrcUser::updateObjectName() +{ + renameObject(QString::number(network()->networkId().toInt()) + "/" + _nick); } -void IrcUser::updateHostmask(const QString &mask) { - if(mask == hostmask()) - return; - QString user = userFromMask(mask); - QString host = hostFromMask(mask); - setUser(user); - setHost(host); +void IrcUser::updateHostmask(const QString &mask) +{ + if (mask == hostmask()) + return; + + QString user = userFromMask(mask); + QString host = hostFromMask(mask); + setUser(user); + setHost(host); } -void IrcUser::joinChannel(IrcChannel *channel) { - Q_ASSERT(channel); - if(!_channels.contains(channel)) { - _channels.insert(channel); - channel->joinIrcUser(this); - } + +void IrcUser::joinChannel(IrcChannel *channel) +{ + Q_ASSERT(channel); + if (!_channels.contains(channel)) { + _channels.insert(channel); + channel->joinIrcUser(this); + } } -void IrcUser::joinChannel(const QString &channelname) { - joinChannel(network()->newIrcChannel(channelname)); + +void IrcUser::joinChannel(const QString &channelname) +{ + joinChannel(network()->newIrcChannel(channelname)); } -void IrcUser::partChannel(IrcChannel *channel) { - if(_channels.contains(channel)) { - _channels.remove(channel); - disconnect(channel, 0, this, 0); - channel->part(this); - QString channelName = channel->name(); - SYNC_OTHER(partChannel, ARG(channelName)) - if(_channels.isEmpty() && !network()->isMe(this)) - quit(); - } + +void IrcUser::partChannel(IrcChannel *channel) +{ + if (_channels.contains(channel)) { + _channels.remove(channel); + disconnect(channel, 0, this, 0); + channel->part(this); + QString channelName = channel->name(); + SYNC_OTHER(partChannel, ARG(channelName)) + if (_channels.isEmpty() && !network()->isMe(this)) + quit(); + } } -void IrcUser::partChannel(const QString &channelname) { - IrcChannel *channel = network()->ircChannel(channelname); - if(channel == 0) { - qWarning() << "IrcUser::partChannel(): received part for unknown Channel" << channelname; - } else { - partChannel(channel); - } + +void IrcUser::partChannel(const QString &channelname) +{ + IrcChannel *channel = network()->ircChannel(channelname); + if (channel == 0) { + qWarning() << "IrcUser::partChannel(): received part for unknown Channel" << channelname; + } + else { + partChannel(channel); + } } -void IrcUser::quit() { - QList channels = _channels.toList(); - _channels.clear(); - foreach(IrcChannel *channel, channels) { - disconnect(channel, 0, this, 0); - channel->part(this); - } - network()->removeIrcUser(this); - SYNC(NO_ARG) - emit quited(); + +void IrcUser::quit() +{ + QList channels = _channels.toList(); + _channels.clear(); + foreach(IrcChannel *channel, channels) { + disconnect(channel, 0, this, 0); + channel->part(this); + } + network()->removeIrcUser(this); + SYNC(NO_ARG) + emit quited(); } -void IrcUser::channelDestroyed() { - // private slot! - IrcChannel *channel = static_cast(sender()); - if(_channels.contains(channel)) { - _channels.remove(channel); - if(_channels.isEmpty() && !network()->isMe(this)) - quit(); - } + +void IrcUser::channelDestroyed() +{ + // private slot! + IrcChannel *channel = static_cast(sender()); + if (_channels.contains(channel)) { + _channels.remove(channel); + if (_channels.isEmpty() && !network()->isMe(this)) + quit(); + } } -void IrcUser::setUserModes(const QString &modes) { - _userModes = modes; - SYNC(ARG(modes)) - emit userModesSet(modes); + +void IrcUser::setUserModes(const QString &modes) +{ + _userModes = modes; + SYNC(ARG(modes)) + emit userModesSet(modes); } -void IrcUser::addUserModes(const QString &modes) { - if(modes.isEmpty()) - return; - for(int i = 0; i < modes.count(); i++) { - if(!_userModes.contains(modes[i])) - _userModes += modes[i]; - } +void IrcUser::addUserModes(const QString &modes) +{ + if (modes.isEmpty()) + return; + + for (int i = 0; i < modes.count(); i++) { + if (!_userModes.contains(modes[i])) + _userModes += modes[i]; + } - SYNC(ARG(modes)) - emit userModesAdded(modes); + SYNC(ARG(modes)) + emit userModesAdded(modes); } -void IrcUser::removeUserModes(const QString &modes) { - if(modes.isEmpty()) - return; - for(int i = 0; i < modes.count(); i++) { - _userModes.remove(modes[i]); - } - SYNC(ARG(modes)) - emit userModesRemoved(modes); +void IrcUser::removeUserModes(const QString &modes) +{ + if (modes.isEmpty()) + return; + + for (int i = 0; i < modes.count(); i++) { + _userModes.remove(modes[i]); + } + SYNC(ARG(modes)) + emit userModesRemoved(modes); } -void IrcUser::setLastChannelActivity(BufferId buffer, const QDateTime &time) { - _lastActivity[buffer] = time; - emit lastChannelActivityUpdated(buffer, time); + +void IrcUser::setLastChannelActivity(BufferId buffer, const QDateTime &time) +{ + _lastActivity[buffer] = time; + emit lastChannelActivityUpdated(buffer, time); } -void IrcUser::setLastSpokenTo(BufferId buffer, const QDateTime &time) { - _lastSpokenTo[buffer] = time; - emit lastSpokenToUpdated(buffer, time); + +void IrcUser::setLastSpokenTo(BufferId buffer, const QDateTime &time) +{ + _lastSpokenTo[buffer] = time; + emit lastSpokenToUpdated(buffer, time); } diff --git a/src/common/ircuser.h b/src/common/ircuser.h index 7ec878e7..2be27583 100644 --- a/src/common/ircuser.h +++ b/src/common/ircuser.h @@ -34,101 +34,102 @@ class SignalProxy; class Network; class IrcChannel; -class IrcUser : public SyncableObject { - SYNCABLE_OBJECT - Q_OBJECT - - Q_PROPERTY(QString user READ user WRITE setUser STORED false) - Q_PROPERTY(QString host READ host WRITE setHost STORED false) - Q_PROPERTY(QString nick READ nick WRITE setNick STORED false) - Q_PROPERTY(QString realName READ realName WRITE setRealName STORED false) - Q_PROPERTY(bool away READ isAway WRITE setAway STORED false) - Q_PROPERTY(QString awayMessage READ awayMessage WRITE setAwayMessage STORED false) - Q_PROPERTY(QDateTime idleTime READ idleTime WRITE setIdleTime STORED false) - Q_PROPERTY(QDateTime loginTime READ loginTime WRITE setLoginTime STORED false) - Q_PROPERTY(QString server READ server WRITE setServer STORED false) - Q_PROPERTY(QString ircOperator READ ircOperator WRITE setIrcOperator STORED false) - Q_PROPERTY(int lastAwayMessage READ lastAwayMessage WRITE setLastAwayMessage STORED false) - Q_PROPERTY(QString whoisServiceReply READ whoisServiceReply WRITE setWhoisServiceReply STORED false) - Q_PROPERTY(QString suserHost READ suserHost WRITE setSuserHost STORED false) - - Q_PROPERTY(QStringList channels READ channels STORED false) - Q_PROPERTY(QString userModes READ userModes WRITE setUserModes) - -public: - IrcUser(const QString &hostmask, Network *network); - virtual ~IrcUser(); - - inline QString user() const { return _user; } - inline QString host() const { return _host; } - inline QString nick() const { return _nick; } - inline QString realName() const { return _realName; } - QString hostmask() const; - inline bool isAway() const { return _away; } - inline QString awayMessage() const { return _awayMessage; } - QDateTime idleTime(); - inline QDateTime loginTime() const { return _loginTime; } - inline QString server() const { return _server; } - inline QString ircOperator() const { return _ircOperator; } - inline int lastAwayMessage() const { return _lastAwayMessage; } - inline QString whoisServiceReply() const { return _whoisServiceReply; } - inline QString suserHost() const { return _suserHost; } - inline Network *network() const { return _network; } - - inline QString userModes() const { return _userModes; } - - QStringList channels() const; - - // user-specific encodings - inline QTextCodec *codecForEncoding() const { return _codecForEncoding; } - inline QTextCodec *codecForDecoding() const { return _codecForDecoding; } - void setCodecForEncoding(const QString &codecName); - void setCodecForEncoding(QTextCodec *codec); - void setCodecForDecoding(const QString &codecName); - void setCodecForDecoding(QTextCodec *codec); - - QString decodeString(const QByteArray &text) const; - QByteArray encodeString(const QString &string) const; - - // only valid on client side, these are not synced! - inline QDateTime lastChannelActivity(BufferId id) const { return _lastActivity.value(id); } - void setLastChannelActivity(BufferId id, const QDateTime &time); - inline QDateTime lastSpokenTo(BufferId id) const { return _lastSpokenTo.value(id); } - void setLastSpokenTo(BufferId id, const QDateTime &time); +class IrcUser : public SyncableObject +{ + SYNCABLE_OBJECT + Q_OBJECT + + Q_PROPERTY(QString user READ user WRITE setUser STORED false) + Q_PROPERTY(QString host READ host WRITE setHost STORED false) + Q_PROPERTY(QString nick READ nick WRITE setNick STORED false) + Q_PROPERTY(QString realName READ realName WRITE setRealName STORED false) + Q_PROPERTY(bool away READ isAway WRITE setAway STORED false) + Q_PROPERTY(QString awayMessage READ awayMessage WRITE setAwayMessage STORED false) + Q_PROPERTY(QDateTime idleTime READ idleTime WRITE setIdleTime STORED false) + Q_PROPERTY(QDateTime loginTime READ loginTime WRITE setLoginTime STORED false) + Q_PROPERTY(QString server READ server WRITE setServer STORED false) + Q_PROPERTY(QString ircOperator READ ircOperator WRITE setIrcOperator STORED false) + Q_PROPERTY(int lastAwayMessage READ lastAwayMessage WRITE setLastAwayMessage STORED false) + Q_PROPERTY(QString whoisServiceReply READ whoisServiceReply WRITE setWhoisServiceReply STORED false) + Q_PROPERTY(QString suserHost READ suserHost WRITE setSuserHost STORED false) + + Q_PROPERTY(QStringList channels READ channels STORED false) + Q_PROPERTY(QString userModes READ userModes WRITE setUserModes) + +public : + IrcUser(const QString &hostmask, Network *network); + virtual ~IrcUser(); + + inline QString user() const { return _user; } + inline QString host() const { return _host; } + inline QString nick() const { return _nick; } + inline QString realName() const { return _realName; } + QString hostmask() const; + inline bool isAway() const { return _away; } + inline QString awayMessage() const { return _awayMessage; } + QDateTime idleTime(); + inline QDateTime loginTime() const { return _loginTime; } + inline QString server() const { return _server; } + inline QString ircOperator() const { return _ircOperator; } + inline int lastAwayMessage() const { return _lastAwayMessage; } + inline QString whoisServiceReply() const { return _whoisServiceReply; } + inline QString suserHost() const { return _suserHost; } + inline Network *network() const { return _network; } + + inline QString userModes() const { return _userModes; } + + QStringList channels() const; + + // user-specific encodings + inline QTextCodec *codecForEncoding() const { return _codecForEncoding; } + inline QTextCodec *codecForDecoding() const { return _codecForDecoding; } + void setCodecForEncoding(const QString &codecName); + void setCodecForEncoding(QTextCodec *codec); + void setCodecForDecoding(const QString &codecName); + void setCodecForDecoding(QTextCodec *codec); + + QString decodeString(const QByteArray &text) const; + QByteArray encodeString(const QString &string) const; + + // only valid on client side, these are not synced! + inline QDateTime lastChannelActivity(BufferId id) const { return _lastActivity.value(id); } + void setLastChannelActivity(BufferId id, const QDateTime &time); + inline QDateTime lastSpokenTo(BufferId id) const { return _lastSpokenTo.value(id); } + void setLastSpokenTo(BufferId id, const QDateTime &time); public slots: - void setUser(const QString &user); - void setHost(const QString &host); - void setNick(const QString &nick); - void setRealName(const QString &realName); - void setAway(const bool &away); - void setAwayMessage(const QString &awayMessage); - void setIdleTime(const QDateTime &idleTime); - void setLoginTime(const QDateTime &loginTime); - void setServer(const QString &server); - void setIrcOperator(const QString &ircOperator); - void setLastAwayMessage(const int &lastAwayMessage); - void setWhoisServiceReply(const QString &whoisServiceReply); - void setSuserHost(const QString &suserHost); - void updateHostmask(const QString &mask); - - void setUserModes(const QString &modes); - - void joinChannel(IrcChannel *channel); - void joinChannel(const QString &channelname); - void partChannel(IrcChannel *channel); - void partChannel(const QString &channelname); - void quit(); - - void addUserModes(const QString &modes); - void removeUserModes(const QString &modes); + void setUser(const QString &user); + void setHost(const QString &host); + void setNick(const QString &nick); + void setRealName(const QString &realName); + void setAway(const bool &away); + void setAwayMessage(const QString &awayMessage); + void setIdleTime(const QDateTime &idleTime); + void setLoginTime(const QDateTime &loginTime); + void setServer(const QString &server); + void setIrcOperator(const QString &ircOperator); + void setLastAwayMessage(const int &lastAwayMessage); + void setWhoisServiceReply(const QString &whoisServiceReply); + void setSuserHost(const QString &suserHost); + void updateHostmask(const QString &mask); + + void setUserModes(const QString &modes); + + void joinChannel(IrcChannel *channel); + void joinChannel(const QString &channelname); + void partChannel(IrcChannel *channel); + void partChannel(const QString &channelname); + void quit(); + + void addUserModes(const QString &modes); + void removeUserModes(const QString &modes); signals: // void userSet(QString user); // void hostSet(QString host); - void nickSet(QString newnick); // needed in NetworkModel + void nickSet(QString newnick); // needed in NetworkModel // void realNameSet(QString realName); - void awaySet(bool away); // needed in NetworkModel + void awaySet(bool away); // needed in NetworkModel // void awayMessageSet(QString awayMessage); // void idleTimeSet(QDateTime idleTime); // void loginTimeSet(QDateTime loginTime); @@ -138,58 +139,63 @@ signals: // void whoisServiceReplySet(QString whoisServiceReply); // void suserHostSet(QString suserHost); - void userModesSet(QString modes); - void userModesAdded(QString modes); - void userModesRemoved(QString modes); + void userModesSet(QString modes); + void userModesAdded(QString modes); + void userModesRemoved(QString modes); - // void channelJoined(QString channel); - void channelParted(QString channel); - void quited(); + // void channelJoined(QString channel); + void channelParted(QString channel); + void quited(); - void lastChannelActivityUpdated(BufferId id, const QDateTime &newTime); - void lastSpokenToUpdated(BufferId id, const QDateTime &newTime); + void lastChannelActivityUpdated(BufferId id, const QDateTime &newTime); + void lastSpokenToUpdated(BufferId id, const QDateTime &newTime); private slots: - void updateObjectName(); - void channelDestroyed(); + void updateObjectName(); + void channelDestroyed(); private: - inline bool operator==(const IrcUser &ircuser2) { - return (_nick.toLower() == ircuser2.nick().toLower()); - } - - inline bool operator==(const QString &nickname) { - return (_nick.toLower() == nickname.toLower()); - } - - bool _initialized; - - QString _nick; - QString _user; - QString _host; - QString _realName; - QString _awayMessage; - bool _away; - QString _server; - QDateTime _idleTime; - QDateTime _idleTimeSet; - QDateTime _loginTime; - QString _ircOperator; - int _lastAwayMessage; - QString _whoisServiceReply; - QString _suserHost; - - // QSet _channels; - QSet _channels; - QString _userModes; - - Network *_network; - - QTextCodec *_codecForEncoding; - QTextCodec *_codecForDecoding; - - QHash _lastActivity; - QHash _lastSpokenTo; + inline bool operator==(const IrcUser &ircuser2) + { + return (_nick.toLower() == ircuser2.nick().toLower()); + } + + + inline bool operator==(const QString &nickname) + { + return (_nick.toLower() == nickname.toLower()); + } + + + bool _initialized; + + QString _nick; + QString _user; + QString _host; + QString _realName; + QString _awayMessage; + bool _away; + QString _server; + QDateTime _idleTime; + QDateTime _idleTimeSet; + QDateTime _loginTime; + QString _ircOperator; + int _lastAwayMessage; + QString _whoisServiceReply; + QString _suserHost; + + // QSet _channels; + QSet _channels; + QString _userModes; + + Network *_network; + + QTextCodec *_codecForEncoding; + QTextCodec *_codecForDecoding; + + QHash _lastActivity; + QHash _lastSpokenTo; }; + #endif diff --git a/src/common/logbacktrace_unix.cpp b/src/common/logbacktrace_unix.cpp index 2152c082..c34e90c4 100644 --- a/src/common/logbacktrace_unix.cpp +++ b/src/common/logbacktrace_unix.cpp @@ -30,65 +30,68 @@ # include #endif -void Quassel::logBacktrace(const QString &filename) { +void Quassel::logBacktrace(const QString &filename) +{ #ifndef BUILD_CRASHHANDLER - Q_UNUSED(filename) + Q_UNUSED(filename) #else - void* callstack[128]; - int i, frames = backtrace(callstack, 128); + void *callstack[128]; + int i, frames = backtrace(callstack, 128); - QFile dumpFile(filename); - dumpFile.open(QIODevice::Append); - QTextStream dumpStream(&dumpFile); + QFile dumpFile(filename); + dumpFile.open(QIODevice::Append); + QTextStream dumpStream(&dumpFile); - for (i = 0; i < frames; ++i) { - Dl_info info; - dladdr (callstack[i], &info); - // as a reference: - // typedef struct - // { - // __const char *dli_fname; /* File name of defining object. */ - // void *dli_fbase; /* Load address of that object. */ - // __const char *dli_sname; /* Name of nearest symbol. */ - // void *dli_saddr; /* Exact value of nearest symbol. */ - // } Dl_info; + for (i = 0; i < frames; ++i) { + Dl_info info; + dladdr(callstack[i], &info); + // as a reference: + // typedef struct + // { + // __const char *dli_fname; /* File name of defining object. */ + // void *dli_fbase; /* Load address of that object. */ + // __const char *dli_sname; /* Name of nearest symbol. */ + // void *dli_saddr; /* Exact value of nearest symbol. */ + // } Dl_info; #if __LP64__ - int addrSize = 16; + int addrSize = 16; #else - int addrSize = 8; + int addrSize = 8; #endif - QString funcName; - if(info.dli_sname) { - char *func = abi::__cxa_demangle(info.dli_sname, 0, 0, 0); - if(func) { - funcName = QString(func); - free(func); - } else { - funcName = QString(info.dli_sname); - } - } else { - funcName = QString("0x%1").arg((ulong)(info.dli_saddr), addrSize, 16, QLatin1Char('0')); - } + QString funcName; + if (info.dli_sname) { + char *func = abi::__cxa_demangle(info.dli_sname, 0, 0, 0); + if (func) { + funcName = QString(func); + free(func); + } + else { + funcName = QString(info.dli_sname); + } + } + else { + funcName = QString("0x%1").arg((ulong)(info.dli_saddr), addrSize, 16, QLatin1Char('0')); + } - // prettificating the filename - QString fileName("???"); - if(info.dli_fname) { - fileName = QString(info.dli_fname); - int slashPos = fileName.lastIndexOf('/'); - if(slashPos != -1) - fileName = fileName.mid(slashPos + 1); - } + // prettificating the filename + QString fileName("???"); + if (info.dli_fname) { + fileName = QString(info.dli_fname); + int slashPos = fileName.lastIndexOf('/'); + if (slashPos != -1) + fileName = fileName.mid(slashPos + 1); + } - QString debugLine = QString("#%1 %2 0x%3 %4").arg(i, 3, 10) - .arg(fileName, - 20) - .arg((ulong)(callstack[i]), addrSize, 16, QLatin1Char('0')) - .arg(funcName); + QString debugLine = QString("#%1 %2 0x%3 %4").arg(i, 3, 10) + .arg(fileName, -20) + .arg((ulong)(callstack[i]), addrSize, 16, QLatin1Char('0')) + .arg(funcName); - dumpStream << debugLine << "\n"; - qDebug() << qPrintable(debugLine); - } - dumpFile.close(); + dumpStream << debugLine << "\n"; + qDebug() << qPrintable(debugLine); + } + dumpFile.close(); #endif /* BUILD_CRASHHANDLER */ } diff --git a/src/common/logbacktrace_win.cpp b/src/common/logbacktrace_win.cpp index b12c15dc..06a6f80e 100644 --- a/src/common/logbacktrace_win.cpp +++ b/src/common/logbacktrace_win.cpp @@ -28,191 +28,197 @@ #include #include -void loadHelpStackFrame(IMAGEHLP_STACK_FRAME &ihsf, const STACKFRAME64 &stackFrame) { - ZeroMemory(&ihsf, sizeof(IMAGEHLP_STACK_FRAME)); - ihsf.InstructionOffset = stackFrame.AddrPC.Offset; - ihsf.FrameOffset = stackFrame.AddrFrame.Offset; +void loadHelpStackFrame(IMAGEHLP_STACK_FRAME &ihsf, const STACKFRAME64 &stackFrame) +{ + ZeroMemory(&ihsf, sizeof(IMAGEHLP_STACK_FRAME)); + ihsf.InstructionOffset = stackFrame.AddrPC.Offset; + ihsf.FrameOffset = stackFrame.AddrFrame.Offset; } -BOOL CALLBACK EnumSymbolsCB(PSYMBOL_INFO symInfo, ULONG size, PVOID user) { - QStringList *params = (QStringList *)user; - if(symInfo->Flags & SYMFLAG_PARAMETER) { - params->append(symInfo->Name); - } - return TRUE; + +BOOL CALLBACK EnumSymbolsCB(PSYMBOL_INFO symInfo, ULONG size, PVOID user) +{ + QStringList *params = (QStringList *)user; + if (symInfo->Flags & SYMFLAG_PARAMETER) { + params->append(symInfo->Name); + } + return TRUE; } struct EnumModulesContext { - HANDLE hProcess; - QTextStream &stream; - EnumModulesContext(HANDLE hProcess, QTextStream &stream) : hProcess(hProcess), stream(stream) {} + HANDLE hProcess; + QTextStream &stream; + EnumModulesContext(HANDLE hProcess, QTextStream &stream) : hProcess(hProcess), stream(stream) {} }; -BOOL CALLBACK EnumModulesCB(LPCSTR ModuleName, DWORD64 BaseOfDll, PVOID UserContext) { - IMAGEHLP_MODULE64 mod; - EnumModulesContext *context = (EnumModulesContext *)UserContext; - mod.SizeOfStruct = sizeof(IMAGEHLP_MODULE64); - if(SymGetModuleInfo64(context->hProcess, BaseOfDll, &mod)) { - QString line = QString("%1 0x%2 Image: %3").arg(mod.ModuleName, -14) - .arg(BaseOfDll, 8, 16, QLatin1Char('0')) - .arg(mod.LoadedImageName); - // qDebug() << qPrintable(line); - context->stream << line << '\n'; - - QString pdbName(mod.LoadedPdbName); - if(!pdbName.isEmpty()) { - QString line2 = QString("%1 %2").arg("", 32).arg(pdbName); - // qDebug() << qPrintable(line2); - context->stream << line2 << '\n'; +BOOL CALLBACK EnumModulesCB(LPCSTR ModuleName, DWORD64 BaseOfDll, PVOID UserContext) +{ + IMAGEHLP_MODULE64 mod; + EnumModulesContext *context = (EnumModulesContext *)UserContext; + mod.SizeOfStruct = sizeof(IMAGEHLP_MODULE64); + if (SymGetModuleInfo64(context->hProcess, BaseOfDll, &mod)) { + QString line = QString("%1 0x%2 Image: %3").arg(mod.ModuleName, -14) + .arg(BaseOfDll, 8, 16, QLatin1Char('0')) + .arg(mod.LoadedImageName); + // qDebug() << qPrintable(line); + context->stream << line << '\n'; + + QString pdbName(mod.LoadedPdbName); + if (!pdbName.isEmpty()) { + QString line2 = QString("%1 %2").arg("", 32).arg(pdbName); + // qDebug() << qPrintable(line2); + context->stream << line2 << '\n'; + } } - } - return TRUE; + return TRUE; } - -#if defined( _M_IX86 ) && defined(Q_CC_MSVC) - // Disable global optimization and ignore /GS waning caused by - // inline assembly. - // not needed with mingw cause we can tell mingw which registers we use +#if defined(_M_IX86) && defined(Q_CC_MSVC) +// Disable global optimization and ignore /GS waning caused by +// inline assembly. +// not needed with mingw cause we can tell mingw which registers we use #pragma optimize("g", off) #pragma warning(push) #pragma warning(disable : 4748) #endif -void Quassel::logBacktrace(const QString &filename) { - DWORD MachineType; - CONTEXT Context; - STACKFRAME64 StackFrame; +void Quassel::logBacktrace(const QString &filename) +{ + DWORD MachineType; + CONTEXT Context; + STACKFRAME64 StackFrame; #ifdef _M_IX86 ZeroMemory(&Context, sizeof(CONTEXT)); Context.ContextFlags = CONTEXT_CONTROL; - #ifdef __MINGW32__ - asm("Label:\n\t" - "movl %%ebp,%0;\n\t" - "movl %%esp,%1;\n\t" - "movl $Label,%%eax;\n\t" - "movl %%eax,%2;\n\t" - :"=r"(Context.Ebp),"=r"(Context.Esp),"=r"(Context.Eip) - ://no input - :"eax"); + asm ("Label:\n\t" + "movl %%ebp,%0;\n\t" + "movl %%esp,%1;\n\t" + "movl $Label,%%eax;\n\t" + "movl %%eax,%2;\n\t" + : "=r" (Context.Ebp), "=r" (Context.Esp), "=r" (Context.Eip) + : //no input + : "eax"); #else _asm { - Label: - mov [Context.Ebp], ebp; - mov [Context.Esp], esp; - mov eax, [Label]; - mov [Context.Eip], eax; +Label: + mov[Context.Ebp], ebp; + mov[Context.Esp], esp; + mov eax, [Label]; + mov[Context.Eip], eax; } #endif #else RtlCaptureContext(&Context); #endif - ZeroMemory(&StackFrame, sizeof(STACKFRAME64)); + ZeroMemory(&StackFrame, sizeof(STACKFRAME64)); #ifdef _M_IX86 - MachineType = IMAGE_FILE_MACHINE_I386; - StackFrame.AddrPC.Offset = Context.Eip; - StackFrame.AddrPC.Mode = AddrModeFlat; - StackFrame.AddrFrame.Offset = Context.Ebp; - StackFrame.AddrFrame.Mode = AddrModeFlat; - StackFrame.AddrStack.Offset = Context.Esp; - StackFrame.AddrStack.Mode = AddrModeFlat; + MachineType = IMAGE_FILE_MACHINE_I386; + StackFrame.AddrPC.Offset = Context.Eip; + StackFrame.AddrPC.Mode = AddrModeFlat; + StackFrame.AddrFrame.Offset = Context.Ebp; + StackFrame.AddrFrame.Mode = AddrModeFlat; + StackFrame.AddrStack.Offset = Context.Esp; + StackFrame.AddrStack.Mode = AddrModeFlat; #elif _M_X64 - MachineType = IMAGE_FILE_MACHINE_AMD64; - StackFrame.AddrPC.Offset = Context.Rip; - StackFrame.AddrPC.Mode = AddrModeFlat; - StackFrame.AddrFrame.Offset = Context.Rsp; - StackFrame.AddrFrame.Mode = AddrModeFlat; - StackFrame.AddrStack.Offset = Context.Rsp; - StackFrame.AddrStack.Mode = AddrModeFlat; + MachineType = IMAGE_FILE_MACHINE_AMD64; + StackFrame.AddrPC.Offset = Context.Rip; + StackFrame.AddrPC.Mode = AddrModeFlat; + StackFrame.AddrFrame.Offset = Context.Rsp; + StackFrame.AddrFrame.Mode = AddrModeFlat; + StackFrame.AddrStack.Offset = Context.Rsp; + StackFrame.AddrStack.Mode = AddrModeFlat; #elif _M_IA64 - MachineType = IMAGE_FILE_MACHINE_IA64; - StackFrame.AddrPC.Offset = Context.StIIP; - StackFrame.AddrPC.Mode = AddrModeFlat; - StackFrame.AddrFrame.Offset = Context.IntSp; - StackFrame.AddrFrame.Mode = AddrModeFlat; - StackFrame.AddrBStore.Offset= Context.RsBSP; - StackFrame.AddrBStore.Mode = AddrModeFlat; - StackFrame.AddrStack.Offset = Context.IntSp; - StackFrame.AddrStack.Mode = AddrModeFlat; + MachineType = IMAGE_FILE_MACHINE_IA64; + StackFrame.AddrPC.Offset = Context.StIIP; + StackFrame.AddrPC.Mode = AddrModeFlat; + StackFrame.AddrFrame.Offset = Context.IntSp; + StackFrame.AddrFrame.Mode = AddrModeFlat; + StackFrame.AddrBStore.Offset = Context.RsBSP; + StackFrame.AddrBStore.Mode = AddrModeFlat; + StackFrame.AddrStack.Offset = Context.IntSp; + StackFrame.AddrStack.Mode = AddrModeFlat; #else #error "Unsupported platform" #endif - //EnterCriticalSection(&DbgHelpLock); - - QFile logFile(filename); - logFile.open(QIODevice::Append); - QTextStream logStream(&logFile); - - HANDLE hProcess = GetCurrentProcess(); - HANDLE hThread = GetCurrentThread(); - SymInitialize(hProcess, NULL, TRUE); - - DWORD64 dwDisplacement; - - ULONG64 buffer[(sizeof(SYMBOL_INFO) + - MAX_SYM_NAME*sizeof(TCHAR) + - sizeof(ULONG64) - 1) / sizeof(ULONG64)]; - PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; - pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); - pSymbol->MaxNameLen = MAX_SYM_NAME; - - IMAGEHLP_MODULE64 mod; - mod.SizeOfStruct = sizeof(IMAGEHLP_MODULE64); - - IMAGEHLP_STACK_FRAME ihsf; - ZeroMemory(&ihsf, sizeof(IMAGEHLP_STACK_FRAME)); - - int i = 0; - while(StackWalk64(MachineType, hProcess, hThread, &StackFrame, &Context, NULL, NULL, NULL, NULL)) { - if(i == 128) - break; - - loadHelpStackFrame(ihsf, StackFrame); - if(StackFrame.AddrPC.Offset != 0) { // Valid frame. - - QString fileName("???"); - if(SymGetModuleInfo64(hProcess, ihsf.InstructionOffset, &mod)) { - fileName = QString(mod.ImageName); - int slashPos = fileName.lastIndexOf('\\'); - if(slashPos != -1) - fileName = fileName.mid(slashPos + 1); - } - QString funcName; - if(SymFromAddr(hProcess, ihsf.InstructionOffset, &dwDisplacement, pSymbol)) { - funcName = QString(pSymbol->Name); - } else { - funcName = QString("0x%1").arg(ihsf.InstructionOffset, 8, 16, QLatin1Char('0')); - } - QStringList params; - SymSetContext(hProcess, &ihsf, NULL); - SymEnumSymbols(hProcess, 0, NULL, EnumSymbolsCB, (PVOID)¶ms); - - QString debugLine = QString("#%1 %2 0x%3 %4(%5)").arg(i, 3, 10) - .arg(fileName, -20) - .arg(ihsf.InstructionOffset, 8, 16, QLatin1Char('0')) - .arg(funcName) - .arg(params.join(", ")); - // qDebug() << qPrintable(debugLine); - logStream << debugLine << '\n'; - i++; - } else { - break; // we're at the end. + //EnterCriticalSection(&DbgHelpLock); + + QFile logFile(filename); + logFile.open(QIODevice::Append); + QTextStream logStream(&logFile); + + HANDLE hProcess = GetCurrentProcess(); + HANDLE hThread = GetCurrentThread(); + SymInitialize(hProcess, NULL, TRUE); + + DWORD64 dwDisplacement; + + ULONG64 buffer[(sizeof(SYMBOL_INFO) + + MAX_SYM_NAME*sizeof(TCHAR) + + sizeof(ULONG64) - 1) / sizeof(ULONG64)]; + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; + pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); + pSymbol->MaxNameLen = MAX_SYM_NAME; + + IMAGEHLP_MODULE64 mod; + mod.SizeOfStruct = sizeof(IMAGEHLP_MODULE64); + + IMAGEHLP_STACK_FRAME ihsf; + ZeroMemory(&ihsf, sizeof(IMAGEHLP_STACK_FRAME)); + + int i = 0; + while (StackWalk64(MachineType, hProcess, hThread, &StackFrame, &Context, NULL, NULL, NULL, NULL)) { + if (i == 128) + break; + + loadHelpStackFrame(ihsf, StackFrame); + if (StackFrame.AddrPC.Offset != 0) { // Valid frame. + QString fileName("???"); + if (SymGetModuleInfo64(hProcess, ihsf.InstructionOffset, &mod)) { + fileName = QString(mod.ImageName); + int slashPos = fileName.lastIndexOf('\\'); + if (slashPos != -1) + fileName = fileName.mid(slashPos + 1); + } + QString funcName; + if (SymFromAddr(hProcess, ihsf.InstructionOffset, &dwDisplacement, pSymbol)) { + funcName = QString(pSymbol->Name); + } + else { + funcName = QString("0x%1").arg(ihsf.InstructionOffset, 8, 16, QLatin1Char('0')); + } + QStringList params; + SymSetContext(hProcess, &ihsf, NULL); + SymEnumSymbols(hProcess, 0, NULL, EnumSymbolsCB, (PVOID)¶ms); + + QString debugLine = QString("#%1 %2 0x%3 %4(%5)").arg(i, 3, 10) + .arg(fileName, -20) + .arg(ihsf.InstructionOffset, 8, 16, QLatin1Char('0')) + .arg(funcName) + .arg(params.join(", ")); + // qDebug() << qPrintable(debugLine); + logStream << debugLine << '\n'; + i++; + } + else { + break; // we're at the end. + } } - } - // qDebug() << "List of linked Modules:"; - logStream << "\n\nList of linked Modules:\n"; - EnumModulesContext modulesContext(hProcess, logStream); - SymEnumerateModules64(hProcess, EnumModulesCB, (PVOID)&modulesContext); + // qDebug() << "List of linked Modules:"; + logStream << "\n\nList of linked Modules:\n"; + EnumModulesContext modulesContext(hProcess, logStream); + SymEnumerateModules64(hProcess, EnumModulesCB, (PVOID)&modulesContext); - logFile.close(); + logFile.close(); } + + #if defined(_M_IX86) && defined(Q_CC_MSVC) #pragma warning(pop) #pragma optimize("g", on) diff --git a/src/common/logger.cpp b/src/common/logger.cpp index bf270f9d..5eb318f1 100644 --- a/src/common/logger.cpp +++ b/src/common/logger.cpp @@ -29,85 +29,89 @@ #include "logger.h" #include "quassel.h" -Logger::~Logger() { - log(); +Logger::~Logger() +{ + log(); } -void Logger::log() { - if(_logLevel < Quassel::logLevel()) - return; - switch(_logLevel) { - case Quassel::DebugLevel: - _buffer.prepend("Debug: "); - break; - case Quassel::InfoLevel: - _buffer.prepend("Info: "); - break; - case Quassel::WarningLevel: - _buffer.prepend("Warning: "); - break; - case Quassel::ErrorLevel: - _buffer.prepend("Error: "); - break; - default: - break; - } +void Logger::log() +{ + if (_logLevel < Quassel::logLevel()) + return; -#ifdef HAVE_SYSLOG - if(Quassel::logToSyslog()) { - int prio; - switch(_logLevel) { + switch (_logLevel) { case Quassel::DebugLevel: - prio = LOG_DEBUG; - break; + _buffer.prepend("Debug: "); + break; case Quassel::InfoLevel: - prio = LOG_INFO; - break; + _buffer.prepend("Info: "); + break; case Quassel::WarningLevel: - prio = LOG_WARNING; - break; + _buffer.prepend("Warning: "); + break; case Quassel::ErrorLevel: - prio = LOG_ERR; - break; + _buffer.prepend("Error: "); + break; default: - prio = LOG_INFO; - break; + break; + } + +#ifdef HAVE_SYSLOG + if (Quassel::logToSyslog()) { + int prio; + switch (_logLevel) { + case Quassel::DebugLevel: + prio = LOG_DEBUG; + break; + case Quassel::InfoLevel: + prio = LOG_INFO; + break; + case Quassel::WarningLevel: + prio = LOG_WARNING; + break; + case Quassel::ErrorLevel: + prio = LOG_ERR; + break; + default: + prio = LOG_INFO; + break; + } + syslog(LOG_USER & prio, "%s", qPrintable(_buffer)); } - syslog(LOG_USER & prio, "%s", qPrintable(_buffer)); - } #endif - // if we neither use syslog nor have a logfile we log to stdout + // if we neither use syslog nor have a logfile we log to stdout - if(Quassel::logFile() || !Quassel::logToSyslog()) { - _buffer.prepend(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss ")); + if (Quassel::logFile() || !Quassel::logToSyslog()) { + _buffer.prepend(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss ")); - QTextStream out(stdout); - if(Quassel::logFile() && Quassel::logFile()->isOpen()) { - _buffer.remove(QChar('\n')); - out.setDevice(Quassel::logFile()); - } + QTextStream out(stdout); + if (Quassel::logFile() && Quassel::logFile()->isOpen()) { + _buffer.remove(QChar('\n')); + out.setDevice(Quassel::logFile()); + } - out << _buffer << endl; - } + out << _buffer << endl; + } } -void Logger::logMessage(QtMsgType type, const char *msg) { - switch (type) { - case QtDebugMsg: - Logger(Quassel::DebugLevel) << msg; - break; - case QtWarningMsg: - Logger(Quassel::WarningLevel) << msg; - break; - case QtCriticalMsg: - Logger(Quassel::ErrorLevel) << msg; - break; - case QtFatalMsg: - Logger(Quassel::ErrorLevel) << msg; - Quassel::logFatalMessage(msg); - return; - } +void Logger::logMessage(QtMsgType type, const char *msg) +{ + switch (type) { + case QtDebugMsg: + Logger(Quassel::DebugLevel) << msg; + break; + case QtWarningMsg: + Logger(Quassel::WarningLevel) << msg; + break; + case QtCriticalMsg: + Logger(Quassel::ErrorLevel) << msg; + break; + case QtFatalMsg: + Logger(Quassel::ErrorLevel) << msg; + Quassel::logFatalMessage(msg); + return; + } } diff --git a/src/common/logger.h b/src/common/logger.h index 744c9800..ac4af54b 100644 --- a/src/common/logger.h +++ b/src/common/logger.h @@ -27,38 +27,46 @@ #include "quassel.h" #include "types.h" -class Logger { +class Logger +{ public: - inline Logger(Quassel::LogLevel level) : _stream(&_buffer, QIODevice::WriteOnly), _logLevel(level) {} - ~Logger(); + inline Logger(Quassel::LogLevel level) : _stream(&_buffer, QIODevice::WriteOnly), _logLevel(level) {} + ~Logger(); - static void logMessage(QtMsgType type, const char *msg); + static void logMessage(QtMsgType type, const char *msg); - template - inline Logger &operator<<(const T &value) { _stream << value << " "; return *this; } - inline Logger &operator<<(const QStringList & t) { _stream << t.join(" ") << " "; return *this; } - inline Logger &operator<<(bool t) { _stream << (t ? "true" : "false") << " "; return *this; } + template + inline Logger &operator<<(const T &value) { _stream << value << " "; return *this; } + inline Logger &operator<<(const QStringList &t) { _stream << t.join(" ") << " "; return *this; } + inline Logger &operator<<(bool t) { _stream << (t ? "true" : "false") << " "; return *this; } private: - void log(); - QTextStream _stream; - QString _buffer; - Quassel::LogLevel _logLevel; + void log(); + QTextStream _stream; + QString _buffer; + Quassel::LogLevel _logLevel; }; -class quInfo : public Logger { + +class quInfo : public Logger +{ public: - inline quInfo() : Logger(Quassel::InfoLevel) {} + inline quInfo() : Logger(Quassel::InfoLevel) {} }; -class quWarning : public Logger { + +class quWarning : public Logger +{ public: - inline quWarning() : Logger(Quassel::WarningLevel) {} + inline quWarning() : Logger(Quassel::WarningLevel) {} }; -class quError : public Logger { + +class quError : public Logger +{ public: - inline quError() : Logger(Quassel::ErrorLevel) {} + inline quError() : Logger(Quassel::ErrorLevel) {} }; + #endif diff --git a/src/common/mac_utils.cpp b/src/common/mac_utils.cpp index c76c71cc..ea1ad347 100644 --- a/src/common/mac_utils.cpp +++ b/src/common/mac_utils.cpp @@ -22,16 +22,17 @@ #include -QString CFStringToQString(CFStringRef str) { - if(!str) - return QString(); +QString CFStringToQString(CFStringRef str) +{ + if (!str) + return QString(); - CFIndex length = CFStringGetLength(str); - const UniChar *chars = CFStringGetCharactersPtr(str); - if(chars) - return QString(reinterpret_cast(chars), length); + CFIndex length = CFStringGetLength(str); + const UniChar *chars = CFStringGetCharactersPtr(str); + if (chars) + return QString(reinterpret_cast(chars), length); - QVarLengthArray buffer(length); - CFStringGetCharacters(str, CFRangeMake(0, length), buffer.data()); - return QString(reinterpret_cast(buffer.constData()), length); + QVarLengthArray buffer(length); + CFStringGetCharacters(str, CFRangeMake(0, length), buffer.data()); + return QString(reinterpret_cast(buffer.constData()), length); } diff --git a/src/common/main.cpp b/src/common/main.cpp index 24a71588..cf90a48d 100644 --- a/src/common/main.cpp +++ b/src/common/main.cpp @@ -50,78 +50,78 @@ Q_IMPORT_PLUGIN(qgif) #include "cliparser.h" #include "quassel.h" -int main(int argc, char **argv) { - - // Setup build information and version string +int main(int argc, char **argv) +{ + // Setup build information and version string # include "version.gen" - buildinfo.append(QString(",%1,%2").arg(__DATE__, __TIME__)); - Quassel::setupBuildInfo(buildinfo); - QCoreApplication::setApplicationName(Quassel::buildInfo().applicationName); - QCoreApplication::setOrganizationName(Quassel::buildInfo().organizationName); - QCoreApplication::setOrganizationDomain(Quassel::buildInfo().organizationDomain); + buildinfo.append(QString(",%1,%2").arg(__DATE__, __TIME__)); + Quassel::setupBuildInfo(buildinfo); + QCoreApplication::setApplicationName(Quassel::buildInfo().applicationName); + QCoreApplication::setOrganizationName(Quassel::buildInfo().organizationName); + QCoreApplication::setOrganizationDomain(Quassel::buildInfo().organizationDomain); - AbstractCliParser *cliParser; + AbstractCliParser *cliParser; #ifdef HAVE_KDE - // We need to init KCmdLineArgs first - // TODO: build an AboutData compat class to replace our aboutDlg strings - KAboutData aboutData("quassel", "kdelibs4", ki18n("Quassel IRC"), Quassel::buildInfo().plainVersionString.toUtf8(), - ki18n("A modern, distributed IRC client")); - aboutData.addLicense(KAboutData::License_GPL_V2); - aboutData.addLicense(KAboutData::License_GPL_V3); - aboutData.setBugAddress("http://bugs.quassel-irc.org/projects/quassel-irc/issues/new"); - aboutData.setOrganizationDomain(Quassel::buildInfo().organizationDomain.toUtf8()); - KCmdLineArgs::init(argc, argv, &aboutData); - - cliParser = new KCmdLineWrapper(); + // We need to init KCmdLineArgs first + // TODO: build an AboutData compat class to replace our aboutDlg strings + KAboutData aboutData("quassel", "kdelibs4", ki18n("Quassel IRC"), Quassel::buildInfo().plainVersionString.toUtf8(), + ki18n("A modern, distributed IRC client")); + aboutData.addLicense(KAboutData::License_GPL_V2); + aboutData.addLicense(KAboutData::License_GPL_V3); + aboutData.setBugAddress("http://bugs.quassel-irc.org/projects/quassel-irc/issues/new"); + aboutData.setOrganizationDomain(Quassel::buildInfo().organizationDomain.toUtf8()); + KCmdLineArgs::init(argc, argv, &aboutData); + + cliParser = new KCmdLineWrapper(); #else - cliParser = new CliParser(); + cliParser = new CliParser(); #endif - Quassel::setCliParser(cliParser); + Quassel::setCliParser(cliParser); - // Initialize CLI arguments - // NOTE: We can't use tr() at this point, since app is not yet created + // Initialize CLI arguments + // NOTE: We can't use tr() at this point, since app is not yet created - // put shared client&core arguments here - cliParser->addSwitch("debug",'d', "Enable debug output"); - cliParser->addSwitch("help",'h', "Display this help and exit"); - cliParser->addSwitch("version", 'v', "Display version information"); + // put shared client&core arguments here + cliParser->addSwitch("debug", 'd', "Enable debug output"); + cliParser->addSwitch("help", 'h', "Display this help and exit"); + cliParser->addSwitch("version", 'v', "Display version information"); #ifdef BUILD_QTUI - cliParser->addOption("configdir ", 'c', "Specify the directory holding the client configuration"); + cliParser->addOption("configdir ", 'c', "Specify the directory holding the client configuration"); #else - cliParser->addOption("configdir ", 'c', "Specify the directory holding configuration files, the SQlite database and the SSL certificate"); + cliParser->addOption("configdir ", 'c', "Specify the directory holding configuration files, the SQlite database and the SSL certificate"); #endif - cliParser->addOption("datadir ", 0, "DEPRECATED - Use --configdir instead"); + cliParser->addOption("datadir ", 0, "DEPRECATED - Use --configdir instead"); #ifndef BUILD_CORE - // put client-only arguments here - cliParser->addOption("qss ", 0, "Load a custom application stylesheet"); - cliParser->addSwitch("debugbufferswitches", 0, "Enables debugging for bufferswitches"); - cliParser->addSwitch("debugmodel", 0, "Enables debugging for models"); + // put client-only arguments here + cliParser->addOption("qss ", 0, "Load a custom application stylesheet"); + cliParser->addSwitch("debugbufferswitches", 0, "Enables debugging for bufferswitches"); + cliParser->addSwitch("debugmodel", 0, "Enables debugging for models"); #endif #ifndef BUILD_QTUI - // put core-only arguments here - cliParser->addOption("listen
[,", 0, "The address(es) quasselcore will listen on", "::,0.0.0.0"); - cliParser->addOption("port ",'p', "The port quasselcore will listen at", QString("4242")); - cliParser->addSwitch("norestore", 'n', "Don't restore last core's state"); - cliParser->addOption("loglevel ", 'L', "Loglevel Debug|Info|Warning|Error", "Info"); + // put core-only arguments here + cliParser->addOption("listen
[,", 0, "The address(es) quasselcore will listen on", "::,0.0.0.0"); + cliParser->addOption("port ", 'p', "The port quasselcore will listen at", QString("4242")); + cliParser->addSwitch("norestore", 'n', "Don't restore last core's state"); + cliParser->addOption("loglevel ", 'L', "Loglevel Debug|Info|Warning|Error", "Info"); #ifdef HAVE_SYSLOG - cliParser->addSwitch("syslog", 0, "Log to syslog"); + cliParser->addSwitch("syslog", 0, "Log to syslog"); #endif - cliParser->addOption("logfile ", 'l', "Log to a file"); - cliParser->addOption("select-backend ", 0, "Switch storage backend (migrating data if possible)"); - cliParser->addSwitch("add-user", 0, "Starts an interactive session to add a new core user"); - cliParser->addOption("change-userpass ", 0, "Starts an interactive session to change the password of the user identified by username"); - cliParser->addSwitch("oidentd", 0, "Enable oidentd integration"); - cliParser->addOption("oidentd-conffile ", 0, "Set path to oidentd configuration file"); + cliParser->addOption("logfile ", 'l', "Log to a file"); + cliParser->addOption("select-backend ", 0, "Switch storage backend (migrating data if possible)"); + cliParser->addSwitch("add-user", 0, "Starts an interactive session to add a new core user"); + cliParser->addOption("change-userpass ", 0, "Starts an interactive session to change the password of the user identified by username"); + cliParser->addSwitch("oidentd", 0, "Enable oidentd integration"); + cliParser->addOption("oidentd-conffile ", 0, "Set path to oidentd configuration file"); #endif #ifdef HAVE_KDE - // the KDE version needs this extra call to parse argc/argv before app is instantiated - if(!cliParser->init()) { - cliParser->usage(); - return EXIT_FAILURE; - } + // the KDE version needs this extra call to parse argc/argv before app is instantiated + if (!cliParser->init()) { + cliParser->usage(); + return EXIT_FAILURE; + } #endif # if defined BUILD_CORE @@ -133,13 +133,13 @@ int main(int argc, char **argv) { # endif #ifndef HAVE_KDE - // the non-KDE version parses after app has been instantiated - if(!cliParser->init(app.arguments())) { - cliParser->usage(); - return false; - } + // the non-KDE version parses after app has been instantiated + if (!cliParser->init(app.arguments())) { + cliParser->usage(); + return false; + } #endif - if(!app.init()) return EXIT_FAILURE; - return app.exec(); + if (!app.init()) return EXIT_FAILURE; + return app.exec(); } diff --git a/src/common/message.cpp b/src/common/message.cpp index c867a7cb..addcbb3c 100644 --- a/src/common/message.cpp +++ b/src/common/message.cpp @@ -25,7 +25,7 @@ #include Message::Message(const BufferInfo &bufferInfo, Type type, const QString &contents, const QString &sender, Flags flags) - : _timestamp(QDateTime::currentDateTime().toUTC()), + : _timestamp(QDateTime::currentDateTime().toUTC()), _bufferInfo(bufferInfo), _contents(contents), _sender(sender), @@ -34,8 +34,9 @@ Message::Message(const BufferInfo &bufferInfo, Type type, const QString &content { } + Message::Message(const QDateTime &ts, const BufferInfo &bufferInfo, Type type, const QString &contents, const QString &sender, Flags flags) - : _timestamp(ts), + : _timestamp(ts), _bufferInfo(bufferInfo), _contents(contents), _sender(sender), @@ -44,33 +45,39 @@ Message::Message(const QDateTime &ts, const BufferInfo &bufferInfo, Type type, c { } -QDataStream &operator<<(QDataStream &out, const Message &msg) { - out << msg.msgId() << (quint32)msg.timestamp().toTime_t() << (quint32)msg.type() << (quint8)msg.flags() - << msg.bufferInfo() << msg.sender().toUtf8() << msg.contents().toUtf8(); - return out; + +QDataStream &operator<<(QDataStream &out, const Message &msg) +{ + out << msg.msgId() << (quint32)msg.timestamp().toTime_t() << (quint32)msg.type() << (quint8)msg.flags() + << msg.bufferInfo() << msg.sender().toUtf8() << msg.contents().toUtf8(); + return out; } -QDataStream &operator>>(QDataStream &in, Message &msg) { - quint8 f; - quint32 t; - quint32 ts; - QByteArray s, m; - BufferInfo buf; - in >> msg._msgId >> ts >> t >> f >> buf >> s >> m; - msg._type = (Message::Type)t; - msg._flags = (Message::Flags)f; - msg._bufferInfo = buf; - msg._timestamp = QDateTime::fromTime_t(ts); - msg._sender = QString::fromUtf8(s); - msg._contents = QString::fromUtf8(m); - return in; + +QDataStream &operator>>(QDataStream &in, Message &msg) +{ + quint8 f; + quint32 t; + quint32 ts; + QByteArray s, m; + BufferInfo buf; + in >> msg._msgId >> ts >> t >> f >> buf >> s >> m; + msg._type = (Message::Type)t; + msg._flags = (Message::Flags)f; + msg._bufferInfo = buf; + msg._timestamp = QDateTime::fromTime_t(ts); + msg._sender = QString::fromUtf8(s); + msg._contents = QString::fromUtf8(m); + return in; } -QDebug operator<<(QDebug dbg, const Message &msg) { - dbg.nospace() << qPrintable(QString("Message(MsgId:")) << msg.msgId() - << qPrintable(QString(",")) << msg.timestamp() - << qPrintable(QString(", Type:")) << msg.type() - << qPrintable(QString(", Flags:")) << msg.flags() << qPrintable(QString(")")) - << msg.sender() << ":" << msg.contents(); - return dbg; + +QDebug operator<<(QDebug dbg, const Message &msg) +{ + dbg.nospace() << qPrintable(QString("Message(MsgId:")) << msg.msgId() + << qPrintable(QString(",")) << msg.timestamp() + << qPrintable(QString(", Type:")) << msg.type() + << qPrintable(QString(", Flags:")) << msg.flags() << qPrintable(QString(")")) + << msg.sender() << ":" << msg.contents(); + return dbg; } diff --git a/src/common/message.h b/src/common/message.h index 612757d5..c7000f9f 100644 --- a/src/common/message.h +++ b/src/common/message.h @@ -27,78 +27,79 @@ #include "bufferinfo.h" #include "types.h" -class Message { - Q_DECLARE_TR_FUNCTIONS(Message) +class Message +{ + Q_DECLARE_TR_FUNCTIONS(Message) public: - /** The different types a message can have for display */ - enum Type { - Plain = 0x00001, - Notice = 0x00002, - Action = 0x00004, - Nick = 0x00008, - Mode = 0x00010, - Join = 0x00020, - Part = 0x00040, - Quit = 0x00080, - Kick = 0x00100, - Kill = 0x00200, - Server = 0x00400, - Info = 0x00800, - Error = 0x01000, - DayChange = 0x02000, - Topic = 0x04000, - NetsplitJoin = 0x08000, - NetsplitQuit = 0x10000, - Invite = 0x20000, - }; - - // DO NOT CHANGE without knowing what you do, some of these flags are stored in the database - enum Flag { - None = 0x00, - Self = 0x01, - Highlight = 0x02, - Redirected = 0x04, - ServerMsg = 0x08, - Backlog = 0x80 - }; - Q_DECLARE_FLAGS(Flags, Flag) - - - Message(const BufferInfo &bufferInfo = BufferInfo(), Type type = Plain, const QString &contents = "", const QString &sender = "", Flags flags = None); - Message(const QDateTime &ts, const BufferInfo &buffer = BufferInfo(), Type type = Plain, - const QString &contents = "", const QString &sender = "", Flags flags = None); - - inline static Message ChangeOfDay(const QDateTime &day) { return Message(day, BufferInfo(), DayChange); } - inline const MsgId &msgId() const { return _msgId; } - inline void setMsgId(MsgId id) { _msgId = id; } - - inline const BufferInfo &bufferInfo() const { return _bufferInfo; } - inline const BufferId &bufferId() const { return _bufferInfo.bufferId(); } - inline void setBufferId(BufferId id) { _bufferInfo.setBufferId(id); } - inline const QString &contents() const { return _contents; } - inline const QString &sender() const { return _sender; } - inline Type type() const { return _type; } - inline Flags flags() const { return _flags; } - inline void setFlags(Flags flags) { _flags = flags; } - inline const QDateTime ×tamp() const { return _timestamp; } - - inline bool isValid() const { return _msgId.isValid(); } - - inline bool operator<(const Message &other) const { return _msgId < other._msgId; } + /** The different types a message can have for display */ + enum Type { + Plain = 0x00001, + Notice = 0x00002, + Action = 0x00004, + Nick = 0x00008, + Mode = 0x00010, + Join = 0x00020, + Part = 0x00040, + Quit = 0x00080, + Kick = 0x00100, + Kill = 0x00200, + Server = 0x00400, + Info = 0x00800, + Error = 0x01000, + DayChange = 0x02000, + Topic = 0x04000, + NetsplitJoin = 0x08000, + NetsplitQuit = 0x10000, + Invite = 0x20000, + }; + + // DO NOT CHANGE without knowing what you do, some of these flags are stored in the database + enum Flag { + None = 0x00, + Self = 0x01, + Highlight = 0x02, + Redirected = 0x04, + ServerMsg = 0x08, + Backlog = 0x80 + }; + Q_DECLARE_FLAGS(Flags, Flag) + + Message(const BufferInfo &bufferInfo = BufferInfo(), Type type = Plain, const QString &contents = "", const QString &sender = "", Flags flags = None); + Message(const QDateTime &ts, const BufferInfo &buffer = BufferInfo(), Type type = Plain, + const QString &contents = "", const QString &sender = "", Flags flags = None); + + inline static Message ChangeOfDay(const QDateTime &day) { return Message(day, BufferInfo(), DayChange); } + inline const MsgId &msgId() const { return _msgId; } + inline void setMsgId(MsgId id) { _msgId = id; } + + inline const BufferInfo &bufferInfo() const { return _bufferInfo; } + inline const BufferId &bufferId() const { return _bufferInfo.bufferId(); } + inline void setBufferId(BufferId id) { _bufferInfo.setBufferId(id); } + inline const QString &contents() const { return _contents; } + inline const QString &sender() const { return _sender; } + inline Type type() const { return _type; } + inline Flags flags() const { return _flags; } + inline void setFlags(Flags flags) { _flags = flags; } + inline const QDateTime ×tamp() const { return _timestamp; } + + inline bool isValid() const { return _msgId.isValid(); } + + inline bool operator<(const Message &other) const { return _msgId < other._msgId; } private: - QDateTime _timestamp; - MsgId _msgId; - BufferInfo _bufferInfo; - QString _contents; - QString _sender; - Type _type; - Flags _flags; - - friend QDataStream &operator>>(QDataStream &in, Message &msg); + QDateTime _timestamp; + MsgId _msgId; + BufferInfo _bufferInfo; + QString _contents; + QString _sender; + Type _type; + Flags _flags; + + friend QDataStream &operator>>(QDataStream &in, Message &msg); }; + typedef QList MessageList; QDataStream &operator<<(QDataStream &out, const Message &msg); diff --git a/src/common/messageevent.cpp b/src/common/messageevent.cpp index 606103e9..712fdf7e 100644 --- a/src/common/messageevent.cpp +++ b/src/common/messageevent.cpp @@ -20,71 +20,73 @@ #include "messageevent.h" -Event *MessageEvent::create(EventManager::EventType type, QVariantMap &map, Network *network) { - if(type == EventManager::MessageEvent) - return new MessageEvent(type, map, network); +Event *MessageEvent::create(EventManager::EventType type, QVariantMap &map, Network *network) +{ + if (type == EventManager::MessageEvent) + return new MessageEvent(type, map, network); - return 0; + return 0; } MessageEvent::MessageEvent(Message::Type msgType, Network *net, const QString &msg, const QString &sender, const QString &target, - Message::Flags flags, const QDateTime ×tamp) + Message::Flags flags, const QDateTime ×tamp) : NetworkEvent(EventManager::MessageEvent, net), - _msgType(msgType), - _text(msg), - _sender(sender), - _target(target), - _msgFlags(flags) + _msgType(msgType), + _text(msg), + _sender(sender), + _target(target), + _msgFlags(flags) { - IrcChannel *channel = network()->ircChannel(_target); - if(!channel) { - if(!_target.isEmpty() && network()->prefixes().contains(_target.at(0))) - _target = _target.mid(1); + IrcChannel *channel = network()->ircChannel(_target); + if (!channel) { + if (!_target.isEmpty() && network()->prefixes().contains(_target.at(0))) + _target = _target.mid(1); - if(_target.startsWith('$') || _target.startsWith('#')) - _target = nickFromMask(sender); - } + if (_target.startsWith('$') || _target.startsWith('#')) + _target = nickFromMask(sender); + } - _bufferType = bufferTypeByTarget(_target); + _bufferType = bufferTypeByTarget(_target); - if(timestamp.isValid()) - setTimestamp(timestamp); - else - setTimestamp(QDateTime::currentDateTime()); + if (timestamp.isValid()) + setTimestamp(timestamp); + else + setTimestamp(QDateTime::currentDateTime()); } MessageEvent::MessageEvent(EventManager::EventType type, QVariantMap &map, Network *network) - : NetworkEvent(type, map, network) + : NetworkEvent(type, map, network) { - _msgType = static_cast(map.take("messageType").toInt()); - _msgFlags = static_cast(map.take("messageFlags").toInt()); - _bufferType = static_cast(map.take("bufferType").toInt()); - _text = map.take("text").toString(); - _sender = map.take("sender").toString(); - _target = map.take("target").toString(); + _msgType = static_cast(map.take("messageType").toInt()); + _msgFlags = static_cast(map.take("messageFlags").toInt()); + _bufferType = static_cast(map.take("bufferType").toInt()); + _text = map.take("text").toString(); + _sender = map.take("sender").toString(); + _target = map.take("target").toString(); } -void MessageEvent::toVariantMap(QVariantMap &map) const { - NetworkEvent::toVariantMap(map); - map["messageType"] = msgType(); - map["messageFlags"] = (int)msgFlags(); - map["bufferType"] = bufferType(); - map["text"] = text(); - map["sender"] = sender(); - map["target"] = target(); +void MessageEvent::toVariantMap(QVariantMap &map) const +{ + NetworkEvent::toVariantMap(map); + map["messageType"] = msgType(); + map["messageFlags"] = (int)msgFlags(); + map["bufferType"] = bufferType(); + map["text"] = text(); + map["sender"] = sender(); + map["target"] = target(); } -BufferInfo::Type MessageEvent::bufferTypeByTarget(const QString &target) const { - if(target.isEmpty()) - return BufferInfo::StatusBuffer; +BufferInfo::Type MessageEvent::bufferTypeByTarget(const QString &target) const +{ + if (target.isEmpty()) + return BufferInfo::StatusBuffer; - if(network()->isChannelName(target)) - return BufferInfo::ChannelBuffer; + if (network()->isChannelName(target)) + return BufferInfo::ChannelBuffer; - return BufferInfo::QueryBuffer; + return BufferInfo::QueryBuffer; } - diff --git a/src/common/messageevent.h b/src/common/messageevent.h index e93794cd..4f476b42 100644 --- a/src/common/messageevent.h +++ b/src/common/messageevent.h @@ -27,56 +27,59 @@ // this corresponds to CoreSession::RawMessage for now and should contain the information we need to convert events // into messages for the legacy code to work with -class MessageEvent : public NetworkEvent { - +class MessageEvent : public NetworkEvent +{ public: - explicit MessageEvent(Message::Type msgType, - Network *network, - const QString &msg, - const QString &sender = QString(), - const QString &target = QString(), - Message::Flags msgFlags = Message::None, - const QDateTime ×tamp = QDateTime() - ); + explicit MessageEvent(Message::Type msgType, + Network *network, + const QString &msg, + const QString &sender = QString(), + const QString &target = QString(), + Message::Flags msgFlags = Message::None, + const QDateTime ×tamp = QDateTime() + ); - inline Message::Type msgType() const { return _msgType; } - inline void setMsgType(Message::Type type) { _msgType = type; } + inline Message::Type msgType() const { return _msgType; } + inline void setMsgType(Message::Type type) { _msgType = type; } - inline BufferInfo::Type bufferType() const { return _bufferType; } - inline void setBufferType(BufferInfo::Type type) { _bufferType = type; } + inline BufferInfo::Type bufferType() const { return _bufferType; } + inline void setBufferType(BufferInfo::Type type) { _bufferType = type; } - inline QString target() const { return _target; } - inline QString text() const { return _text; } - inline QString sender() const { return _sender; } + inline QString target() const { return _target; } + inline QString text() const { return _text; } + inline QString sender() const { return _sender; } - inline Message::Flags msgFlags() const { return _msgFlags; } - inline void setMsgFlag(Message::Flag flag) { _msgFlags |= flag; } - inline void setMsgFlags(Message::Flags flags) { _msgFlags = flags; } + inline Message::Flags msgFlags() const { return _msgFlags; } + inline void setMsgFlag(Message::Flag flag) { _msgFlags |= flag; } + inline void setMsgFlags(Message::Flags flags) { _msgFlags = flags; } - static Event *create(EventManager::EventType type, QVariantMap &map, Network *network); + static Event *create(EventManager::EventType type, QVariantMap &map, Network *network); protected: - explicit MessageEvent(EventManager::EventType type, QVariantMap &map, Network *network); - void toVariantMap(QVariantMap &map) const; - - virtual inline QString className() const { return "MessageEvent"; } - virtual inline void debugInfo(QDebug &dbg) const { - NetworkEvent::debugInfo(dbg); - dbg.nospace() << ", sender = " << qPrintable(sender()) - << ", target = " << qPrintable(target()) - << ", text = " << text() - << ", msgtype = " << qPrintable(QString::number(msgType(), 16)) - << ", buffertype = " << qPrintable(QString::number(bufferType(), 16)) - << ", msgflags = " << qPrintable(QString::number(msgFlags(), 16)); - } + explicit MessageEvent(EventManager::EventType type, QVariantMap &map, Network *network); + void toVariantMap(QVariantMap &map) const; + + virtual inline QString className() const { return "MessageEvent"; } + virtual inline void debugInfo(QDebug &dbg) const + { + NetworkEvent::debugInfo(dbg); + dbg.nospace() << ", sender = " << qPrintable(sender()) + << ", target = " << qPrintable(target()) + << ", text = " << text() + << ", msgtype = " << qPrintable(QString::number(msgType(), 16)) + << ", buffertype = " << qPrintable(QString::number(bufferType(), 16)) + << ", msgflags = " << qPrintable(QString::number(msgFlags(), 16)); + } + private: - BufferInfo::Type bufferTypeByTarget(const QString &target) const; + BufferInfo::Type bufferTypeByTarget(const QString &target) const; - Message::Type _msgType; - BufferInfo::Type _bufferType; - QString _text, _sender, _target; - Message::Flags _msgFlags; + Message::Type _msgType; + BufferInfo::Type _bufferType; + QString _text, _sender, _target; + Message::Flags _msgFlags; }; + #endif diff --git a/src/common/network.cpp b/src/common/network.cpp index 6fd006ab..b17e1d32 100644 --- a/src/common/network.cpp +++ b/src/common/network.cpp @@ -33,7 +33,7 @@ QString Network::_networksIniPath = QString(); // ==================== INIT_SYNCABLE_OBJECT(Network) Network::Network(const NetworkId &networkid, QObject *parent) - : SyncableObject(parent), + : SyncableObject(parent), _proxy(0), _networkId(networkid), _identity(0), @@ -57,891 +57,1054 @@ Network::Network(const NetworkId &networkid, QObject *parent) _codecForDecoding(0), _autoAwayActive(false) { - setObjectName(QString::number(networkid.toInt())); -} - -Network::~Network() { - emit aboutToBeDestroyed(); -} - -bool Network::isChannelName(const QString &channelname) const { - if(channelname.isEmpty()) - return false; - - if(supports("CHANTYPES")) - return support("CHANTYPES").contains(channelname[0]); - else - return QString("#&!+").contains(channelname[0]); -} - -NetworkInfo Network::networkInfo() const { - NetworkInfo info; - info.networkName = networkName(); - info.networkId = networkId(); - info.identity = identity(); - info.codecForServer = codecForServer(); - info.codecForEncoding = codecForEncoding(); - info.codecForDecoding = codecForDecoding(); - info.serverList = serverList(); - info.useRandomServer = useRandomServer(); - info.perform = perform(); - info.useAutoIdentify = useAutoIdentify(); - info.autoIdentifyService = autoIdentifyService(); - info.autoIdentifyPassword = autoIdentifyPassword(); - info.useSasl = useSasl(); - info.saslAccount = saslAccount(); - info.saslPassword = saslPassword(); - info.useAutoReconnect = useAutoReconnect(); - info.autoReconnectInterval = autoReconnectInterval(); - info.autoReconnectRetries = autoReconnectRetries(); - info.unlimitedReconnectRetries = unlimitedReconnectRetries(); - info.rejoinChannels = rejoinChannels(); - return info; -} - -void Network::setNetworkInfo(const NetworkInfo &info) { - // we don't set our ID! - if(!info.networkName.isEmpty() && info.networkName != networkName()) setNetworkName(info.networkName); - if(info.identity > 0 && info.identity != identity()) setIdentity(info.identity); - if(info.codecForServer != codecForServer()) setCodecForServer(QTextCodec::codecForName(info.codecForServer)); - if(info.codecForEncoding != codecForEncoding()) setCodecForEncoding(QTextCodec::codecForName(info.codecForEncoding)); - if(info.codecForDecoding != codecForDecoding()) setCodecForDecoding(QTextCodec::codecForName(info.codecForDecoding)); - if(info.serverList.count()) setServerList(toVariantList(info.serverList)); // FIXME compare components - if(info.useRandomServer != useRandomServer()) setUseRandomServer(info.useRandomServer); - if(info.perform != perform()) setPerform(info.perform); - if(info.useAutoIdentify != useAutoIdentify()) setUseAutoIdentify(info.useAutoIdentify); - if(info.autoIdentifyService != autoIdentifyService()) setAutoIdentifyService(info.autoIdentifyService); - if(info.autoIdentifyPassword != autoIdentifyPassword()) setAutoIdentifyPassword(info.autoIdentifyPassword); - if(info.useSasl != useSasl()) setUseSasl(info.useSasl); - if(info.saslAccount != saslAccount()) setSaslAccount(info.saslAccount); - if(info.saslPassword != saslPassword()) setSaslPassword(info.saslPassword); - if(info.useAutoReconnect != useAutoReconnect()) setUseAutoReconnect(info.useAutoReconnect); - if(info.autoReconnectInterval != autoReconnectInterval()) setAutoReconnectInterval(info.autoReconnectInterval); - if(info.autoReconnectRetries != autoReconnectRetries()) setAutoReconnectRetries(info.autoReconnectRetries); - if(info.unlimitedReconnectRetries != unlimitedReconnectRetries()) setUnlimitedReconnectRetries(info.unlimitedReconnectRetries); - if(info.rejoinChannels != rejoinChannels()) setRejoinChannels(info.rejoinChannels); -} - -QString Network::prefixToMode(const QString &prefix) const { - if(prefixes().contains(prefix)) - return QString(prefixModes()[prefixes().indexOf(prefix)]); - else - return QString(); -} - -QString Network::modeToPrefix(const QString &mode) const { - if(prefixModes().contains(mode)) - return QString(prefixes()[prefixModes().indexOf(mode)]); - else - return QString(); -} - -QStringList Network::nicks() const { - // we don't use _ircUsers.keys() since the keys may be - // not up to date after a nick change - QStringList nicks; - foreach(IrcUser *ircuser, _ircUsers.values()) { - nicks << ircuser->nick(); - } - return nicks; -} - -QString Network::prefixes() const { - if(_prefixes.isNull()) - determinePrefixes(); - - return _prefixes; -} - -QString Network::prefixModes() const { - if(_prefixModes.isNull()) - determinePrefixes(); - - return _prefixModes; + setObjectName(QString::number(networkid.toInt())); } -// example Unreal IRCD: CHANMODES=beI,kfL,lj,psmntirRcOAQKVCuzNSMTG -Network::ChannelModeType Network::channelModeType(const QString &mode) { - if(mode.isEmpty()) - return NOT_A_CHANMODE; - - QString chanmodes = support("CHANMODES"); - if(chanmodes.isEmpty()) - return NOT_A_CHANMODE; - - ChannelModeType modeType = A_CHANMODE; - for(int i = 0; i < chanmodes.count(); i++) { - if(chanmodes[i] == mode[0]) - break; - else if(chanmodes[i] == ',') - modeType = (ChannelModeType)(modeType << 1); - } - if(modeType > D_CHANMODE) { - qWarning() << "Network" << networkId() << "supplied invalid CHANMODES:" << chanmodes; - modeType = NOT_A_CHANMODE; - } - return modeType; -} - -QString Network::support(const QString ¶m) const { - QString support_ = param.toUpper(); - if(_supports.contains(support_)) - return _supports[support_]; - else - return QString(); -} - -IrcUser *Network::newIrcUser(const QString &hostmask, const QVariantMap &initData) { - QString nick(nickFromMask(hostmask).toLower()); - if(!_ircUsers.contains(nick)) { - IrcUser *ircuser = ircUserFactory(hostmask); - if(!initData.isEmpty()) { - ircuser->fromVariantMap(initData); - ircuser->setInitialized(); - } - if(proxy()) - proxy()->synchronize(ircuser); +Network::~Network() +{ + emit aboutToBeDestroyed(); +} + + +bool Network::isChannelName(const QString &channelname) const +{ + if (channelname.isEmpty()) + return false; + + if (supports("CHANTYPES")) + return support("CHANTYPES").contains(channelname[0]); else - qWarning() << "unable to synchronize new IrcUser" << hostmask << "forgot to call Network::setProxy(SignalProxy *)?"; + return QString("#&!+").contains(channelname[0]); +} - connect(ircuser, SIGNAL(nickSet(QString)), this, SLOT(ircUserNickChanged(QString))); - _ircUsers[nick] = ircuser; +NetworkInfo Network::networkInfo() const +{ + NetworkInfo info; + info.networkName = networkName(); + info.networkId = networkId(); + info.identity = identity(); + info.codecForServer = codecForServer(); + info.codecForEncoding = codecForEncoding(); + info.codecForDecoding = codecForDecoding(); + info.serverList = serverList(); + info.useRandomServer = useRandomServer(); + info.perform = perform(); + info.useAutoIdentify = useAutoIdentify(); + info.autoIdentifyService = autoIdentifyService(); + info.autoIdentifyPassword = autoIdentifyPassword(); + info.useSasl = useSasl(); + info.saslAccount = saslAccount(); + info.saslPassword = saslPassword(); + info.useAutoReconnect = useAutoReconnect(); + info.autoReconnectInterval = autoReconnectInterval(); + info.autoReconnectRetries = autoReconnectRetries(); + info.unlimitedReconnectRetries = unlimitedReconnectRetries(); + info.rejoinChannels = rejoinChannels(); + return info; +} + + +void Network::setNetworkInfo(const NetworkInfo &info) +{ + // we don't set our ID! + if (!info.networkName.isEmpty() && info.networkName != networkName()) setNetworkName(info.networkName); + if (info.identity > 0 && info.identity != identity()) setIdentity(info.identity); + if (info.codecForServer != codecForServer()) setCodecForServer(QTextCodec::codecForName(info.codecForServer)); + if (info.codecForEncoding != codecForEncoding()) setCodecForEncoding(QTextCodec::codecForName(info.codecForEncoding)); + if (info.codecForDecoding != codecForDecoding()) setCodecForDecoding(QTextCodec::codecForName(info.codecForDecoding)); + if (info.serverList.count()) setServerList(toVariantList(info.serverList)); // FIXME compare components + if (info.useRandomServer != useRandomServer()) setUseRandomServer(info.useRandomServer); + if (info.perform != perform()) setPerform(info.perform); + if (info.useAutoIdentify != useAutoIdentify()) setUseAutoIdentify(info.useAutoIdentify); + if (info.autoIdentifyService != autoIdentifyService()) setAutoIdentifyService(info.autoIdentifyService); + if (info.autoIdentifyPassword != autoIdentifyPassword()) setAutoIdentifyPassword(info.autoIdentifyPassword); + if (info.useSasl != useSasl()) setUseSasl(info.useSasl); + if (info.saslAccount != saslAccount()) setSaslAccount(info.saslAccount); + if (info.saslPassword != saslPassword()) setSaslPassword(info.saslPassword); + if (info.useAutoReconnect != useAutoReconnect()) setUseAutoReconnect(info.useAutoReconnect); + if (info.autoReconnectInterval != autoReconnectInterval()) setAutoReconnectInterval(info.autoReconnectInterval); + if (info.autoReconnectRetries != autoReconnectRetries()) setAutoReconnectRetries(info.autoReconnectRetries); + if (info.unlimitedReconnectRetries != unlimitedReconnectRetries()) setUnlimitedReconnectRetries(info.unlimitedReconnectRetries); + if (info.rejoinChannels != rejoinChannels()) setRejoinChannels(info.rejoinChannels); +} + + +QString Network::prefixToMode(const QString &prefix) const +{ + if (prefixes().contains(prefix)) + return QString(prefixModes()[prefixes().indexOf(prefix)]); + else + return QString(); +} - SYNC_OTHER(addIrcUser, ARG(hostmask)) - // emit ircUserAdded(hostmask); - emit ircUserAdded(ircuser); - } - return _ircUsers[nick]; +QString Network::modeToPrefix(const QString &mode) const +{ + if (prefixModes().contains(mode)) + return QString(prefixes()[prefixModes().indexOf(mode)]); + else + return QString(); } -IrcUser *Network::ircUser(QString nickname) const { - nickname = nickname.toLower(); - if(_ircUsers.contains(nickname)) - return _ircUsers[nickname]; - else - return 0; + +QStringList Network::nicks() const +{ + // we don't use _ircUsers.keys() since the keys may be + // not up to date after a nick change + QStringList nicks; + foreach(IrcUser *ircuser, _ircUsers.values()) { + nicks << ircuser->nick(); + } + return nicks; } -void Network::removeIrcUser(IrcUser *ircuser) { - QString nick = _ircUsers.key(ircuser); - if(nick.isNull()) - return; - _ircUsers.remove(nick); - disconnect(ircuser, 0, this, 0); - ircuser->deleteLater(); +QString Network::prefixes() const +{ + if (_prefixes.isNull()) + determinePrefixes(); + + return _prefixes; } -void Network::removeIrcChannel(IrcChannel *channel) { - QString chanName = _ircChannels.key(channel); - if(chanName.isNull()) - return; - _ircChannels.remove(chanName); - disconnect(channel, 0, this, 0); - channel->deleteLater(); +QString Network::prefixModes() const +{ + if (_prefixModes.isNull()) + determinePrefixes(); + + return _prefixModes; } -void Network::removeChansAndUsers() { - QList users = ircUsers(); - _ircUsers.clear(); - QList channels = ircChannels(); - _ircChannels.clear(); - foreach(IrcChannel *channel, channels) { - proxy()->detachObject(channel); - disconnect(channel, 0, this, 0); - } - foreach(IrcUser *user, users) { - proxy()->detachObject(user); - disconnect(user, 0, this, 0); - } - - // the second loop is needed because quit can have sideffects - foreach(IrcUser *user, users) { - user->quit(); - } - - qDeleteAll(users); - qDeleteAll(channels); -} - -IrcChannel *Network::newIrcChannel(const QString &channelname, const QVariantMap &initData) { - if(!_ircChannels.contains(channelname.toLower())) { - IrcChannel *channel = ircChannelFactory(channelname); - if(!initData.isEmpty()) { - channel->fromVariantMap(initData); - channel->setInitialized(); +// example Unreal IRCD: CHANMODES=beI,kfL,lj,psmntirRcOAQKVCuzNSMTG +Network::ChannelModeType Network::channelModeType(const QString &mode) +{ + if (mode.isEmpty()) + return NOT_A_CHANMODE; + + QString chanmodes = support("CHANMODES"); + if (chanmodes.isEmpty()) + return NOT_A_CHANMODE; + + ChannelModeType modeType = A_CHANMODE; + for (int i = 0; i < chanmodes.count(); i++) { + if (chanmodes[i] == mode[0]) + break; + else if (chanmodes[i] == ',') + modeType = (ChannelModeType)(modeType << 1); + } + if (modeType > D_CHANMODE) { + qWarning() << "Network" << networkId() << "supplied invalid CHANMODES:" << chanmodes; + modeType = NOT_A_CHANMODE; } + return modeType; +} - if(proxy()) - proxy()->synchronize(channel); + +QString Network::support(const QString ¶m) const +{ + QString support_ = param.toUpper(); + if (_supports.contains(support_)) + return _supports[support_]; + else + return QString(); +} + + +IrcUser *Network::newIrcUser(const QString &hostmask, const QVariantMap &initData) +{ + QString nick(nickFromMask(hostmask).toLower()); + if (!_ircUsers.contains(nick)) { + IrcUser *ircuser = ircUserFactory(hostmask); + if (!initData.isEmpty()) { + ircuser->fromVariantMap(initData); + ircuser->setInitialized(); + } + + if (proxy()) + proxy()->synchronize(ircuser); + else + qWarning() << "unable to synchronize new IrcUser" << hostmask << "forgot to call Network::setProxy(SignalProxy *)?"; + + connect(ircuser, SIGNAL(nickSet(QString)), this, SLOT(ircUserNickChanged(QString))); + + _ircUsers[nick] = ircuser; + + SYNC_OTHER(addIrcUser, ARG(hostmask)) + // emit ircUserAdded(hostmask); + emit ircUserAdded(ircuser); + } + + return _ircUsers[nick]; +} + + +IrcUser *Network::ircUser(QString nickname) const +{ + nickname = nickname.toLower(); + if (_ircUsers.contains(nickname)) + return _ircUsers[nickname]; else - qWarning() << "unable to synchronize new IrcChannel" << channelname << "forgot to call Network::setProxy(SignalProxy *)?"; + return 0; +} + + +void Network::removeIrcUser(IrcUser *ircuser) +{ + QString nick = _ircUsers.key(ircuser); + if (nick.isNull()) + return; + + _ircUsers.remove(nick); + disconnect(ircuser, 0, this, 0); + ircuser->deleteLater(); +} + + +void Network::removeIrcChannel(IrcChannel *channel) +{ + QString chanName = _ircChannels.key(channel); + if (chanName.isNull()) + return; + + _ircChannels.remove(chanName); + disconnect(channel, 0, this, 0); + channel->deleteLater(); +} + + +void Network::removeChansAndUsers() +{ + QList users = ircUsers(); + _ircUsers.clear(); + QList channels = ircChannels(); + _ircChannels.clear(); + + foreach(IrcChannel *channel, channels) { + proxy()->detachObject(channel); + disconnect(channel, 0, this, 0); + } + foreach(IrcUser *user, users) { + proxy()->detachObject(user); + disconnect(user, 0, this, 0); + } - _ircChannels[channelname.toLower()] = channel; + // the second loop is needed because quit can have sideffects + foreach(IrcUser *user, users) { + user->quit(); + } - SYNC_OTHER(addIrcChannel, ARG(channelname)) - // emit ircChannelAdded(channelname); - emit ircChannelAdded(channel); - } - return _ircChannels[channelname.toLower()]; + qDeleteAll(users); + qDeleteAll(channels); } -IrcChannel *Network::ircChannel(QString channelname) const { - channelname = channelname.toLower(); - if(_ircChannels.contains(channelname)) - return _ircChannels[channelname]; - else - return 0; + +IrcChannel *Network::newIrcChannel(const QString &channelname, const QVariantMap &initData) +{ + if (!_ircChannels.contains(channelname.toLower())) { + IrcChannel *channel = ircChannelFactory(channelname); + if (!initData.isEmpty()) { + channel->fromVariantMap(initData); + channel->setInitialized(); + } + + if (proxy()) + proxy()->synchronize(channel); + else + qWarning() << "unable to synchronize new IrcChannel" << channelname << "forgot to call Network::setProxy(SignalProxy *)?"; + + _ircChannels[channelname.toLower()] = channel; + + SYNC_OTHER(addIrcChannel, ARG(channelname)) + // emit ircChannelAdded(channelname); + emit ircChannelAdded(channel); + } + return _ircChannels[channelname.toLower()]; } -QByteArray Network::defaultCodecForServer() { - if(_defaultCodecForServer) - return _defaultCodecForServer->name(); - return QByteArray(); + +IrcChannel *Network::ircChannel(QString channelname) const +{ + channelname = channelname.toLower(); + if (_ircChannels.contains(channelname)) + return _ircChannels[channelname]; + else + return 0; } -void Network::setDefaultCodecForServer(const QByteArray &name) { - _defaultCodecForServer = QTextCodec::codecForName(name); + +QByteArray Network::defaultCodecForServer() +{ + if (_defaultCodecForServer) + return _defaultCodecForServer->name(); + return QByteArray(); } -QByteArray Network::defaultCodecForEncoding() { - if(_defaultCodecForEncoding) - return _defaultCodecForEncoding->name(); - return QByteArray(); + +void Network::setDefaultCodecForServer(const QByteArray &name) +{ + _defaultCodecForServer = QTextCodec::codecForName(name); } -void Network::setDefaultCodecForEncoding(const QByteArray &name) { - _defaultCodecForEncoding = QTextCodec::codecForName(name); + +QByteArray Network::defaultCodecForEncoding() +{ + if (_defaultCodecForEncoding) + return _defaultCodecForEncoding->name(); + return QByteArray(); } -QByteArray Network::defaultCodecForDecoding() { - if(_defaultCodecForDecoding) - return _defaultCodecForDecoding->name(); - return QByteArray(); + +void Network::setDefaultCodecForEncoding(const QByteArray &name) +{ + _defaultCodecForEncoding = QTextCodec::codecForName(name); } -void Network::setDefaultCodecForDecoding(const QByteArray &name) { - _defaultCodecForDecoding = QTextCodec::codecForName(name); + +QByteArray Network::defaultCodecForDecoding() +{ + if (_defaultCodecForDecoding) + return _defaultCodecForDecoding->name(); + return QByteArray(); } -QByteArray Network::codecForServer() const { - if(_codecForServer) - return _codecForServer->name(); - return QByteArray(); + +void Network::setDefaultCodecForDecoding(const QByteArray &name) +{ + _defaultCodecForDecoding = QTextCodec::codecForName(name); } -void Network::setCodecForServer(const QByteArray &name) { - setCodecForServer(QTextCodec::codecForName(name)); + +QByteArray Network::codecForServer() const +{ + if (_codecForServer) + return _codecForServer->name(); + return QByteArray(); } -void Network::setCodecForServer(QTextCodec *codec) { - _codecForServer = codec; - QByteArray codecName = codecForServer(); - SYNC_OTHER(setCodecForServer, ARG(codecName)) - emit configChanged(); + +void Network::setCodecForServer(const QByteArray &name) +{ + setCodecForServer(QTextCodec::codecForName(name)); } -QByteArray Network::codecForEncoding() const { - if(_codecForEncoding) - return _codecForEncoding->name(); - return QByteArray(); + +void Network::setCodecForServer(QTextCodec *codec) +{ + _codecForServer = codec; + QByteArray codecName = codecForServer(); + SYNC_OTHER(setCodecForServer, ARG(codecName)) + emit configChanged(); } -void Network::setCodecForEncoding(const QByteArray &name) { - setCodecForEncoding(QTextCodec::codecForName(name)); + +QByteArray Network::codecForEncoding() const +{ + if (_codecForEncoding) + return _codecForEncoding->name(); + return QByteArray(); } -void Network::setCodecForEncoding(QTextCodec *codec) { - _codecForEncoding = codec; - QByteArray codecName = codecForEncoding(); - SYNC_OTHER(setCodecForEncoding, ARG(codecName)) - emit configChanged(); + +void Network::setCodecForEncoding(const QByteArray &name) +{ + setCodecForEncoding(QTextCodec::codecForName(name)); } -QByteArray Network::codecForDecoding() const { - if(_codecForDecoding) - return _codecForDecoding->name(); - else return QByteArray(); + +void Network::setCodecForEncoding(QTextCodec *codec) +{ + _codecForEncoding = codec; + QByteArray codecName = codecForEncoding(); + SYNC_OTHER(setCodecForEncoding, ARG(codecName)) + emit configChanged(); } -void Network::setCodecForDecoding(const QByteArray &name) { - setCodecForDecoding(QTextCodec::codecForName(name)); + +QByteArray Network::codecForDecoding() const +{ + if (_codecForDecoding) + return _codecForDecoding->name(); + else return QByteArray(); } -void Network::setCodecForDecoding(QTextCodec *codec) { - _codecForDecoding = codec; - QByteArray codecName = codecForDecoding(); - SYNC_OTHER(setCodecForDecoding, ARG(codecName)) - emit configChanged(); + +void Network::setCodecForDecoding(const QByteArray &name) +{ + setCodecForDecoding(QTextCodec::codecForName(name)); } -// FIXME use server encoding if appropriate -QString Network::decodeString(const QByteArray &text) const { - if(_codecForDecoding) - return ::decodeString(text, _codecForDecoding); - else return ::decodeString(text, _defaultCodecForDecoding); + +void Network::setCodecForDecoding(QTextCodec *codec) +{ + _codecForDecoding = codec; + QByteArray codecName = codecForDecoding(); + SYNC_OTHER(setCodecForDecoding, ARG(codecName)) + emit configChanged(); } -QByteArray Network::encodeString(const QString &string) const { - if(_codecForEncoding) { - return _codecForEncoding->fromUnicode(string); - } - if(_defaultCodecForEncoding) { - return _defaultCodecForEncoding->fromUnicode(string); - } - return string.toAscii(); + +// FIXME use server encoding if appropriate +QString Network::decodeString(const QByteArray &text) const +{ + if (_codecForDecoding) + return ::decodeString(text, _codecForDecoding); + else return ::decodeString(text, _defaultCodecForDecoding); } -QString Network::decodeServerString(const QByteArray &text) const { - if(_codecForServer) - return ::decodeString(text, _codecForServer); - else - return ::decodeString(text, _defaultCodecForServer); + +QByteArray Network::encodeString(const QString &string) const +{ + if (_codecForEncoding) { + return _codecForEncoding->fromUnicode(string); + } + if (_defaultCodecForEncoding) { + return _defaultCodecForEncoding->fromUnicode(string); + } + return string.toAscii(); } -QByteArray Network::encodeServerString(const QString &string) const { - if(_codecForServer) { - return _codecForServer->fromUnicode(string); - } - if(_defaultCodecForServer) { - return _defaultCodecForServer->fromUnicode(string); - } - return string.toAscii(); + +QString Network::decodeServerString(const QByteArray &text) const +{ + if (_codecForServer) + return ::decodeString(text, _codecForServer); + else + return ::decodeString(text, _defaultCodecForServer); } -/*** Handle networks.ini ***/ -QStringList Network::presetNetworks(bool onlyDefault) { - // lazily find the file, make sure to not call one of the other preset functions first (they'll fail else) - if(_networksIniPath.isNull()) { - _networksIniPath = Quassel::findDataFilePath("networks.ini"); - if(_networksIniPath.isNull()) { - _networksIniPath = ""; // now we won't check again, as it's not null anymore - return QStringList(); +QByteArray Network::encodeServerString(const QString &string) const +{ + if (_codecForServer) { + return _codecForServer->fromUnicode(string); } - } - if(!_networksIniPath.isEmpty()) { - QSettings s(_networksIniPath, QSettings::IniFormat); - QStringList networks = s.childGroups(); - if(!networks.isEmpty()) { - // we sort the list case-insensitive - QMap sorted; - foreach(QString net, networks) { - if(onlyDefault && !s.value(QString("%1/Default").arg(net)).toBool()) - continue; - sorted[net.toLower()] = net; - } - return sorted.values(); + if (_defaultCodecForServer) { + return _defaultCodecForServer->fromUnicode(string); } - } - return QStringList(); + return string.toAscii(); } -QStringList Network::presetDefaultChannels(const QString &networkName) { - if(_networksIniPath.isEmpty()) // be sure to have called presetNetworks() first, else this always fails + +/*** Handle networks.ini ***/ + +QStringList Network::presetNetworks(bool onlyDefault) +{ + // lazily find the file, make sure to not call one of the other preset functions first (they'll fail else) + if (_networksIniPath.isNull()) { + _networksIniPath = Quassel::findDataFilePath("networks.ini"); + if (_networksIniPath.isNull()) { + _networksIniPath = ""; // now we won't check again, as it's not null anymore + return QStringList(); + } + } + if (!_networksIniPath.isEmpty()) { + QSettings s(_networksIniPath, QSettings::IniFormat); + QStringList networks = s.childGroups(); + if (!networks.isEmpty()) { + // we sort the list case-insensitive + QMap sorted; + foreach(QString net, networks) { + if (onlyDefault && !s.value(QString("%1/Default").arg(net)).toBool()) + continue; + sorted[net.toLower()] = net; + } + return sorted.values(); + } + } return QStringList(); - QSettings s(_networksIniPath, QSettings::IniFormat); - return s.value(QString("%1/DefaultChannels").arg(networkName)).toStringList(); } -NetworkInfo Network::networkInfoFromPreset(const QString &networkName) { - NetworkInfo info; - if(!_networksIniPath.isEmpty()) { - info.networkName = networkName; + +QStringList Network::presetDefaultChannels(const QString &networkName) +{ + if (_networksIniPath.isEmpty()) // be sure to have called presetNetworks() first, else this always fails + return QStringList(); QSettings s(_networksIniPath, QSettings::IniFormat); - s.beginGroup(info.networkName); - foreach(QString server, s.value("Servers").toStringList()) { - bool ssl = false; - QStringList splitserver = server.split(':', QString::SkipEmptyParts); - if(splitserver.count() != 2) { - qWarning() << "Invalid server entry in networks.conf:" << server; - continue; - } - if(splitserver[1].at(0) == '+') - ssl = true; - uint port = splitserver[1].toUInt(); - if(!port) { - qWarning() << "Invalid port entry in networks.conf:" << server; - continue; - } - info.serverList << Network::Server(splitserver[0].trimmed(), port, QString(), ssl); + return s.value(QString("%1/DefaultChannels").arg(networkName)).toStringList(); +} + + +NetworkInfo Network::networkInfoFromPreset(const QString &networkName) +{ + NetworkInfo info; + if (!_networksIniPath.isEmpty()) { + info.networkName = networkName; + QSettings s(_networksIniPath, QSettings::IniFormat); + s.beginGroup(info.networkName); + foreach(QString server, s.value("Servers").toStringList()) { + bool ssl = false; + QStringList splitserver = server.split(':', QString::SkipEmptyParts); + if (splitserver.count() != 2) { + qWarning() << "Invalid server entry in networks.conf:" << server; + continue; + } + if (splitserver[1].at(0) == '+') + ssl = true; + uint port = splitserver[1].toUInt(); + if (!port) { + qWarning() << "Invalid port entry in networks.conf:" << server; + continue; + } + info.serverList << Network::Server(splitserver[0].trimmed(), port, QString(), ssl); + } } - } - return info; + return info; } + // ==================== // Public Slots: // ==================== -void Network::setNetworkName(const QString &networkName) { - _networkName = networkName; - SYNC(ARG(networkName)) - emit networkNameSet(networkName); - emit configChanged(); +void Network::setNetworkName(const QString &networkName) +{ + _networkName = networkName; + SYNC(ARG(networkName)) + emit networkNameSet(networkName); + emit configChanged(); } -void Network::setCurrentServer(const QString ¤tServer) { - _currentServer = currentServer; - SYNC(ARG(currentServer)) - emit currentServerSet(currentServer); + +void Network::setCurrentServer(const QString ¤tServer) +{ + _currentServer = currentServer; + SYNC(ARG(currentServer)) + emit currentServerSet(currentServer); } -void Network::setConnected(bool connected) { - if(_connected == connected) - return; - _connected = connected; - if(!connected) { - setMyNick(QString()); - setCurrentServer(QString()); - removeChansAndUsers(); - } - SYNC(ARG(connected)) - emit connectedSet(connected); +void Network::setConnected(bool connected) +{ + if (_connected == connected) + return; + + _connected = connected; + if (!connected) { + setMyNick(QString()); + setCurrentServer(QString()); + removeChansAndUsers(); + } + SYNC(ARG(connected)) + emit connectedSet(connected); } + //void Network::setConnectionState(ConnectionState state) { -void Network::setConnectionState(int state) { - _connectionState = (ConnectionState)state; - //qDebug() << "netstate" << networkId() << networkName() << state; - SYNC(ARG(state)) - emit connectionStateSet(_connectionState); +void Network::setConnectionState(int state) +{ + _connectionState = (ConnectionState)state; + //qDebug() << "netstate" << networkId() << networkName() << state; + SYNC(ARG(state)) + emit connectionStateSet(_connectionState); } -void Network::setMyNick(const QString &nickname) { - _myNick = nickname; - if(!_myNick.isEmpty() && !ircUser(myNick())) { - newIrcUser(myNick()); - } - SYNC(ARG(nickname)) - emit myNickSet(nickname); + +void Network::setMyNick(const QString &nickname) +{ + _myNick = nickname; + if (!_myNick.isEmpty() && !ircUser(myNick())) { + newIrcUser(myNick()); + } + SYNC(ARG(nickname)) + emit myNickSet(nickname); } -void Network::setLatency(int latency) { - if(_latency == latency) - return; - _latency = latency; - SYNC(ARG(latency)) + +void Network::setLatency(int latency) +{ + if (_latency == latency) + return; + _latency = latency; + SYNC(ARG(latency)) } -void Network::setIdentity(IdentityId id) { - _identity = id; - SYNC(ARG(id)) - emit identitySet(id); - emit configChanged(); + +void Network::setIdentity(IdentityId id) +{ + _identity = id; + SYNC(ARG(id)) + emit identitySet(id); + emit configChanged(); } -void Network::setServerList(const QVariantList &serverList) { - _serverList = fromVariantList(serverList); - SYNC(ARG(serverList)) - emit configChanged(); + +void Network::setServerList(const QVariantList &serverList) +{ + _serverList = fromVariantList(serverList); + SYNC(ARG(serverList)) + emit configChanged(); } -void Network::setUseRandomServer(bool use) { - _useRandomServer = use; - SYNC(ARG(use)) - emit configChanged(); + +void Network::setUseRandomServer(bool use) +{ + _useRandomServer = use; + SYNC(ARG(use)) + emit configChanged(); } -void Network::setPerform(const QStringList &perform) { - _perform = perform; - SYNC(ARG(perform)) - emit configChanged(); + +void Network::setPerform(const QStringList &perform) +{ + _perform = perform; + SYNC(ARG(perform)) + emit configChanged(); } -void Network::setUseAutoIdentify(bool use) { - _useAutoIdentify = use; - SYNC(ARG(use)) - emit configChanged(); + +void Network::setUseAutoIdentify(bool use) +{ + _useAutoIdentify = use; + SYNC(ARG(use)) + emit configChanged(); } -void Network::setAutoIdentifyService(const QString &service) { - _autoIdentifyService = service; - SYNC(ARG(service)) - emit configChanged(); + +void Network::setAutoIdentifyService(const QString &service) +{ + _autoIdentifyService = service; + SYNC(ARG(service)) + emit configChanged(); } -void Network::setAutoIdentifyPassword(const QString &password) { - _autoIdentifyPassword = password; - SYNC(ARG(password)) - emit configChanged(); + +void Network::setAutoIdentifyPassword(const QString &password) +{ + _autoIdentifyPassword = password; + SYNC(ARG(password)) + emit configChanged(); } -void Network::setUseSasl(bool use) { - _useSasl = use; - SYNC(ARG(use)) - emit configChanged(); + +void Network::setUseSasl(bool use) +{ + _useSasl = use; + SYNC(ARG(use)) + emit configChanged(); } -void Network::setSaslAccount(const QString &account) { - _saslAccount = account; - SYNC(ARG(account)) - emit configChanged(); + +void Network::setSaslAccount(const QString &account) +{ + _saslAccount = account; + SYNC(ARG(account)) + emit configChanged(); } -void Network::setSaslPassword(const QString &password) { - _saslPassword = password; - SYNC(ARG(password)) - emit configChanged(); + +void Network::setSaslPassword(const QString &password) +{ + _saslPassword = password; + SYNC(ARG(password)) + emit configChanged(); } -void Network::setUseAutoReconnect(bool use) { - _useAutoReconnect = use; - SYNC(ARG(use)) - emit configChanged(); + +void Network::setUseAutoReconnect(bool use) +{ + _useAutoReconnect = use; + SYNC(ARG(use)) + emit configChanged(); } -void Network::setAutoReconnectInterval(quint32 interval) { - _autoReconnectInterval = interval; - SYNC(ARG(interval)) - emit configChanged(); + +void Network::setAutoReconnectInterval(quint32 interval) +{ + _autoReconnectInterval = interval; + SYNC(ARG(interval)) + emit configChanged(); } -void Network::setAutoReconnectRetries(quint16 retries) { - _autoReconnectRetries = retries; - SYNC(ARG(retries)) - emit configChanged(); + +void Network::setAutoReconnectRetries(quint16 retries) +{ + _autoReconnectRetries = retries; + SYNC(ARG(retries)) + emit configChanged(); } -void Network::setUnlimitedReconnectRetries(bool unlimited) { - _unlimitedReconnectRetries = unlimited; - SYNC(ARG(unlimited)) - emit configChanged(); + +void Network::setUnlimitedReconnectRetries(bool unlimited) +{ + _unlimitedReconnectRetries = unlimited; + SYNC(ARG(unlimited)) + emit configChanged(); } -void Network::setRejoinChannels(bool rejoin) { - _rejoinChannels = rejoin; - SYNC(ARG(rejoin)) - emit configChanged(); + +void Network::setRejoinChannels(bool rejoin) +{ + _rejoinChannels = rejoin; + SYNC(ARG(rejoin)) + emit configChanged(); } -void Network::addSupport(const QString ¶m, const QString &value) { - if(!_supports.contains(param)) { - _supports[param] = value; - SYNC(ARG(param), ARG(value)) - } + +void Network::addSupport(const QString ¶m, const QString &value) +{ + if (!_supports.contains(param)) { + _supports[param] = value; + SYNC(ARG(param), ARG(value)) + } } -void Network::removeSupport(const QString ¶m) { - if(_supports.contains(param)) { - _supports.remove(param); - SYNC(ARG(param)) - } + +void Network::removeSupport(const QString ¶m) +{ + if (_supports.contains(param)) { + _supports.remove(param); + SYNC(ARG(param)) + } } -QVariantMap Network::initSupports() const { - QVariantMap supports; - QHashIterator iter(_supports); - while(iter.hasNext()) { - iter.next(); - supports[iter.key()] = iter.value(); - } - return supports; + +QVariantMap Network::initSupports() const +{ + QVariantMap supports; + QHashIterator iter(_supports); + while (iter.hasNext()) { + iter.next(); + supports[iter.key()] = iter.value(); + } + return supports; } -QVariantMap Network::initIrcUsersAndChannels() const { - QVariantMap usersAndChannels; - QVariantMap users; - QVariantMap channels; - QHash::const_iterator userIter = _ircUsers.constBegin(); - QHash::const_iterator userIterEnd = _ircUsers.constEnd(); - while(userIter != userIterEnd) { - users[userIter.value()->hostmask()] = userIter.value()->toVariantMap(); - userIter++; - } - usersAndChannels["users"] = users; +QVariantMap Network::initIrcUsersAndChannels() const +{ + QVariantMap usersAndChannels; + QVariantMap users; + QVariantMap channels; + + QHash::const_iterator userIter = _ircUsers.constBegin(); + QHash::const_iterator userIterEnd = _ircUsers.constEnd(); + while (userIter != userIterEnd) { + users[userIter.value()->hostmask()] = userIter.value()->toVariantMap(); + userIter++; + } + usersAndChannels["users"] = users; - QHash::const_iterator channelIter = _ircChannels.constBegin(); - QHash::const_iterator channelIterEnd = _ircChannels.constEnd(); - while(channelIter != channelIterEnd) { - channels[channelIter.value()->name()] = channelIter.value()->toVariantMap(); - channelIter++; - } - usersAndChannels["channels"] = channels; + QHash::const_iterator channelIter = _ircChannels.constBegin(); + QHash::const_iterator channelIterEnd = _ircChannels.constEnd(); + while (channelIter != channelIterEnd) { + channels[channelIter.value()->name()] = channelIter.value()->toVariantMap(); + channelIter++; + } + usersAndChannels["channels"] = channels; - return usersAndChannels; + return usersAndChannels; } -void Network::initSetIrcUsersAndChannels(const QVariantMap &usersAndChannels) { - Q_ASSERT(proxy()); - if(isInitialized()) { - qWarning() << "Network" << networkId() << "received init data for users and channels allthough there allready are known users or channels!"; - return; - } - QVariantMap users = usersAndChannels.value("users").toMap(); - QVariantMap::const_iterator userIter = users.constBegin(); - QVariantMap::const_iterator userIterEnd = users.constEnd(); - while(userIter != userIterEnd) { - newIrcUser(userIter.key(), userIter.value().toMap()); - userIter++; - } +void Network::initSetIrcUsersAndChannels(const QVariantMap &usersAndChannels) +{ + Q_ASSERT(proxy()); + if (isInitialized()) { + qWarning() << "Network" << networkId() << "received init data for users and channels allthough there allready are known users or channels!"; + return; + } + + QVariantMap users = usersAndChannels.value("users").toMap(); + QVariantMap::const_iterator userIter = users.constBegin(); + QVariantMap::const_iterator userIterEnd = users.constEnd(); + while (userIter != userIterEnd) { + newIrcUser(userIter.key(), userIter.value().toMap()); + userIter++; + } - QVariantMap channels = usersAndChannels.value("channels").toMap(); - QVariantMap::const_iterator channelIter = channels.constBegin(); - QVariantMap::const_iterator channelIterEnd = channels.constEnd(); - while(channelIter != channelIterEnd) { - newIrcChannel(channelIter.key(), channelIter.value().toMap()); - channelIter++; - } + QVariantMap channels = usersAndChannels.value("channels").toMap(); + QVariantMap::const_iterator channelIter = channels.constBegin(); + QVariantMap::const_iterator channelIterEnd = channels.constEnd(); + while (channelIter != channelIterEnd) { + newIrcChannel(channelIter.key(), channelIter.value().toMap()); + channelIter++; + } } -void Network::initSetSupports(const QVariantMap &supports) { - QMapIterator iter(supports); - while(iter.hasNext()) { - iter.next(); - addSupport(iter.key(), iter.value().toString()); - } + +void Network::initSetSupports(const QVariantMap &supports) +{ + QMapIterator iter(supports); + while (iter.hasNext()) { + iter.next(); + addSupport(iter.key(), iter.value().toString()); + } } -IrcUser *Network::updateNickFromMask(const QString &mask) { - QString nick(nickFromMask(mask).toLower()); - IrcUser *ircuser; - if(_ircUsers.contains(nick)) { - ircuser = _ircUsers[nick]; - ircuser->updateHostmask(mask); - } else { - ircuser = newIrcUser(mask); - } - return ircuser; +IrcUser *Network::updateNickFromMask(const QString &mask) +{ + QString nick(nickFromMask(mask).toLower()); + IrcUser *ircuser; + + if (_ircUsers.contains(nick)) { + ircuser = _ircUsers[nick]; + ircuser->updateHostmask(mask); + } + else { + ircuser = newIrcUser(mask); + } + return ircuser; } -void Network::ircUserNickChanged(QString newnick) { - QString oldnick = _ircUsers.key(qobject_cast(sender())); - if(oldnick.isNull()) - return; +void Network::ircUserNickChanged(QString newnick) +{ + QString oldnick = _ircUsers.key(qobject_cast(sender())); + + if (oldnick.isNull()) + return; - if(newnick.toLower() != oldnick) _ircUsers[newnick.toLower()] = _ircUsers.take(oldnick); + if (newnick.toLower() != oldnick) _ircUsers[newnick.toLower()] = _ircUsers.take(oldnick); - if(myNick().toLower() == oldnick) - setMyNick(newnick); + if (myNick().toLower() == oldnick) + setMyNick(newnick); } -void Network::emitConnectionError(const QString &errorMsg) { - emit connectionError(errorMsg); + +void Network::emitConnectionError(const QString &errorMsg) +{ + emit connectionError(errorMsg); } + // ==================== // Private: // ==================== -void Network::determinePrefixes() const { - // seems like we have to construct them first - QString prefix = support("PREFIX"); - - if(prefix.startsWith("(") && prefix.contains(")")) { - _prefixes = prefix.section(")", 1); - _prefixModes = prefix.mid(1).section(")", 0, 0); - } else { - QString defaultPrefixes("~&@%+"); - QString defaultPrefixModes("qaohv"); - - if(prefix.isEmpty()) { - _prefixes = defaultPrefixes; - _prefixModes = defaultPrefixModes; - return; - } - // clear the existing modes, just in case we're run multiple times - _prefixes = QString(); - _prefixModes = QString(); - - // we just assume that in PREFIX are only prefix chars stored - for(int i = 0; i < defaultPrefixes.size(); i++) { - if(prefix.contains(defaultPrefixes[i])) { - _prefixes += defaultPrefixes[i]; - _prefixModes += defaultPrefixModes[i]; - } +void Network::determinePrefixes() const +{ + // seems like we have to construct them first + QString prefix = support("PREFIX"); + + if (prefix.startsWith("(") && prefix.contains(")")) { + _prefixes = prefix.section(")", 1); + _prefixModes = prefix.mid(1).section(")", 0, 0); } - // check for success - if(!_prefixes.isNull()) - return; - - // well... our assumption was obviously wrong... - // check if it's only prefix modes - for(int i = 0; i < defaultPrefixes.size(); i++) { - if(prefix.contains(defaultPrefixModes[i])) { - _prefixes += defaultPrefixes[i]; - _prefixModes += defaultPrefixModes[i]; - } + else { + QString defaultPrefixes("~&@%+"); + QString defaultPrefixModes("qaohv"); + + if (prefix.isEmpty()) { + _prefixes = defaultPrefixes; + _prefixModes = defaultPrefixModes; + return; + } + // clear the existing modes, just in case we're run multiple times + _prefixes = QString(); + _prefixModes = QString(); + + // we just assume that in PREFIX are only prefix chars stored + for (int i = 0; i < defaultPrefixes.size(); i++) { + if (prefix.contains(defaultPrefixes[i])) { + _prefixes += defaultPrefixes[i]; + _prefixModes += defaultPrefixModes[i]; + } + } + // check for success + if (!_prefixes.isNull()) + return; + + // well... our assumption was obviously wrong... + // check if it's only prefix modes + for (int i = 0; i < defaultPrefixes.size(); i++) { + if (prefix.contains(defaultPrefixModes[i])) { + _prefixes += defaultPrefixes[i]; + _prefixModes += defaultPrefixModes[i]; + } + } + // now we've done all we've could... } - // now we've done all we've could... - } } + /************************************************************************ * NetworkInfo ************************************************************************/ NetworkInfo::NetworkInfo() -: networkId(0), - identity(1), - useRandomServer(false), - useAutoIdentify(false), - autoIdentifyService("NickServ"), - useSasl(false), - useAutoReconnect(true), - autoReconnectInterval(60), - autoReconnectRetries(20), - unlimitedReconnectRetries(false), - rejoinChannels(true) -{ - -} - -bool NetworkInfo::operator==(const NetworkInfo &other) const { - if(networkId != other.networkId) return false; - if(networkName != other.networkName) return false; - if(identity != other.identity) return false; - if(codecForServer != other.codecForServer) return false; - if(codecForEncoding != other.codecForEncoding) return false; - if(codecForDecoding != other.codecForDecoding) return false; - if(serverList != other.serverList) return false; - if(useRandomServer != other.useRandomServer) return false; - if(perform != other.perform) return false; - if(useAutoIdentify != other.useAutoIdentify) return false; - if(autoIdentifyService != other.autoIdentifyService) return false; - if(autoIdentifyPassword != other.autoIdentifyPassword) return false; - if(useSasl != other.useSasl) return false; - if(saslAccount != other.saslAccount) return false; - if(saslPassword != other.saslPassword) return false; - if(useAutoReconnect != other.useAutoReconnect) return false; - if(autoReconnectInterval != other.autoReconnectInterval) return false; - if(autoReconnectRetries != other.autoReconnectRetries) return false; - if(unlimitedReconnectRetries != other.unlimitedReconnectRetries) return false; - if(rejoinChannels != other.rejoinChannels) return false; - return true; -} - -bool NetworkInfo::operator!=(const NetworkInfo &other) const { - return !(*this == other); -} - -QDataStream &operator<<(QDataStream &out, const NetworkInfo &info) { - QVariantMap i; - i["NetworkId"] = QVariant::fromValue(info.networkId); - i["NetworkName"] = info.networkName; - i["Identity"] = QVariant::fromValue(info.identity); - i["CodecForServer"] = info.codecForServer; - i["CodecForEncoding"] = info.codecForEncoding; - i["CodecForDecoding"] = info.codecForDecoding; - i["ServerList"] = toVariantList(info.serverList); - i["UseRandomServer"] = info.useRandomServer; - i["Perform"] = info.perform; - i["UseAutoIdentify"] = info.useAutoIdentify; - i["AutoIdentifyService"] = info.autoIdentifyService; - i["AutoIdentifyPassword"] = info.autoIdentifyPassword; - i["UseSasl"] = info.useSasl; - i["SaslAccount"] = info.saslAccount; - i["SaslPassword"] = info.saslPassword; - i["UseAutoReconnect"] = info.useAutoReconnect; - i["AutoReconnectInterval"] = info.autoReconnectInterval; - i["AutoReconnectRetries"] = info.autoReconnectRetries; - i["UnlimitedReconnectRetries"] = info.unlimitedReconnectRetries; - i["RejoinChannels"] = info.rejoinChannels; - out << i; - return out; -} - -QDataStream &operator>>(QDataStream &in, NetworkInfo &info) { - QVariantMap i; - in >> i; - info.networkId = i["NetworkId"].value(); - info.networkName = i["NetworkName"].toString(); - info.identity = i["Identity"].value(); - info.codecForServer = i["CodecForServer"].toByteArray(); - info.codecForEncoding = i["CodecForEncoding"].toByteArray(); - info.codecForDecoding = i["CodecForDecoding"].toByteArray(); - info.serverList = fromVariantList(i["ServerList"].toList()); - info.useRandomServer = i["UseRandomServer"].toBool(); - info.perform = i["Perform"].toStringList(); - info.useAutoIdentify = i["UseAutoIdentify"].toBool(); - info.autoIdentifyService = i["AutoIdentifyService"].toString(); - info.autoIdentifyPassword = i["AutoIdentifyPassword"].toString(); - info.useSasl = i["UseSasl"].toBool(); - info.saslAccount = i["SaslAccount"].toString(); - info.saslPassword = i["SaslPassword"].toString(); - info.useAutoReconnect = i["UseAutoReconnect"].toBool(); - info.autoReconnectInterval = i["AutoReconnectInterval"].toUInt(); - info.autoReconnectRetries = i["AutoReconnectRetries"].toInt(); - info.unlimitedReconnectRetries = i["UnlimitedReconnectRetries"].toBool(); - info.rejoinChannels = i["RejoinChannels"].toBool(); - return in; -} - -QDebug operator<<(QDebug dbg, const NetworkInfo &i) { - dbg.nospace() << "(id = " << i.networkId << " name = " << i.networkName << " identity = " << i.identity - << " codecForServer = " << i.codecForServer << " codecForEncoding = " << i.codecForEncoding << " codecForDecoding = " << i.codecForDecoding - << " serverList = " << i.serverList << " useRandomServer = " << i.useRandomServer << " perform = " << i.perform - << " useAutoIdentify = " << i.useAutoIdentify << " autoIdentifyService = " << i.autoIdentifyService << " autoIdentifyPassword = " << i.autoIdentifyPassword - << " useSasl = " << i.useSasl << " saslAccount = " << i.saslAccount << " saslPassword = " << i.saslPassword - << " useAutoReconnect = " << i.useAutoReconnect << " autoReconnectInterval = " << i.autoReconnectInterval - << " autoReconnectRetries = " << i.autoReconnectRetries << " unlimitedReconnectRetries = " << i.unlimitedReconnectRetries - << " rejoinChannels = " << i.rejoinChannels << ")"; - return dbg.space(); -} - -QDataStream &operator<<(QDataStream &out, const Network::Server &server) { - QVariantMap serverMap; - serverMap["Host"] = server.host; - serverMap["Port"] = server.port; - serverMap["Password"] = server.password; - serverMap["UseSSL"] = server.useSsl; - serverMap["sslVersion"] = server.sslVersion; - serverMap["UseProxy"] = server.useProxy; - serverMap["ProxyType"] = server.proxyType; - serverMap["ProxyHost"] = server.proxyHost; - serverMap["ProxyPort"] = server.proxyPort; - serverMap["ProxyUser"] = server.proxyUser; - serverMap["ProxyPass"] = server.proxyPass; - out << serverMap; - return out; -} - -QDataStream &operator>>(QDataStream &in, Network::Server &server) { - QVariantMap serverMap; - in >> serverMap; - server.host = serverMap["Host"].toString(); - server.port = serverMap["Port"].toUInt(); - server.password = serverMap["Password"].toString(); - server.useSsl = serverMap["UseSSL"].toBool(); - server.sslVersion = serverMap["sslVersion"].toInt(); - server.useProxy = serverMap["UseProxy"].toBool(); - server.proxyType = serverMap["ProxyType"].toInt(); - server.proxyHost = serverMap["ProxyHost"].toString(); - server.proxyPort = serverMap["ProxyPort"].toUInt(); - server.proxyUser = serverMap["ProxyUser"].toString(); - server.proxyPass = serverMap["ProxyPass"].toString(); - return in; -} - - -bool Network::Server::operator==(const Server &other) const { - if(host != other.host) return false; - if(port != other.port) return false; - if(password != other.password) return false; - if(useSsl != other.useSsl) return false; - if(sslVersion != other.sslVersion) return false; - if(useProxy != other.useProxy) return false; - if(proxyType != other.proxyType) return false; - if(proxyHost != other.proxyHost) return false; - if(proxyPort != other.proxyPort) return false; - if(proxyUser != other.proxyUser) return false; - if(proxyPass != other.proxyPass) return false; - return true; -} - -bool Network::Server::operator!=(const Server &other) const { - return !(*this == other); -} - -QDebug operator<<(QDebug dbg, const Network::Server &server) { - dbg.nospace() << "Server(host = " << server.host << ":" << server.port << ", useSsl = " << server.useSsl << ")"; - return dbg.space(); + : networkId(0), + identity(1), + useRandomServer(false), + useAutoIdentify(false), + autoIdentifyService("NickServ"), + useSasl(false), + useAutoReconnect(true), + autoReconnectInterval(60), + autoReconnectRetries(20), + unlimitedReconnectRetries(false), + rejoinChannels(true) +{ +} + + +bool NetworkInfo::operator==(const NetworkInfo &other) const +{ + if (networkId != other.networkId) return false; + if (networkName != other.networkName) return false; + if (identity != other.identity) return false; + if (codecForServer != other.codecForServer) return false; + if (codecForEncoding != other.codecForEncoding) return false; + if (codecForDecoding != other.codecForDecoding) return false; + if (serverList != other.serverList) return false; + if (useRandomServer != other.useRandomServer) return false; + if (perform != other.perform) return false; + if (useAutoIdentify != other.useAutoIdentify) return false; + if (autoIdentifyService != other.autoIdentifyService) return false; + if (autoIdentifyPassword != other.autoIdentifyPassword) return false; + if (useSasl != other.useSasl) return false; + if (saslAccount != other.saslAccount) return false; + if (saslPassword != other.saslPassword) return false; + if (useAutoReconnect != other.useAutoReconnect) return false; + if (autoReconnectInterval != other.autoReconnectInterval) return false; + if (autoReconnectRetries != other.autoReconnectRetries) return false; + if (unlimitedReconnectRetries != other.unlimitedReconnectRetries) return false; + if (rejoinChannels != other.rejoinChannels) return false; + return true; +} + + +bool NetworkInfo::operator!=(const NetworkInfo &other) const +{ + return !(*this == other); +} + + +QDataStream &operator<<(QDataStream &out, const NetworkInfo &info) +{ + QVariantMap i; + i["NetworkId"] = QVariant::fromValue(info.networkId); + i["NetworkName"] = info.networkName; + i["Identity"] = QVariant::fromValue(info.identity); + i["CodecForServer"] = info.codecForServer; + i["CodecForEncoding"] = info.codecForEncoding; + i["CodecForDecoding"] = info.codecForDecoding; + i["ServerList"] = toVariantList(info.serverList); + i["UseRandomServer"] = info.useRandomServer; + i["Perform"] = info.perform; + i["UseAutoIdentify"] = info.useAutoIdentify; + i["AutoIdentifyService"] = info.autoIdentifyService; + i["AutoIdentifyPassword"] = info.autoIdentifyPassword; + i["UseSasl"] = info.useSasl; + i["SaslAccount"] = info.saslAccount; + i["SaslPassword"] = info.saslPassword; + i["UseAutoReconnect"] = info.useAutoReconnect; + i["AutoReconnectInterval"] = info.autoReconnectInterval; + i["AutoReconnectRetries"] = info.autoReconnectRetries; + i["UnlimitedReconnectRetries"] = info.unlimitedReconnectRetries; + i["RejoinChannels"] = info.rejoinChannels; + out << i; + return out; +} + + +QDataStream &operator>>(QDataStream &in, NetworkInfo &info) +{ + QVariantMap i; + in >> i; + info.networkId = i["NetworkId"].value(); + info.networkName = i["NetworkName"].toString(); + info.identity = i["Identity"].value(); + info.codecForServer = i["CodecForServer"].toByteArray(); + info.codecForEncoding = i["CodecForEncoding"].toByteArray(); + info.codecForDecoding = i["CodecForDecoding"].toByteArray(); + info.serverList = fromVariantList(i["ServerList"].toList()); + info.useRandomServer = i["UseRandomServer"].toBool(); + info.perform = i["Perform"].toStringList(); + info.useAutoIdentify = i["UseAutoIdentify"].toBool(); + info.autoIdentifyService = i["AutoIdentifyService"].toString(); + info.autoIdentifyPassword = i["AutoIdentifyPassword"].toString(); + info.useSasl = i["UseSasl"].toBool(); + info.saslAccount = i["SaslAccount"].toString(); + info.saslPassword = i["SaslPassword"].toString(); + info.useAutoReconnect = i["UseAutoReconnect"].toBool(); + info.autoReconnectInterval = i["AutoReconnectInterval"].toUInt(); + info.autoReconnectRetries = i["AutoReconnectRetries"].toInt(); + info.unlimitedReconnectRetries = i["UnlimitedReconnectRetries"].toBool(); + info.rejoinChannels = i["RejoinChannels"].toBool(); + return in; +} + + +QDebug operator<<(QDebug dbg, const NetworkInfo &i) +{ + dbg.nospace() << "(id = " << i.networkId << " name = " << i.networkName << " identity = " << i.identity + << " codecForServer = " << i.codecForServer << " codecForEncoding = " << i.codecForEncoding << " codecForDecoding = " << i.codecForDecoding + << " serverList = " << i.serverList << " useRandomServer = " << i.useRandomServer << " perform = " << i.perform + << " useAutoIdentify = " << i.useAutoIdentify << " autoIdentifyService = " << i.autoIdentifyService << " autoIdentifyPassword = " << i.autoIdentifyPassword + << " useSasl = " << i.useSasl << " saslAccount = " << i.saslAccount << " saslPassword = " << i.saslPassword + << " useAutoReconnect = " << i.useAutoReconnect << " autoReconnectInterval = " << i.autoReconnectInterval + << " autoReconnectRetries = " << i.autoReconnectRetries << " unlimitedReconnectRetries = " << i.unlimitedReconnectRetries + << " rejoinChannels = " << i.rejoinChannels << ")"; + return dbg.space(); +} + + +QDataStream &operator<<(QDataStream &out, const Network::Server &server) +{ + QVariantMap serverMap; + serverMap["Host"] = server.host; + serverMap["Port"] = server.port; + serverMap["Password"] = server.password; + serverMap["UseSSL"] = server.useSsl; + serverMap["sslVersion"] = server.sslVersion; + serverMap["UseProxy"] = server.useProxy; + serverMap["ProxyType"] = server.proxyType; + serverMap["ProxyHost"] = server.proxyHost; + serverMap["ProxyPort"] = server.proxyPort; + serverMap["ProxyUser"] = server.proxyUser; + serverMap["ProxyPass"] = server.proxyPass; + out << serverMap; + return out; +} + + +QDataStream &operator>>(QDataStream &in, Network::Server &server) +{ + QVariantMap serverMap; + in >> serverMap; + server.host = serverMap["Host"].toString(); + server.port = serverMap["Port"].toUInt(); + server.password = serverMap["Password"].toString(); + server.useSsl = serverMap["UseSSL"].toBool(); + server.sslVersion = serverMap["sslVersion"].toInt(); + server.useProxy = serverMap["UseProxy"].toBool(); + server.proxyType = serverMap["ProxyType"].toInt(); + server.proxyHost = serverMap["ProxyHost"].toString(); + server.proxyPort = serverMap["ProxyPort"].toUInt(); + server.proxyUser = serverMap["ProxyUser"].toString(); + server.proxyPass = serverMap["ProxyPass"].toString(); + return in; +} + + +bool Network::Server::operator==(const Server &other) const +{ + if (host != other.host) return false; + if (port != other.port) return false; + if (password != other.password) return false; + if (useSsl != other.useSsl) return false; + if (sslVersion != other.sslVersion) return false; + if (useProxy != other.useProxy) return false; + if (proxyType != other.proxyType) return false; + if (proxyHost != other.proxyHost) return false; + if (proxyPort != other.proxyPort) return false; + if (proxyUser != other.proxyUser) return false; + if (proxyPass != other.proxyPass) return false; + return true; +} + + +bool Network::Server::operator!=(const Server &other) const +{ + return !(*this == other); +} + + +QDebug operator<<(QDebug dbg, const Network::Server &server) +{ + dbg.nospace() << "Server(host = " << server.host << ":" << server.port << ", useSsl = " << server.useSsl << ")"; + return dbg.space(); } diff --git a/src/common/network.h b/src/common/network.h index 6b126d83..548ba9e0 100644 --- a/src/common/network.h +++ b/src/common/network.h @@ -44,254 +44,255 @@ struct NetworkInfo; // TODO: ConnectionInfo to propagate and sync the current state of NetworkConnection, encodings etcpp -class Network : public SyncableObject { - SYNCABLE_OBJECT - Q_OBJECT - Q_ENUMS(ConnectionState) - - Q_PROPERTY(QString networkName READ networkName WRITE setNetworkName STORED false) - Q_PROPERTY(QString currentServer READ currentServer WRITE setCurrentServer STORED false) - Q_PROPERTY(QString myNick READ myNick WRITE setMyNick STORED false) - Q_PROPERTY(int latency READ latency WRITE setLatency STORED false) - Q_PROPERTY(QByteArray codecForServer READ codecForServer WRITE setCodecForServer STORED false) - Q_PROPERTY(QByteArray codecForEncoding READ codecForEncoding WRITE setCodecForEncoding STORED false) - Q_PROPERTY(QByteArray codecForDecoding READ codecForDecoding WRITE setCodecForDecoding STORED false) - Q_PROPERTY(IdentityId identityId READ identity WRITE setIdentity STORED false) - Q_PROPERTY(bool isConnected READ isConnected WRITE setConnected STORED false) - //Q_PROPERTY(Network::ConnectionState connectionState READ connectionState WRITE setConnectionState STORED false) - Q_PROPERTY(int connectionState READ connectionState WRITE setConnectionState STORED false) - Q_PROPERTY(bool useRandomServer READ useRandomServer WRITE setUseRandomServer STORED false) - Q_PROPERTY(QStringList perform READ perform WRITE setPerform STORED false) - Q_PROPERTY(bool useAutoIdentify READ useAutoIdentify WRITE setUseAutoIdentify STORED false) - Q_PROPERTY(QString autoIdentifyService READ autoIdentifyService WRITE setAutoIdentifyService STORED false) - Q_PROPERTY(QString autoIdentifyPassword READ autoIdentifyPassword WRITE setAutoIdentifyPassword STORED false) - Q_PROPERTY(bool useSasl READ useSasl WRITE setUseSasl STORED false) - Q_PROPERTY(QString saslAccount READ saslAccount WRITE setSaslAccount STORED false) - Q_PROPERTY(QString saslPassword READ saslPassword WRITE setSaslPassword STORED false) - Q_PROPERTY(bool useAutoReconnect READ useAutoReconnect WRITE setUseAutoReconnect STORED false) - Q_PROPERTY(quint32 autoReconnectInterval READ autoReconnectInterval WRITE setAutoReconnectInterval STORED false) - Q_PROPERTY(quint16 autoReconnectRetries READ autoReconnectRetries WRITE setAutoReconnectRetries STORED false) - Q_PROPERTY(bool unlimitedReconnectRetries READ unlimitedReconnectRetries WRITE setUnlimitedReconnectRetries STORED false) - Q_PROPERTY(bool rejoinChannels READ rejoinChannels WRITE setRejoinChannels STORED false) - -public: - enum ConnectionState { - Disconnected, - Connecting, - Initializing, - Initialized, - Reconnecting, - Disconnecting - }; - - // see: - // http://www.irc.org/tech_docs/005.html - // http://www.irc.org/tech_docs/draft-brocklesby-irc-isupport-03.txt - enum ChannelModeType { - NOT_A_CHANMODE = 0x00, - A_CHANMODE = 0x01, - B_CHANMODE = 0x02, - C_CHANMODE = 0x04, - D_CHANMODE = 0x08 - }; - - struct Server { - QString host; - uint port; - QString password; - bool useSsl; - int sslVersion; - - bool useProxy; - int proxyType; - QString proxyHost; - uint proxyPort; - QString proxyUser; - QString proxyPass; - - Server() : port(6667), useSsl(false), sslVersion(0), useProxy(false), proxyType(QNetworkProxy::Socks5Proxy), proxyHost("localhost"), proxyPort(8080) {} - Server(const QString &host, uint port, const QString &password, bool useSsl) - : host(host), port(port), password(password), useSsl(useSsl), sslVersion(0), - useProxy(false), proxyType(QNetworkProxy::Socks5Proxy), proxyHost("localhost"), proxyPort(8080) {} - bool operator==(const Server &other) const; - bool operator!=(const Server &other) const; - }; - typedef QList ServerList; - - Network(const NetworkId &networkid, QObject *parent = 0); - ~Network(); - - inline NetworkId networkId() const { return _networkId; } - - inline SignalProxy *proxy() const { return _proxy; } - inline void setProxy(SignalProxy *proxy) { _proxy = proxy; } - - inline bool isMyNick(const QString &nick) const { return (myNick().toLower() == nick.toLower()); } - inline bool isMe(IrcUser *ircuser) const { return (ircuser->nick().toLower() == myNick().toLower()); } - - bool isChannelName(const QString &channelname) const; - - inline bool isConnected() const { return _connected; } - //Network::ConnectionState connectionState() const; - inline int connectionState() const { return _connectionState; } - - QString prefixToMode(const QString &prefix) const; - inline QString prefixToMode(const QCharRef &prefix) const { return prefixToMode(QString(prefix)); } - QString modeToPrefix(const QString &mode) const; - inline QString modeToPrefix(const QCharRef &mode) const { return modeToPrefix(QString(mode)); } - - ChannelModeType channelModeType(const QString &mode); - inline ChannelModeType channelModeType(const QCharRef &mode) { return channelModeType(QString(mode)); } - - inline const QString &networkName() const { return _networkName; } - inline const QString ¤tServer() const { return _currentServer; } - inline const QString &myNick() const { return _myNick; } - inline int latency() const { return _latency; } - inline IrcUser *me() const { return ircUser(myNick()); } - inline IdentityId identity() const { return _identity; } - QStringList nicks() const; - inline QStringList channels() const { return _ircChannels.keys(); } - inline const ServerList &serverList() const { return _serverList; } - inline bool useRandomServer() const { return _useRandomServer; } - inline const QStringList &perform() const { return _perform; } - inline bool useAutoIdentify() const { return _useAutoIdentify; } - inline const QString &autoIdentifyService() const { return _autoIdentifyService; } - inline const QString &autoIdentifyPassword() const { return _autoIdentifyPassword; } - inline bool useSasl() const { return _useSasl; } - inline const QString &saslAccount() const { return _saslAccount; } - inline const QString &saslPassword() const { return _saslPassword; } - inline bool useAutoReconnect() const { return _useAutoReconnect; } - inline quint32 autoReconnectInterval() const { return _autoReconnectInterval; } - inline quint16 autoReconnectRetries() const { return _autoReconnectRetries; } - inline bool unlimitedReconnectRetries() const { return _unlimitedReconnectRetries; } - inline bool rejoinChannels() const { return _rejoinChannels; } - - NetworkInfo networkInfo() const; - void setNetworkInfo(const NetworkInfo &); - - QString prefixes() const; - QString prefixModes() const; - void determinePrefixes() const; - - bool supports(const QString ¶m) const { return _supports.contains(param); } - QString support(const QString ¶m) const; - - IrcUser *newIrcUser(const QString &hostmask, const QVariantMap &initData = QVariantMap()); - inline IrcUser *newIrcUser(const QByteArray &hostmask) { return newIrcUser(decodeServerString(hostmask)); } - IrcUser *ircUser(QString nickname) const; - inline IrcUser *ircUser(const QByteArray &nickname) const { return ircUser(decodeServerString(nickname)); } - inline QList ircUsers() const { return _ircUsers.values(); } - inline quint32 ircUserCount() const { return _ircUsers.count(); } - - IrcChannel *newIrcChannel(const QString &channelname, const QVariantMap &initData = QVariantMap()); - inline IrcChannel *newIrcChannel(const QByteArray &channelname) { return newIrcChannel(decodeServerString(channelname)); } - IrcChannel *ircChannel(QString channelname) const; - inline IrcChannel *ircChannel(const QByteArray &channelname) const { return ircChannel(decodeServerString(channelname)); } - inline QList ircChannels() const { return _ircChannels.values(); } - inline quint32 ircChannelCount() const { return _ircChannels.count(); } - - QByteArray codecForServer() const; - QByteArray codecForEncoding() const; - QByteArray codecForDecoding() const; - void setCodecForServer(QTextCodec *codec); - void setCodecForEncoding(QTextCodec *codec); - void setCodecForDecoding(QTextCodec *codec); - - QString decodeString(const QByteArray &text) const; - QByteArray encodeString(const QString &string) const; - QString decodeServerString(const QByteArray &text) const; - QByteArray encodeServerString(const QString &string) const; - - static QByteArray defaultCodecForServer(); - static QByteArray defaultCodecForEncoding(); - static QByteArray defaultCodecForDecoding(); - static void setDefaultCodecForServer(const QByteArray &name); - static void setDefaultCodecForEncoding(const QByteArray &name); - static void setDefaultCodecForDecoding(const QByteArray &name); - - inline bool autoAwayActive() const { return _autoAwayActive; } - inline void setAutoAwayActive(bool active) { _autoAwayActive = active; } - - static QStringList presetNetworks(bool onlyDefault = false); - static QStringList presetDefaultChannels(const QString &networkName); - static NetworkInfo networkInfoFromPreset(const QString &networkName); +class Network : public SyncableObject +{ + SYNCABLE_OBJECT + Q_OBJECT + Q_ENUMS(ConnectionState) + + Q_PROPERTY(QString networkName READ networkName WRITE setNetworkName STORED false) + Q_PROPERTY(QString currentServer READ currentServer WRITE setCurrentServer STORED false) + Q_PROPERTY(QString myNick READ myNick WRITE setMyNick STORED false) + Q_PROPERTY(int latency READ latency WRITE setLatency STORED false) + Q_PROPERTY(QByteArray codecForServer READ codecForServer WRITE setCodecForServer STORED false) + Q_PROPERTY(QByteArray codecForEncoding READ codecForEncoding WRITE setCodecForEncoding STORED false) + Q_PROPERTY(QByteArray codecForDecoding READ codecForDecoding WRITE setCodecForDecoding STORED false) + Q_PROPERTY(IdentityId identityId READ identity WRITE setIdentity STORED false) + Q_PROPERTY(bool isConnected READ isConnected WRITE setConnected STORED false) + //Q_PROPERTY(Network::ConnectionState connectionState READ connectionState WRITE setConnectionState STORED false) + Q_PROPERTY(int connectionState READ connectionState WRITE setConnectionState STORED false) + Q_PROPERTY(bool useRandomServer READ useRandomServer WRITE setUseRandomServer STORED false) + Q_PROPERTY(QStringList perform READ perform WRITE setPerform STORED false) + Q_PROPERTY(bool useAutoIdentify READ useAutoIdentify WRITE setUseAutoIdentify STORED false) + Q_PROPERTY(QString autoIdentifyService READ autoIdentifyService WRITE setAutoIdentifyService STORED false) + Q_PROPERTY(QString autoIdentifyPassword READ autoIdentifyPassword WRITE setAutoIdentifyPassword STORED false) + Q_PROPERTY(bool useSasl READ useSasl WRITE setUseSasl STORED false) + Q_PROPERTY(QString saslAccount READ saslAccount WRITE setSaslAccount STORED false) + Q_PROPERTY(QString saslPassword READ saslPassword WRITE setSaslPassword STORED false) + Q_PROPERTY(bool useAutoReconnect READ useAutoReconnect WRITE setUseAutoReconnect STORED false) + Q_PROPERTY(quint32 autoReconnectInterval READ autoReconnectInterval WRITE setAutoReconnectInterval STORED false) + Q_PROPERTY(quint16 autoReconnectRetries READ autoReconnectRetries WRITE setAutoReconnectRetries STORED false) + Q_PROPERTY(bool unlimitedReconnectRetries READ unlimitedReconnectRetries WRITE setUnlimitedReconnectRetries STORED false) + Q_PROPERTY(bool rejoinChannels READ rejoinChannels WRITE setRejoinChannels STORED false) + +public : + enum ConnectionState { + Disconnected, + Connecting, + Initializing, + Initialized, + Reconnecting, + Disconnecting + }; + + // see: + // http://www.irc.org/tech_docs/005.html + // http://www.irc.org/tech_docs/draft-brocklesby-irc-isupport-03.txt + enum ChannelModeType { + NOT_A_CHANMODE = 0x00, + A_CHANMODE = 0x01, + B_CHANMODE = 0x02, + C_CHANMODE = 0x04, + D_CHANMODE = 0x08 + }; + + struct Server { + QString host; + uint port; + QString password; + bool useSsl; + int sslVersion; + + bool useProxy; + int proxyType; + QString proxyHost; + uint proxyPort; + QString proxyUser; + QString proxyPass; + + Server() : port(6667), useSsl(false), sslVersion(0), useProxy(false), proxyType(QNetworkProxy::Socks5Proxy), proxyHost("localhost"), proxyPort(8080) {} + Server(const QString &host, uint port, const QString &password, bool useSsl) + : host(host), port(port), password(password), useSsl(useSsl), sslVersion(0), + useProxy(false), proxyType(QNetworkProxy::Socks5Proxy), proxyHost("localhost"), proxyPort(8080) {} + bool operator==(const Server &other) const; + bool operator!=(const Server &other) const; + }; + typedef QList ServerList; + + Network(const NetworkId &networkid, QObject *parent = 0); + ~Network(); + + inline NetworkId networkId() const { return _networkId; } + + inline SignalProxy *proxy() const { return _proxy; } + inline void setProxy(SignalProxy *proxy) { _proxy = proxy; } + + inline bool isMyNick(const QString &nick) const { return (myNick().toLower() == nick.toLower()); } + inline bool isMe(IrcUser *ircuser) const { return (ircuser->nick().toLower() == myNick().toLower()); } + + bool isChannelName(const QString &channelname) const; + + inline bool isConnected() const { return _connected; } + //Network::ConnectionState connectionState() const; + inline int connectionState() const { return _connectionState; } + + QString prefixToMode(const QString &prefix) const; + inline QString prefixToMode(const QCharRef &prefix) const { return prefixToMode(QString(prefix)); } + QString modeToPrefix(const QString &mode) const; + inline QString modeToPrefix(const QCharRef &mode) const { return modeToPrefix(QString(mode)); } + + ChannelModeType channelModeType(const QString &mode); + inline ChannelModeType channelModeType(const QCharRef &mode) { return channelModeType(QString(mode)); } + + inline const QString &networkName() const { return _networkName; } + inline const QString ¤tServer() const { return _currentServer; } + inline const QString &myNick() const { return _myNick; } + inline int latency() const { return _latency; } + inline IrcUser *me() const { return ircUser(myNick()); } + inline IdentityId identity() const { return _identity; } + QStringList nicks() const; + inline QStringList channels() const { return _ircChannels.keys(); } + inline const ServerList &serverList() const { return _serverList; } + inline bool useRandomServer() const { return _useRandomServer; } + inline const QStringList &perform() const { return _perform; } + inline bool useAutoIdentify() const { return _useAutoIdentify; } + inline const QString &autoIdentifyService() const { return _autoIdentifyService; } + inline const QString &autoIdentifyPassword() const { return _autoIdentifyPassword; } + inline bool useSasl() const { return _useSasl; } + inline const QString &saslAccount() const { return _saslAccount; } + inline const QString &saslPassword() const { return _saslPassword; } + inline bool useAutoReconnect() const { return _useAutoReconnect; } + inline quint32 autoReconnectInterval() const { return _autoReconnectInterval; } + inline quint16 autoReconnectRetries() const { return _autoReconnectRetries; } + inline bool unlimitedReconnectRetries() const { return _unlimitedReconnectRetries; } + inline bool rejoinChannels() const { return _rejoinChannels; } + + NetworkInfo networkInfo() const; + void setNetworkInfo(const NetworkInfo &); + + QString prefixes() const; + QString prefixModes() const; + void determinePrefixes() const; + + bool supports(const QString ¶m) const { return _supports.contains(param); } + QString support(const QString ¶m) const; + + IrcUser *newIrcUser(const QString &hostmask, const QVariantMap &initData = QVariantMap()); + inline IrcUser *newIrcUser(const QByteArray &hostmask) { return newIrcUser(decodeServerString(hostmask)); } + IrcUser *ircUser(QString nickname) const; + inline IrcUser *ircUser(const QByteArray &nickname) const { return ircUser(decodeServerString(nickname)); } + inline QList ircUsers() const { return _ircUsers.values(); } + inline quint32 ircUserCount() const { return _ircUsers.count(); } + + IrcChannel *newIrcChannel(const QString &channelname, const QVariantMap &initData = QVariantMap()); + inline IrcChannel *newIrcChannel(const QByteArray &channelname) { return newIrcChannel(decodeServerString(channelname)); } + IrcChannel *ircChannel(QString channelname) const; + inline IrcChannel *ircChannel(const QByteArray &channelname) const { return ircChannel(decodeServerString(channelname)); } + inline QList ircChannels() const { return _ircChannels.values(); } + inline quint32 ircChannelCount() const { return _ircChannels.count(); } + + QByteArray codecForServer() const; + QByteArray codecForEncoding() const; + QByteArray codecForDecoding() const; + void setCodecForServer(QTextCodec *codec); + void setCodecForEncoding(QTextCodec *codec); + void setCodecForDecoding(QTextCodec *codec); + + QString decodeString(const QByteArray &text) const; + QByteArray encodeString(const QString &string) const; + QString decodeServerString(const QByteArray &text) const; + QByteArray encodeServerString(const QString &string) const; + + static QByteArray defaultCodecForServer(); + static QByteArray defaultCodecForEncoding(); + static QByteArray defaultCodecForDecoding(); + static void setDefaultCodecForServer(const QByteArray &name); + static void setDefaultCodecForEncoding(const QByteArray &name); + static void setDefaultCodecForDecoding(const QByteArray &name); + + inline bool autoAwayActive() const { return _autoAwayActive; } + inline void setAutoAwayActive(bool active) { _autoAwayActive = active; } + + static QStringList presetNetworks(bool onlyDefault = false); + static QStringList presetDefaultChannels(const QString &networkName); + static NetworkInfo networkInfoFromPreset(const QString &networkName); public slots: - void setNetworkName(const QString &networkName); - void setCurrentServer(const QString ¤tServer); - void setConnected(bool isConnected); - void setConnectionState(int state); - virtual void setMyNick(const QString &mynick); - void setLatency(int latency); - void setIdentity(IdentityId); - - void setServerList(const QVariantList &serverList); - void setUseRandomServer(bool); - void setPerform(const QStringList &); - void setUseAutoIdentify(bool); - void setAutoIdentifyService(const QString &); - void setAutoIdentifyPassword(const QString &); - void setUseSasl(bool); - void setSaslAccount(const QString &); - void setSaslPassword(const QString &); - virtual void setUseAutoReconnect(bool); - virtual void setAutoReconnectInterval(quint32); - virtual void setAutoReconnectRetries(quint16); - void setUnlimitedReconnectRetries(bool); - void setRejoinChannels(bool); - - void setCodecForServer(const QByteArray &codecName); - void setCodecForEncoding(const QByteArray &codecName); - void setCodecForDecoding(const QByteArray &codecName); - - void addSupport(const QString ¶m, const QString &value = QString()); - void removeSupport(const QString ¶m); - - inline void addIrcUser(const QString &hostmask) { newIrcUser(hostmask); } - inline void addIrcChannel(const QString &channel) { newIrcChannel(channel); } - - //init geters - QVariantMap initSupports() const; - inline QVariantList initServerList() const { return toVariantList(serverList()); } - virtual QVariantMap initIrcUsersAndChannels() const; - - //init seters - void initSetSupports(const QVariantMap &supports); - inline void initSetServerList(const QVariantList &serverList) { _serverList = fromVariantList(serverList); } - virtual void initSetIrcUsersAndChannels(const QVariantMap &usersAndChannels); - - IrcUser *updateNickFromMask(const QString &mask); - - // these slots are to keep the hashlists of all users and the - // channel lists up to date - void ircUserNickChanged(QString newnick); - - virtual inline void requestConnect() const { REQUEST(NO_ARG) } - virtual inline void requestDisconnect() const { REQUEST(NO_ARG) } - virtual inline void requestSetNetworkInfo(const NetworkInfo &info) { REQUEST(ARG(info)) } - - void emitConnectionError(const QString &); + void setNetworkName(const QString &networkName); + void setCurrentServer(const QString ¤tServer); + void setConnected(bool isConnected); + void setConnectionState(int state); + virtual void setMyNick(const QString &mynick); + void setLatency(int latency); + void setIdentity(IdentityId); + + void setServerList(const QVariantList &serverList); + void setUseRandomServer(bool); + void setPerform(const QStringList &); + void setUseAutoIdentify(bool); + void setAutoIdentifyService(const QString &); + void setAutoIdentifyPassword(const QString &); + void setUseSasl(bool); + void setSaslAccount(const QString &); + void setSaslPassword(const QString &); + virtual void setUseAutoReconnect(bool); + virtual void setAutoReconnectInterval(quint32); + virtual void setAutoReconnectRetries(quint16); + void setUnlimitedReconnectRetries(bool); + void setRejoinChannels(bool); + + void setCodecForServer(const QByteArray &codecName); + void setCodecForEncoding(const QByteArray &codecName); + void setCodecForDecoding(const QByteArray &codecName); + + void addSupport(const QString ¶m, const QString &value = QString()); + void removeSupport(const QString ¶m); + + inline void addIrcUser(const QString &hostmask) { newIrcUser(hostmask); } + inline void addIrcChannel(const QString &channel) { newIrcChannel(channel); } + + //init geters + QVariantMap initSupports() const; + inline QVariantList initServerList() const { return toVariantList(serverList()); } + virtual QVariantMap initIrcUsersAndChannels() const; + + //init seters + void initSetSupports(const QVariantMap &supports); + inline void initSetServerList(const QVariantList &serverList) { _serverList = fromVariantList(serverList); } + virtual void initSetIrcUsersAndChannels(const QVariantMap &usersAndChannels); + + IrcUser *updateNickFromMask(const QString &mask); + + // these slots are to keep the hashlists of all users and the + // channel lists up to date + void ircUserNickChanged(QString newnick); + + virtual inline void requestConnect() const { REQUEST(NO_ARG) } + virtual inline void requestDisconnect() const { REQUEST(NO_ARG) } + virtual inline void requestSetNetworkInfo(const NetworkInfo &info) { REQUEST(ARG(info)) } + + void emitConnectionError(const QString &); protected slots: - virtual void removeIrcUser(IrcUser *ircuser); - virtual void removeIrcChannel(IrcChannel *ircChannel); - virtual void removeChansAndUsers(); + virtual void removeIrcUser(IrcUser *ircuser); + virtual void removeIrcChannel(IrcChannel *ircChannel); + virtual void removeChansAndUsers(); signals: - void aboutToBeDestroyed(); - void networkNameSet(const QString &networkName); - void currentServerSet(const QString ¤tServer); - void connectedSet(bool isConnected); - void connectionStateSet(Network::ConnectionState); + void aboutToBeDestroyed(); + void networkNameSet(const QString &networkName); + void currentServerSet(const QString ¤tServer); + void connectedSet(bool isConnected); + void connectionStateSet(Network::ConnectionState); // void connectionStateSet(int); - void connectionError(const QString &errorMsg); - void myNickSet(const QString &mynick); + void connectionError(const QString &errorMsg); + void myNickSet(const QString &mynick); // void latencySet(int latency); - void identitySet(IdentityId); + void identitySet(IdentityId); - void configChanged(); + void configChanged(); - // void serverListSet(QVariantList serverList); + // void serverListSet(QVariantList serverList); // void useRandomServerSet(bool); // void performSet(const QStringList &); // void useAutoIdentifySet(bool); @@ -311,107 +312,108 @@ signals: // void supportRemoved(const QString ¶m); // void ircUserAdded(const QString &hostmask); - void ircUserAdded(IrcUser *); + void ircUserAdded(IrcUser *); // void ircChannelAdded(const QString &channelname); - void ircChannelAdded(IrcChannel *); + void ircChannelAdded(IrcChannel *); // void connectRequested() const; // void disconnectRequested() const; // void setNetworkInfoRequested(const NetworkInfo &) const; protected: - inline virtual IrcChannel *ircChannelFactory(const QString &channelname) { return new IrcChannel(channelname, this); } - inline virtual IrcUser *ircUserFactory(const QString &hostmask) { return new IrcUser(hostmask, this); } + inline virtual IrcChannel *ircChannelFactory(const QString &channelname) { return new IrcChannel(channelname, this); } + inline virtual IrcUser *ircUserFactory(const QString &hostmask) { return new IrcUser(hostmask, this); } private: - QPointer _proxy; + QPointer _proxy; - NetworkId _networkId; - IdentityId _identity; + NetworkId _networkId; + IdentityId _identity; - QString _myNick; - int _latency; - QString _networkName; - QString _currentServer; - bool _connected; - ConnectionState _connectionState; + QString _myNick; + int _latency; + QString _networkName; + QString _currentServer; + bool _connected; + ConnectionState _connectionState; - mutable QString _prefixes; - mutable QString _prefixModes; + mutable QString _prefixes; + mutable QString _prefixModes; - QHash _ircUsers; // stores all known nicks for the server - QHash _ircChannels; // stores all known channels - QHash _supports; // stores results from RPL_ISUPPORT + QHash _ircUsers; // stores all known nicks for the server + QHash _ircChannels; // stores all known channels + QHash _supports; // stores results from RPL_ISUPPORT - ServerList _serverList; - bool _useRandomServer; - QStringList _perform; + ServerList _serverList; + bool _useRandomServer; + QStringList _perform; - bool _useAutoIdentify; - QString _autoIdentifyService; - QString _autoIdentifyPassword; + bool _useAutoIdentify; + QString _autoIdentifyService; + QString _autoIdentifyPassword; - bool _useSasl; - QString _saslAccount; - QString _saslPassword; + bool _useSasl; + QString _saslAccount; + QString _saslPassword; - bool _useAutoReconnect; - quint32 _autoReconnectInterval; - quint16 _autoReconnectRetries; - bool _unlimitedReconnectRetries; - bool _rejoinChannels; + bool _useAutoReconnect; + quint32 _autoReconnectInterval; + quint16 _autoReconnectRetries; + bool _unlimitedReconnectRetries; + bool _rejoinChannels; - QTextCodec *_codecForServer; - QTextCodec *_codecForEncoding; - QTextCodec *_codecForDecoding; + QTextCodec *_codecForServer; + QTextCodec *_codecForEncoding; + QTextCodec *_codecForDecoding; - static QTextCodec *_defaultCodecForServer; - static QTextCodec *_defaultCodecForEncoding; - static QTextCodec *_defaultCodecForDecoding; + static QTextCodec *_defaultCodecForServer; + static QTextCodec *_defaultCodecForEncoding; + static QTextCodec *_defaultCodecForDecoding; - bool _autoAwayActive; // when this is active handle305 and handle306 don't trigger any output + bool _autoAwayActive; // when this is active handle305 and handle306 don't trigger any output - static QString _networksIniPath; + static QString _networksIniPath; - friend class IrcUser; - friend class IrcChannel; + friend class IrcUser; + friend class IrcChannel; }; + //! Stores all editable information about a network (as opposed to runtime state). struct NetworkInfo { - // set some default values, note that this does not initialize e.g. name and id - NetworkInfo(); + // set some default values, note that this does not initialize e.g. name and id + NetworkInfo(); - NetworkId networkId; - QString networkName; - IdentityId identity; + NetworkId networkId; + QString networkName; + IdentityId identity; - bool useCustomEncodings; // not used! - QByteArray codecForServer; - QByteArray codecForEncoding; - QByteArray codecForDecoding; + bool useCustomEncodings; // not used! + QByteArray codecForServer; + QByteArray codecForEncoding; + QByteArray codecForDecoding; - Network::ServerList serverList; - bool useRandomServer; + Network::ServerList serverList; + bool useRandomServer; - QStringList perform; + QStringList perform; - bool useAutoIdentify; - QString autoIdentifyService; - QString autoIdentifyPassword; + bool useAutoIdentify; + QString autoIdentifyService; + QString autoIdentifyPassword; - bool useSasl; - QString saslAccount; - QString saslPassword; + bool useSasl; + QString saslAccount; + QString saslPassword; - bool useAutoReconnect; - quint32 autoReconnectInterval; - quint16 autoReconnectRetries; - bool unlimitedReconnectRetries; - bool rejoinChannels; + bool useAutoReconnect; + quint32 autoReconnectInterval; + quint16 autoReconnectRetries; + bool unlimitedReconnectRetries; + bool rejoinChannels; - bool operator==(const NetworkInfo &other) const; - bool operator!=(const NetworkInfo &other) const; + bool operator==(const NetworkInfo &other) const; + bool operator!=(const NetworkInfo &other) const; }; QDataStream &operator<<(QDataStream &out, const NetworkInfo &info); diff --git a/src/common/networkconfig.cpp b/src/common/networkconfig.cpp index 8a0af10f..92176e2e 100644 --- a/src/common/networkconfig.cpp +++ b/src/common/networkconfig.cpp @@ -22,75 +22,88 @@ INIT_SYNCABLE_OBJECT(NetworkConfig) NetworkConfig::NetworkConfig(const QString &objectName, QObject *parent) -: SyncableObject(objectName, parent), - _pingTimeoutEnabled(true), - _pingInterval(30), - _maxPingCount(6), - _autoWhoEnabled(true), - _autoWhoInterval(90), - _autoWhoNickLimit(200), - _autoWhoDelay(5) + : SyncableObject(objectName, parent), + _pingTimeoutEnabled(true), + _pingInterval(30), + _maxPingCount(6), + _autoWhoEnabled(true), + _autoWhoInterval(90), + _autoWhoNickLimit(200), + _autoWhoDelay(5) { - } -void NetworkConfig::setPingTimeoutEnabled(bool enabled) { - if(_pingTimeoutEnabled == enabled) - return; - _pingTimeoutEnabled = enabled; - SYNC(ARG(enabled)) - emit pingTimeoutEnabledSet(enabled); +void NetworkConfig::setPingTimeoutEnabled(bool enabled) +{ + if (_pingTimeoutEnabled == enabled) + return; + + _pingTimeoutEnabled = enabled; + SYNC(ARG(enabled)) + emit pingTimeoutEnabledSet(enabled); } -void NetworkConfig::setPingInterval(int interval) { - if(_pingInterval == interval) - return; - _pingInterval = interval; - SYNC(ARG(interval)) - emit pingIntervalSet(interval); +void NetworkConfig::setPingInterval(int interval) +{ + if (_pingInterval == interval) + return; + + _pingInterval = interval; + SYNC(ARG(interval)) + emit pingIntervalSet(interval); } -void NetworkConfig::setMaxPingCount(int count) { - if(_maxPingCount == count) - return; - _maxPingCount = count; - SYNC(ARG(count)) +void NetworkConfig::setMaxPingCount(int count) +{ + if (_maxPingCount == count) + return; + + _maxPingCount = count; + SYNC(ARG(count)) } -void NetworkConfig::setAutoWhoEnabled(bool enabled) { - if(_autoWhoEnabled == enabled) - return; - _autoWhoEnabled = enabled; - SYNC(ARG(enabled)) - emit autoWhoEnabledSet(enabled); +void NetworkConfig::setAutoWhoEnabled(bool enabled) +{ + if (_autoWhoEnabled == enabled) + return; + + _autoWhoEnabled = enabled; + SYNC(ARG(enabled)) + emit autoWhoEnabledSet(enabled); } -void NetworkConfig::setAutoWhoInterval(int interval) { - if(_autoWhoInterval == interval) - return; - _autoWhoInterval = interval; - SYNC(ARG(interval)) - emit autoWhoIntervalSet(interval); +void NetworkConfig::setAutoWhoInterval(int interval) +{ + if (_autoWhoInterval == interval) + return; + + _autoWhoInterval = interval; + SYNC(ARG(interval)) + emit autoWhoIntervalSet(interval); } -void NetworkConfig::setAutoWhoNickLimit(int nickLimit) { - if(_autoWhoNickLimit == nickLimit) - return; - _autoWhoNickLimit = nickLimit; - SYNC(ARG(nickLimit)) +void NetworkConfig::setAutoWhoNickLimit(int nickLimit) +{ + if (_autoWhoNickLimit == nickLimit) + return; + + _autoWhoNickLimit = nickLimit; + SYNC(ARG(nickLimit)) } -void NetworkConfig::setAutoWhoDelay(int delay) { - if(_autoWhoDelay == delay) - return; - _autoWhoDelay = delay; - SYNC(ARG(delay)) - emit autoWhoDelaySet(delay); +void NetworkConfig::setAutoWhoDelay(int delay) +{ + if (_autoWhoDelay == delay) + return; + + _autoWhoDelay = delay; + SYNC(ARG(delay)) + emit autoWhoDelaySet(delay); } diff --git a/src/common/networkconfig.h b/src/common/networkconfig.h index d9063180..63dc669b 100644 --- a/src/common/networkconfig.h +++ b/src/common/networkconfig.h @@ -23,60 +23,61 @@ #include "syncableobject.h" -class NetworkConfig : public SyncableObject { - SYNCABLE_OBJECT - Q_OBJECT +class NetworkConfig : public SyncableObject +{ + SYNCABLE_OBJECT + Q_OBJECT - Q_PROPERTY(bool pingTimeoutEnabled READ pingTimeoutEnabled WRITE setPingTimeoutEnabled) - Q_PROPERTY(int pingInterval READ pingInterval WRITE setPingInterval) - Q_PROPERTY(int maxPingCount READ maxPingCount WRITE setMaxPingCount) - Q_PROPERTY(bool autoWhoEnabled READ autoWhoEnabled WRITE setAutoWhoEnabled) - Q_PROPERTY(int autoWhoInterval READ autoWhoInterval WRITE setAutoWhoInterval) - Q_PROPERTY(int autoWhoNickLimit READ autoWhoNickLimit WRITE setAutoWhoNickLimit) - Q_PROPERTY(int autoWhoDelay READ autoWhoDelay WRITE setAutoWhoDelay) + Q_PROPERTY(bool pingTimeoutEnabled READ pingTimeoutEnabled WRITE setPingTimeoutEnabled) + Q_PROPERTY(int pingInterval READ pingInterval WRITE setPingInterval) + Q_PROPERTY(int maxPingCount READ maxPingCount WRITE setMaxPingCount) + Q_PROPERTY(bool autoWhoEnabled READ autoWhoEnabled WRITE setAutoWhoEnabled) + Q_PROPERTY(int autoWhoInterval READ autoWhoInterval WRITE setAutoWhoInterval) + Q_PROPERTY(int autoWhoNickLimit READ autoWhoNickLimit WRITE setAutoWhoNickLimit) + Q_PROPERTY(int autoWhoDelay READ autoWhoDelay WRITE setAutoWhoDelay) -public: - NetworkConfig(const QString &objectName = "GlobalNetworkConfig", QObject *parent = 0); +public : + NetworkConfig(const QString &objectName = "GlobalNetworkConfig", QObject *parent = 0); - inline virtual const QMetaObject *syncMetaObject() const { return &staticMetaObject; } + inline virtual const QMetaObject *syncMetaObject() const { return &staticMetaObject; } public slots: - inline bool pingTimeoutEnabled() const { return _pingTimeoutEnabled; } - void setPingTimeoutEnabled(bool); - virtual inline void requestSetPingTimeoutEnabled(bool b) { REQUEST(ARG(b)) } + inline bool pingTimeoutEnabled() const { return _pingTimeoutEnabled; } + void setPingTimeoutEnabled(bool); + virtual inline void requestSetPingTimeoutEnabled(bool b) { REQUEST(ARG(b)) } - inline int pingInterval() const { return _pingInterval; } - void setPingInterval(int); - virtual inline void requestSetPingInterval(int i) { REQUEST(ARG(i)) } + inline int pingInterval() const { return _pingInterval; } + void setPingInterval(int); + virtual inline void requestSetPingInterval(int i) { REQUEST(ARG(i)) } - inline int maxPingCount() const { return _maxPingCount; } - void setMaxPingCount(int); - virtual inline void requestSetMaxPingCount(int i) { REQUEST(ARG(i)) } + inline int maxPingCount() const { return _maxPingCount; } + void setMaxPingCount(int); + virtual inline void requestSetMaxPingCount(int i) { REQUEST(ARG(i)) } - inline bool autoWhoEnabled() const { return _autoWhoEnabled; } - void setAutoWhoEnabled(bool); - virtual inline void requestSetAutoWhoEnabled(bool b) { REQUEST(ARG(b)) } + inline bool autoWhoEnabled() const { return _autoWhoEnabled; } + void setAutoWhoEnabled(bool); + virtual inline void requestSetAutoWhoEnabled(bool b) { REQUEST(ARG(b)) } - inline int autoWhoInterval() const { return _autoWhoInterval; } - void setAutoWhoInterval(int); - virtual inline void requestSetAutoWhoInterval(int i) { REQUEST(ARG(i)) } + inline int autoWhoInterval() const { return _autoWhoInterval; } + void setAutoWhoInterval(int); + virtual inline void requestSetAutoWhoInterval(int i) { REQUEST(ARG(i)) } - inline int autoWhoNickLimit() const { return _autoWhoNickLimit; } - void setAutoWhoNickLimit(int); - virtual inline void requestSetAutoWhoNickLimit(int i) { REQUEST(ARG(i)) } + inline int autoWhoNickLimit() const { return _autoWhoNickLimit; } + void setAutoWhoNickLimit(int); + virtual inline void requestSetAutoWhoNickLimit(int i) { REQUEST(ARG(i)) } - inline int autoWhoDelay() const { return _autoWhoDelay; } - void setAutoWhoDelay(int); - virtual inline void requestSetAutoWhoDelay(int i) { REQUEST(ARG(i)) } + inline int autoWhoDelay() const { return _autoWhoDelay; } + void setAutoWhoDelay(int); + virtual inline void requestSetAutoWhoDelay(int i) { REQUEST(ARG(i)) } signals: - void pingTimeoutEnabledSet(bool); - void pingIntervalSet(int); + void pingTimeoutEnabledSet(bool); + void pingIntervalSet(int); // void maxPingCountSet(int); - void autoWhoEnabledSet(bool); - void autoWhoIntervalSet(int); + void autoWhoEnabledSet(bool); + void autoWhoIntervalSet(int); // void autoWhoNickLimitSet(int); - void autoWhoDelaySet(int); + void autoWhoDelaySet(int); // void setPingTimeoutEnabledRequested(bool); // void setPingIntervalRequested(int); @@ -87,14 +88,15 @@ signals: // void setAutoWhoDelayRequested(int); private: - bool _pingTimeoutEnabled; - int _pingInterval; - int _maxPingCount; - - bool _autoWhoEnabled; - int _autoWhoInterval; - int _autoWhoNickLimit; - int _autoWhoDelay; + bool _pingTimeoutEnabled; + int _pingInterval; + int _maxPingCount; + + bool _autoWhoEnabled; + int _autoWhoInterval; + int _autoWhoNickLimit; + int _autoWhoDelay; }; + #endif diff --git a/src/common/networkevent.cpp b/src/common/networkevent.cpp index 1752b586..89cfa772 100644 --- a/src/common/networkevent.cpp +++ b/src/common/networkevent.cpp @@ -20,82 +20,85 @@ #include "networkevent.h" -Event *NetworkEvent::create(EventManager::EventType type, QVariantMap &map, Network *network) { - switch(type) { - case EventManager::NetworkIncoming: - return new NetworkDataEvent(type, map, network); - - case EventManager::NetworkConnecting: - case EventManager::NetworkInitializing: - case EventManager::NetworkInitialized: - case EventManager::NetworkReconnecting: - case EventManager::NetworkDisconnecting: - case EventManager::NetworkDisconnected: - return new NetworkConnectionEvent(type, map, network); - - case EventManager::NetworkSplitJoin: - case EventManager::NetworkSplitQuit: - return new NetworkSplitEvent(type, map, network); - - default: - return 0; - } +Event *NetworkEvent::create(EventManager::EventType type, QVariantMap &map, Network *network) +{ + switch (type) { + case EventManager::NetworkIncoming: + return new NetworkDataEvent(type, map, network); + + case EventManager::NetworkConnecting: + case EventManager::NetworkInitializing: + case EventManager::NetworkInitialized: + case EventManager::NetworkReconnecting: + case EventManager::NetworkDisconnecting: + case EventManager::NetworkDisconnected: + return new NetworkConnectionEvent(type, map, network); + + case EventManager::NetworkSplitJoin: + case EventManager::NetworkSplitQuit: + return new NetworkSplitEvent(type, map, network); + + default: + return 0; + } } NetworkEvent::NetworkEvent(EventManager::EventType type, QVariantMap &map, Network *network) - : Event(type, map) - , _network(network) + : Event(type, map) + , _network(network) { - } -void NetworkEvent::toVariantMap(QVariantMap &map) const { - Event::toVariantMap(map); - map["network"] = networkId().toInt(); +void NetworkEvent::toVariantMap(QVariantMap &map) const +{ + Event::toVariantMap(map); + map["network"] = networkId().toInt(); } NetworkDataEvent::NetworkDataEvent(EventManager::EventType type, QVariantMap &map, Network *network) - : NetworkEvent(type, map, network) + : NetworkEvent(type, map, network) { - _data = map.take("data").toByteArray(); + _data = map.take("data").toByteArray(); } -void NetworkDataEvent::toVariantMap(QVariantMap &map) const { - NetworkEvent::toVariantMap(map); - map["data"] = data(); +void NetworkDataEvent::toVariantMap(QVariantMap &map) const +{ + NetworkEvent::toVariantMap(map); + map["data"] = data(); } NetworkConnectionEvent::NetworkConnectionEvent(EventManager::EventType type, QVariantMap &map, Network *network) - : NetworkEvent(type, map, network) + : NetworkEvent(type, map, network) { - _state = static_cast(map.take("state").toInt()); // FIXME: check enum plausibility + _state = static_cast(map.take("state").toInt()); // FIXME: check enum plausibility } -void NetworkConnectionEvent::toVariantMap(QVariantMap &map) const { - NetworkEvent::toVariantMap(map); - map["state"] = connectionState(); +void NetworkConnectionEvent::toVariantMap(QVariantMap &map) const +{ + NetworkEvent::toVariantMap(map); + map["state"] = connectionState(); } NetworkSplitEvent::NetworkSplitEvent(EventManager::EventType type, QVariantMap &map, Network *network) - : NetworkEvent(type, map, network) + : NetworkEvent(type, map, network) { - _channel = map.take("channel").toString(); - _users = map.take("users").toStringList(); - _quitMsg = map.take("quitMessage").toString(); + _channel = map.take("channel").toString(); + _users = map.take("users").toStringList(); + _quitMsg = map.take("quitMessage").toString(); } void NetworkSplitEvent::toVariantMap(QVariantMap &map) const { - NetworkEvent::toVariantMap(map); - map["channel"] = channel(); - map["users"] = users(); - map["quitMessage"] = quitMessage(); + NetworkEvent::toVariantMap(map); + map["channel"] = channel(); + map["users"] = users(); + map["quitMessage"] = quitMessage(); } diff --git a/src/common/networkevent.h b/src/common/networkevent.h index 7e46984a..9479da3b 100644 --- a/src/common/networkevent.h +++ b/src/common/networkevent.h @@ -27,122 +27,131 @@ #include "event.h" #include "network.h" -class NetworkEvent : public Event { - +class NetworkEvent : public Event +{ public: - explicit NetworkEvent(EventManager::EventType type, Network *network) - : Event(type), - _network(network) - {} + explicit NetworkEvent(EventManager::EventType type, Network *network) + : Event(type), + _network(network) + {} - inline NetworkId networkId() const { return network()? network()->networkId() : NetworkId(); } - inline Network *network() const { return _network; } + inline NetworkId networkId() const { return network() ? network()->networkId() : NetworkId(); } + inline Network *network() const { return _network; } - static Event *create(EventManager::EventType type, QVariantMap &map, Network *network); + static Event *create(EventManager::EventType type, QVariantMap &map, Network *network); protected: - explicit NetworkEvent(EventManager::EventType type, QVariantMap &map, Network *network); - void toVariantMap(QVariantMap &map) const; + explicit NetworkEvent(EventManager::EventType type, QVariantMap &map, Network *network); + void toVariantMap(QVariantMap &map) const; - virtual inline QString className() const { return "NetworkEvent"; } - virtual inline void debugInfo(QDebug &dbg) const { dbg.nospace() << ", net = " << qPrintable(_network->networkName()); } + virtual inline QString className() const { return "NetworkEvent"; } + virtual inline void debugInfo(QDebug &dbg) const { dbg.nospace() << ", net = " << qPrintable(_network->networkName()); } private: - Network *_network; + Network *_network; }; -/*****************************************************************************/ -class NetworkConnectionEvent : public NetworkEvent { +/*****************************************************************************/ +class NetworkConnectionEvent : public NetworkEvent +{ public: - explicit NetworkConnectionEvent(EventManager::EventType type, Network *network, Network::ConnectionState state) - : NetworkEvent(type, network), - _state(state) - {} + explicit NetworkConnectionEvent(EventManager::EventType type, Network *network, Network::ConnectionState state) + : NetworkEvent(type, network), + _state(state) + {} - inline Network::ConnectionState connectionState() const { return _state; } - inline void setConnectionState(Network::ConnectionState state) { _state = state; } + inline Network::ConnectionState connectionState() const { return _state; } + inline void setConnectionState(Network::ConnectionState state) { _state = state; } protected: - explicit NetworkConnectionEvent(EventManager::EventType type, QVariantMap &map, Network *network); - void toVariantMap(QVariantMap &map) const; + explicit NetworkConnectionEvent(EventManager::EventType type, QVariantMap &map, Network *network); + void toVariantMap(QVariantMap &map) const; + + virtual inline QString className() const { return "NetworkConnectionEvent"; } + virtual inline void debugInfo(QDebug &dbg) const + { + NetworkEvent::debugInfo(dbg); + dbg.nospace() << ", state = " << qPrintable(QString::number(_state)); + } - virtual inline QString className() const { return "NetworkConnectionEvent"; } - virtual inline void debugInfo(QDebug &dbg) const { - NetworkEvent::debugInfo(dbg); - dbg.nospace() << ", state = " << qPrintable(QString::number(_state)); - } private: - Network::ConnectionState _state; + Network::ConnectionState _state; - friend class NetworkEvent; + friend class NetworkEvent; }; -class NetworkDataEvent : public NetworkEvent { +class NetworkDataEvent : public NetworkEvent +{ public: - explicit NetworkDataEvent(EventManager::EventType type, Network *network, const QByteArray &data) - : NetworkEvent(type, network), - _data(data) - {} + explicit NetworkDataEvent(EventManager::EventType type, Network *network, const QByteArray &data) + : NetworkEvent(type, network), + _data(data) + {} - inline QByteArray data() const { return _data; } - inline void setData(const QByteArray &data) { _data = data; } + inline QByteArray data() const { return _data; } + inline void setData(const QByteArray &data) { _data = data; } protected: - explicit NetworkDataEvent(EventManager::EventType type, QVariantMap &map, Network *network); - void toVariantMap(QVariantMap &map) const; + explicit NetworkDataEvent(EventManager::EventType type, QVariantMap &map, Network *network); + void toVariantMap(QVariantMap &map) const; + + virtual inline QString className() const { return "NetworkDataEvent"; } + virtual inline void debugInfo(QDebug &dbg) const + { + NetworkEvent::debugInfo(dbg); + dbg.nospace() << ", data = " << data(); + } - virtual inline QString className() const { return "NetworkDataEvent"; } - virtual inline void debugInfo(QDebug &dbg) const { - NetworkEvent::debugInfo(dbg); - dbg.nospace() << ", data = " << data(); - } private: - QByteArray _data; + QByteArray _data; - friend class NetworkEvent; + friend class NetworkEvent; }; -class NetworkSplitEvent : public NetworkEvent { +class NetworkSplitEvent : public NetworkEvent +{ public: - explicit NetworkSplitEvent(EventManager::EventType type, - Network *network, - const QString &channel, - const QStringList &users, - const QString &quitMsg) - : NetworkEvent(type, network), - _channel(channel), - _users(users), - _quitMsg(quitMsg) - {} - - inline QString channel() const { return _channel; } - inline QStringList users() const { return _users; } - inline QString quitMessage() const { return _quitMsg; } + explicit NetworkSplitEvent(EventManager::EventType type, + Network *network, + const QString &channel, + const QStringList &users, + const QString &quitMsg) + : NetworkEvent(type, network), + _channel(channel), + _users(users), + _quitMsg(quitMsg) + {} + + inline QString channel() const { return _channel; } + inline QStringList users() const { return _users; } + inline QString quitMessage() const { return _quitMsg; } protected: - explicit NetworkSplitEvent(EventManager::EventType type, QVariantMap &map, Network *network); - void toVariantMap(QVariantMap &map) const; + explicit NetworkSplitEvent(EventManager::EventType type, QVariantMap &map, Network *network); + void toVariantMap(QVariantMap &map) const; + + virtual inline QString className() const { return "NetworkSplitEvent"; } + virtual inline void debugInfo(QDebug &dbg) const + { + NetworkEvent::debugInfo(dbg); + dbg.nospace() << ", channel = " << qPrintable(channel()) + << ", users = " << users() + << ", quitmsg = " << quitMessage(); + } - virtual inline QString className() const { return "NetworkSplitEvent"; } - virtual inline void debugInfo(QDebug &dbg) const { - NetworkEvent::debugInfo(dbg); - dbg.nospace() << ", channel = " << qPrintable(channel()) - << ", users = " << users() - << ", quitmsg = " << quitMessage(); - } private: - QString _channel; - QStringList _users; - QString _quitMsg; + QString _channel; + QStringList _users; + QString _quitMsg; - friend class NetworkEvent; + friend class NetworkEvent; }; diff --git a/src/common/quassel.cpp b/src/common/quassel.cpp index eb854b30..171bdc00 100644 --- a/src/common/quassel.cpp +++ b/src/common/quassel.cpp @@ -56,410 +56,448 @@ Quassel::LogLevel Quassel::_logLevel = InfoLevel; QFile *Quassel::_logFile = 0; bool Quassel::_logToSyslog = false; -Quassel::Quassel() { - Q_ASSERT(!_instance); - _instance = this; - - // We catch SIGTERM and SIGINT (caused by Ctrl+C) to graceful shutdown Quassel. - signal(SIGTERM, handleSignal); - signal(SIGINT, handleSignal); +Quassel::Quassel() +{ + Q_ASSERT(!_instance); + _instance = this; + + // We catch SIGTERM and SIGINT (caused by Ctrl+C) to graceful shutdown Quassel. + signal(SIGTERM, handleSignal); + signal(SIGINT, handleSignal); } -Quassel::~Quassel() { - if(logFile()) { - logFile()->close(); - logFile()->deleteLater(); - } - delete _cliParser; + +Quassel::~Quassel() +{ + if (logFile()) { + logFile()->close(); + logFile()->deleteLater(); + } + delete _cliParser; } -bool Quassel::init() { - if(_initialized) - return true; // allow multiple invocations because of MonolithicApplication - if (_handleCrashes) { - // we have crashhandler for win32 and unix (based on execinfo). +bool Quassel::init() +{ + if (_initialized) + return true; // allow multiple invocations because of MonolithicApplication + + if (_handleCrashes) { + // we have crashhandler for win32 and unix (based on execinfo). #if defined(Q_OS_WIN32) || defined(HAVE_EXECINFO) # ifndef Q_OS_WIN32 - // we only handle crashes ourselves if coredumps are disabled - struct rlimit *limit = (rlimit *) malloc(sizeof(struct rlimit)); - int rc = getrlimit(RLIMIT_CORE, limit); + // we only handle crashes ourselves if coredumps are disabled + struct rlimit *limit = (rlimit *)malloc(sizeof(struct rlimit)); + int rc = getrlimit(RLIMIT_CORE, limit); - if(rc == -1 || !((long)limit->rlim_cur > 0 || limit->rlim_cur == RLIM_INFINITY)) { + if (rc == -1 || !((long)limit->rlim_cur > 0 || limit->rlim_cur == RLIM_INFINITY)) { # endif /* Q_OS_WIN32 */ - signal(SIGABRT, handleSignal); - signal(SIGSEGV, handleSignal); + signal(SIGABRT, handleSignal); + signal(SIGSEGV, handleSignal); # ifndef Q_OS_WIN32 - signal(SIGBUS, handleSignal); + signal(SIGBUS, handleSignal); } free(limit); # endif /* Q_OS_WIN32 */ #endif /* Q_OS_WIN32 || HAVE_EXECINFO */ - } - - _initialized = true; - qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); - - registerMetaTypes(); - - Network::setDefaultCodecForServer("ISO-8859-1"); - Network::setDefaultCodecForEncoding("UTF-8"); - Network::setDefaultCodecForDecoding("ISO-8859-15"); - - if(isOptionSet("help")) { - cliParser()->usage(); - return false; - } + } - if(isOptionSet("version")) { - std::cout << qPrintable("Quassel IRC: " + Quassel::buildInfo().plainVersionString) << std::endl; - return false; - } + _initialized = true; + qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime())); - DEBUG = isOptionSet("debug"); + registerMetaTypes(); - // set up logging - if(Quassel::runMode() != Quassel::ClientOnly) { - if(isOptionSet("loglevel")) { - QString level = optionValue("loglevel"); + Network::setDefaultCodecForServer("ISO-8859-1"); + Network::setDefaultCodecForEncoding("UTF-8"); + Network::setDefaultCodecForDecoding("ISO-8859-15"); - if(level == "Debug") _logLevel = DebugLevel; - else if(level == "Info") _logLevel = InfoLevel; - else if(level == "Warning") _logLevel= WarningLevel; - else if(level == "Error") _logLevel = ErrorLevel; + if (isOptionSet("help")) { + cliParser()->usage(); + return false; } - QString logfilename = optionValue("logfile"); - if(!logfilename.isEmpty()) { - _logFile = new QFile(logfilename); - if(!_logFile->open(QIODevice::Append | QIODevice::Text)) { - qWarning() << "Could not open log file" << logfilename << ":" << _logFile->errorString(); - _logFile->deleteLater(); - _logFile = 0; - } + if (isOptionSet("version")) { + std::cout << qPrintable("Quassel IRC: " + Quassel::buildInfo().plainVersionString) << std::endl; + return false; } + + DEBUG = isOptionSet("debug"); + + // set up logging + if (Quassel::runMode() != Quassel::ClientOnly) { + if (isOptionSet("loglevel")) { + QString level = optionValue("loglevel"); + + if (level == "Debug") _logLevel = DebugLevel; + else if (level == "Info") _logLevel = InfoLevel; + else if (level == "Warning") _logLevel = WarningLevel; + else if (level == "Error") _logLevel = ErrorLevel; + } + + QString logfilename = optionValue("logfile"); + if (!logfilename.isEmpty()) { + _logFile = new QFile(logfilename); + if (!_logFile->open(QIODevice::Append | QIODevice::Text)) { + qWarning() << "Could not open log file" << logfilename << ":" << _logFile->errorString(); + _logFile->deleteLater(); + _logFile = 0; + } + } #ifdef HAVE_SYSLOG - _logToSyslog = isOptionSet("syslog"); + _logToSyslog = isOptionSet("syslog"); #endif - } + } - return true; + return true; } -void Quassel::quit() { - QCoreApplication::quit(); + +void Quassel::quit() +{ + QCoreApplication::quit(); } + //! Register our custom types with Qt's Meta Object System. /** This makes them available for QVariant and in signals/slots, among other things. * */ -void Quassel::registerMetaTypes() { - // Complex types - qRegisterMetaType("Message"); - qRegisterMetaType("BufferInfo"); - qRegisterMetaType("NetworkInfo"); - qRegisterMetaType("Network::Server"); - qRegisterMetaType("Identity"); - - qRegisterMetaTypeStreamOperators("Message"); - qRegisterMetaTypeStreamOperators("BufferInfo"); - qRegisterMetaTypeStreamOperators("NetworkInfo"); - qRegisterMetaTypeStreamOperators("Network::Server"); - qRegisterMetaTypeStreamOperators("Identity"); - - qRegisterMetaType("IdentityId"); - qRegisterMetaType("BufferId"); - qRegisterMetaType("NetworkId"); - qRegisterMetaType("UserId"); - qRegisterMetaType("AccountId"); - qRegisterMetaType("MsgId"); - - qRegisterMetaType("QHostAddress"); - - qRegisterMetaTypeStreamOperators("IdentityId"); - qRegisterMetaTypeStreamOperators("BufferId"); - qRegisterMetaTypeStreamOperators("NetworkId"); - qRegisterMetaTypeStreamOperators("UserId"); - qRegisterMetaTypeStreamOperators("AccountId"); - qRegisterMetaTypeStreamOperators("MsgId"); - - // Versions of Qt prior to 4.7 didn't define QVariant as a meta type - if(!QMetaType::type("QVariant")) { - qRegisterMetaType("QVariant"); - qRegisterMetaTypeStreamOperators("QVariant"); - } +void Quassel::registerMetaTypes() +{ + // Complex types + qRegisterMetaType("Message"); + qRegisterMetaType("BufferInfo"); + qRegisterMetaType("NetworkInfo"); + qRegisterMetaType("Network::Server"); + qRegisterMetaType("Identity"); + + qRegisterMetaTypeStreamOperators("Message"); + qRegisterMetaTypeStreamOperators("BufferInfo"); + qRegisterMetaTypeStreamOperators("NetworkInfo"); + qRegisterMetaTypeStreamOperators("Network::Server"); + qRegisterMetaTypeStreamOperators("Identity"); + + qRegisterMetaType("IdentityId"); + qRegisterMetaType("BufferId"); + qRegisterMetaType("NetworkId"); + qRegisterMetaType("UserId"); + qRegisterMetaType("AccountId"); + qRegisterMetaType("MsgId"); + + qRegisterMetaType("QHostAddress"); + + qRegisterMetaTypeStreamOperators("IdentityId"); + qRegisterMetaTypeStreamOperators("BufferId"); + qRegisterMetaTypeStreamOperators("NetworkId"); + qRegisterMetaTypeStreamOperators("UserId"); + qRegisterMetaTypeStreamOperators("AccountId"); + qRegisterMetaTypeStreamOperators("MsgId"); + + // Versions of Qt prior to 4.7 didn't define QVariant as a meta type + if (!QMetaType::type("QVariant")) { + qRegisterMetaType("QVariant"); + qRegisterMetaTypeStreamOperators("QVariant"); + } } -void Quassel::setupBuildInfo(const QString &generated) { - _buildInfo.applicationName = "Quassel IRC"; - _buildInfo.coreApplicationName = "quasselcore"; - _buildInfo.clientApplicationName = "quasselclient"; - _buildInfo.organizationName = "Quassel Project"; - _buildInfo.organizationDomain = "quassel-irc.org"; - - QStringList gen = generated.split(','); - Q_ASSERT(gen.count() == 10); - _buildInfo.baseVersion = gen[0]; - _buildInfo.generatedVersion = gen[1]; - _buildInfo.isSourceDirty = !gen[2].isEmpty(); - _buildInfo.commitHash = gen[3]; - _buildInfo.commitDate = gen[4].toUInt(); - _buildInfo.protocolVersion = gen[5].toUInt(); - _buildInfo.clientNeedsProtocol = gen[6].toUInt(); - _buildInfo.coreNeedsProtocol = gen[7].toUInt(); - _buildInfo.buildDate = QString("%1 %2").arg(gen[8], gen[9]); - // create a nice version string - if(_buildInfo.generatedVersion.isEmpty()) { - if(!_buildInfo.commitHash.isEmpty()) { - // dist version - _buildInfo.plainVersionString = QString("v%1 (dist-%2)") - .arg(_buildInfo.baseVersion) - .arg(_buildInfo.commitHash.left(7)); - _buildInfo.fancyVersionString = QString("v%1 (dist-%2)") - .arg(_buildInfo.baseVersion) - .arg(_buildInfo.commitHash.left(7)) - .arg(_buildInfo.commitHash); - } else { - // we only have a base version :( - _buildInfo.plainVersionString = QString("v%1 (unknown rev)").arg(_buildInfo.baseVersion); + +void Quassel::setupBuildInfo(const QString &generated) +{ + _buildInfo.applicationName = "Quassel IRC"; + _buildInfo.coreApplicationName = "quasselcore"; + _buildInfo.clientApplicationName = "quasselclient"; + _buildInfo.organizationName = "Quassel Project"; + _buildInfo.organizationDomain = "quassel-irc.org"; + + QStringList gen = generated.split(','); + Q_ASSERT(gen.count() == 10); + _buildInfo.baseVersion = gen[0]; + _buildInfo.generatedVersion = gen[1]; + _buildInfo.isSourceDirty = !gen[2].isEmpty(); + _buildInfo.commitHash = gen[3]; + _buildInfo.commitDate = gen[4].toUInt(); + _buildInfo.protocolVersion = gen[5].toUInt(); + _buildInfo.clientNeedsProtocol = gen[6].toUInt(); + _buildInfo.coreNeedsProtocol = gen[7].toUInt(); + _buildInfo.buildDate = QString("%1 %2").arg(gen[8], gen[9]); + // create a nice version string + if (_buildInfo.generatedVersion.isEmpty()) { + if (!_buildInfo.commitHash.isEmpty()) { + // dist version + _buildInfo.plainVersionString = QString("v%1 (dist-%2)") + .arg(_buildInfo.baseVersion) + .arg(_buildInfo.commitHash.left(7)); + _buildInfo.fancyVersionString = QString("v%1 (dist-%2)") + .arg(_buildInfo.baseVersion) + .arg(_buildInfo.commitHash.left(7)) + .arg(_buildInfo.commitHash); + } + else { + // we only have a base version :( + _buildInfo.plainVersionString = QString("v%1 (unknown rev)").arg(_buildInfo.baseVersion); + } } - } else { - // analyze what we got from git-describe - QRegExp rx("(.*)-(\\d+)-g([0-9a-f]+)$"); - if(rx.exactMatch(_buildInfo.generatedVersion)) { - QString distance = rx.cap(2) == "0" ? QString() : QString("%1+%2 ").arg(rx.cap(1), rx.cap(2)); - _buildInfo.plainVersionString = QString("v%1 (%2git-%3%4)") - .arg(_buildInfo.baseVersion, distance, rx.cap(3)) - .arg(_buildInfo.isSourceDirty ? "*" : ""); - if(!_buildInfo.commitHash.isEmpty()) { - _buildInfo.fancyVersionString = QString("v%1 (%2git-%3%4)") - .arg(_buildInfo.baseVersion, distance, rx.cap(3)) - .arg(_buildInfo.isSourceDirty ? "*" : "") - .arg(_buildInfo.commitHash); - } - } else { - _buildInfo.plainVersionString = QString("v%1 (invalid rev)").arg(_buildInfo.baseVersion); + else { + // analyze what we got from git-describe + QRegExp rx("(.*)-(\\d+)-g([0-9a-f]+)$"); + if (rx.exactMatch(_buildInfo.generatedVersion)) { + QString distance = rx.cap(2) == "0" ? QString() : QString("%1+%2 ").arg(rx.cap(1), rx.cap(2)); + _buildInfo.plainVersionString = QString("v%1 (%2git-%3%4)") + .arg(_buildInfo.baseVersion, distance, rx.cap(3)) + .arg(_buildInfo.isSourceDirty ? "*" : ""); + if (!_buildInfo.commitHash.isEmpty()) { + _buildInfo.fancyVersionString = QString("v%1 (%2git-%3%4)") + .arg(_buildInfo.baseVersion, distance, rx.cap(3)) + .arg(_buildInfo.isSourceDirty ? "*" : "") + .arg(_buildInfo.commitHash); + } + } + else { + _buildInfo.plainVersionString = QString("v%1 (invalid rev)").arg(_buildInfo.baseVersion); + } } - } - if(_buildInfo.fancyVersionString.isEmpty()) - _buildInfo.fancyVersionString = _buildInfo.plainVersionString; + if (_buildInfo.fancyVersionString.isEmpty()) + _buildInfo.fancyVersionString = _buildInfo.plainVersionString; } + //! Signal handler for graceful shutdown. -void Quassel::handleSignal(int sig) { - switch(sig) { - case SIGTERM: - case SIGINT: - qWarning("%s", qPrintable(QString("Caught signal %1 - exiting.").arg(sig))); - if(_instance) - _instance->quit(); - else - QCoreApplication::quit(); - break; - case SIGABRT: - case SIGSEGV: +void Quassel::handleSignal(int sig) +{ + switch (sig) { + case SIGTERM: + case SIGINT: + qWarning("%s", qPrintable(QString("Caught signal %1 - exiting.").arg(sig))); + if (_instance) + _instance->quit(); + else + QCoreApplication::quit(); + break; + case SIGABRT: + case SIGSEGV: #ifndef Q_OS_WIN32 - case SIGBUS: + case SIGBUS: #endif - logBacktrace(coreDumpFileName()); - exit(EXIT_FAILURE); - break; - default: - break; - } + logBacktrace(coreDumpFileName()); + exit(EXIT_FAILURE); + break; + default: + break; + } } -void Quassel::logFatalMessage(const char *msg) { + +void Quassel::logFatalMessage(const char *msg) +{ #ifdef Q_OS_MAC - Q_UNUSED(msg) + Q_UNUSED(msg) #else - QFile dumpFile(coreDumpFileName()); - dumpFile.open(QIODevice::Append); - QTextStream dumpStream(&dumpFile); + QFile dumpFile(coreDumpFileName()); + dumpFile.open(QIODevice::Append); + QTextStream dumpStream(&dumpFile); - dumpStream << "Fatal: " << msg << '\n'; - dumpStream.flush(); - dumpFile.close(); + dumpStream << "Fatal: " << msg << '\n'; + dumpStream.flush(); + dumpFile.close(); #endif } -Quassel::Features Quassel::features() { - Features feats = 0; - for(int i = 1; i <= NumFeatures; i<<=1) - feats |= (Feature) i; - return feats; +Quassel::Features Quassel::features() +{ + Features feats = 0; + for (int i = 1; i <= NumFeatures; i <<= 1) + feats |= (Feature)i; + + return feats; } -const QString &Quassel::coreDumpFileName() { - if(_coreDumpFileName.isEmpty()) { - QDir configDir(configDirPath()); - _coreDumpFileName = configDir.absoluteFilePath(QString("Quassel-Crash-%1.log").arg(QDateTime::currentDateTime().toString("yyyyMMdd-hhmm"))); - QFile dumpFile(_coreDumpFileName); - dumpFile.open(QIODevice::Append); - QTextStream dumpStream(&dumpFile); - dumpStream << "Quassel IRC: " << _buildInfo.baseVersion << ' ' << _buildInfo.commitHash << '\n'; - qDebug() << "Quassel IRC: " << _buildInfo.baseVersion << ' ' << _buildInfo.commitHash; - dumpStream.flush(); - dumpFile.close(); - } - return _coreDumpFileName; + +const QString &Quassel::coreDumpFileName() +{ + if (_coreDumpFileName.isEmpty()) { + QDir configDir(configDirPath()); + _coreDumpFileName = configDir.absoluteFilePath(QString("Quassel-Crash-%1.log").arg(QDateTime::currentDateTime().toString("yyyyMMdd-hhmm"))); + QFile dumpFile(_coreDumpFileName); + dumpFile.open(QIODevice::Append); + QTextStream dumpStream(&dumpFile); + dumpStream << "Quassel IRC: " << _buildInfo.baseVersion << ' ' << _buildInfo.commitHash << '\n'; + qDebug() << "Quassel IRC: " << _buildInfo.baseVersion << ' ' << _buildInfo.commitHash; + dumpStream.flush(); + dumpFile.close(); + } + return _coreDumpFileName; } -QString Quassel::configDirPath() { - if(!_configDirPath.isEmpty()) - return _configDirPath; - if(Quassel::isOptionSet("datadir")) { - qWarning() << "Obsolete option --datadir used!"; - _configDirPath = Quassel::optionValue("datadir"); - } else if(Quassel::isOptionSet("configdir")) { - _configDirPath = Quassel::optionValue("configdir"); - } else { +QString Quassel::configDirPath() +{ + if (!_configDirPath.isEmpty()) + return _configDirPath; + if (Quassel::isOptionSet("datadir")) { + qWarning() << "Obsolete option --datadir used!"; + _configDirPath = Quassel::optionValue("datadir"); + } + else if (Quassel::isOptionSet("configdir")) { + _configDirPath = Quassel::optionValue("configdir"); + } + else { #ifdef Q_WS_MAC - // On Mac, the path is always the same - _configDirPath = QDir::homePath() + "/Library/Application Support/Quassel/"; + // On Mac, the path is always the same + _configDirPath = QDir::homePath() + "/Library/Application Support/Quassel/"; #else - // We abuse QSettings to find us a sensible path on the other platforms + // We abuse QSettings to find us a sensible path on the other platforms # ifdef Q_WS_WIN - // don't use the registry - QSettings::Format format = QSettings::IniFormat; + // don't use the registry + QSettings::Format format = QSettings::IniFormat; # else - QSettings::Format format = QSettings::NativeFormat; + QSettings::Format format = QSettings::NativeFormat; # endif - QSettings s(format, QSettings::UserScope, QCoreApplication::organizationDomain(), buildInfo().applicationName); - QFileInfo fileInfo(s.fileName()); - _configDirPath = fileInfo.dir().absolutePath(); + QSettings s(format, QSettings::UserScope, QCoreApplication::organizationDomain(), buildInfo().applicationName); + QFileInfo fileInfo(s.fileName()); + _configDirPath = fileInfo.dir().absolutePath(); #endif /* Q_WS_MAC */ - } + } - if(!_configDirPath.endsWith(QDir::separator()) && !_configDirPath.endsWith('/')) - _configDirPath += QDir::separator(); + if (!_configDirPath.endsWith(QDir::separator()) && !_configDirPath.endsWith('/')) + _configDirPath += QDir::separator(); - QDir qDir(_configDirPath); - if(!qDir.exists(_configDirPath)) { - if(!qDir.mkpath(_configDirPath)) { - qCritical() << "Unable to create Quassel config directory:" << qPrintable(qDir.absolutePath()); - return QString(); + QDir qDir(_configDirPath); + if (!qDir.exists(_configDirPath)) { + if (!qDir.mkpath(_configDirPath)) { + qCritical() << "Unable to create Quassel config directory:" << qPrintable(qDir.absolutePath()); + return QString(); + } } - } - return _configDirPath; + return _configDirPath; } -QStringList Quassel::dataDirPaths() { - return _dataDirPaths; + +QStringList Quassel::dataDirPaths() +{ + return _dataDirPaths; } -QStringList Quassel::findDataDirPaths() const { - QStringList dataDirNames = QString(qgetenv("XDG_DATA_DIRS")).split(':', QString::SkipEmptyParts); - if(!dataDirNames.isEmpty()) { - for(int i = 0; i < dataDirNames.count(); i++) - dataDirNames[i].append("/apps/quassel/"); - } else { - // Provide a fallback +QStringList Quassel::findDataDirPaths() const +{ + QStringList dataDirNames = QString(qgetenv("XDG_DATA_DIRS")).split(':', QString::SkipEmptyParts); + + if (!dataDirNames.isEmpty()) { + for (int i = 0; i < dataDirNames.count(); i++) + dataDirNames[i].append("/apps/quassel/"); + } + else { + // Provide a fallback #ifdef Q_OS_WIN32 - dataDirNames << qgetenv("APPDATA") + QCoreApplication::organizationDomain() + "/share/apps/quassel/" - << qgetenv("APPDATA") + QCoreApplication::organizationDomain() - << QCoreApplication::applicationDirPath(); - } + dataDirNames << qgetenv("APPDATA") + QCoreApplication::organizationDomain() + "/share/apps/quassel/" + << qgetenv("APPDATA") + QCoreApplication::organizationDomain() + << QCoreApplication::applicationDirPath(); + } #elif defined Q_WS_MAC - dataDirNames << QDir::homePath() + "/Library/Application Support/Quassel/" - << QCoreApplication::applicationDirPath(); - } + dataDirNames << QDir::homePath() + "/Library/Application Support/Quassel/" + << QCoreApplication::applicationDirPath(); + } #else - dataDirNames.append("/usr/share/apps/quassel/"); - } - // on UNIX, we always check our install prefix - QString appDir = QCoreApplication::applicationDirPath(); - int binpos = appDir.lastIndexOf("/bin"); - if(binpos >= 0) { - appDir.replace(binpos, 4, "/share"); - appDir.append("/apps/quassel/"); - if(!dataDirNames.contains(appDir)) - dataDirNames.append(appDir); - } + dataDirNames.append("/usr/share/apps/quassel/"); + } + // on UNIX, we always check our install prefix + QString appDir = QCoreApplication::applicationDirPath(); + int binpos = appDir.lastIndexOf("/bin"); + if (binpos >= 0) { + appDir.replace(binpos, 4, "/share"); + appDir.append("/apps/quassel/"); + if (!dataDirNames.contains(appDir)) + dataDirNames.append(appDir); + } #endif - // add resource path and workdir just in case - dataDirNames << QCoreApplication::applicationDirPath() + "/data/" - << ":/data/"; - - // append trailing '/' and check for existence - QStringList::Iterator iter = dataDirNames.begin(); - while(iter != dataDirNames.end()) { - if(!iter->endsWith(QDir::separator()) && !iter->endsWith('/')) - iter->append(QDir::separator()); - if(!QFile::exists(*iter)) - iter = dataDirNames.erase(iter); - else - ++iter; - } - - return dataDirNames; + // add resource path and workdir just in case + dataDirNames << QCoreApplication::applicationDirPath() + "/data/" + << ":/data/"; + + // append trailing '/' and check for existence + QStringList::Iterator iter = dataDirNames.begin(); + while (iter != dataDirNames.end()) { + if (!iter->endsWith(QDir::separator()) && !iter->endsWith('/')) + iter->append(QDir::separator()); + if (!QFile::exists(*iter)) + iter = dataDirNames.erase(iter); + else + ++iter; + } + + return dataDirNames; } -QString Quassel::findDataFilePath(const QString &fileName) { - QStringList dataDirs = dataDirPaths(); - foreach(QString dataDir, dataDirs) { - QString path = dataDir + fileName; - if(QFile::exists(path)) - return path; - } - return QString(); + +QString Quassel::findDataFilePath(const QString &fileName) +{ + QStringList dataDirs = dataDirPaths(); + foreach(QString dataDir, dataDirs) { + QString path = dataDir + fileName; + if (QFile::exists(path)) + return path; + } + return QString(); } -QStringList Quassel::scriptDirPaths() { - QStringList res(configDirPath() + "scripts/"); - foreach(QString path, dataDirPaths()) + +QStringList Quassel::scriptDirPaths() +{ + QStringList res(configDirPath() + "scripts/"); + foreach(QString path, dataDirPaths()) res << path + "scripts/"; - return res; + return res; } -QString Quassel::translationDirPath() { - if(_translationDirPath.isEmpty()) { - // We support only one translation dir; fallback mechanisms wouldn't work else. - // This means that if we have a $data/translations dir, the internal :/i18n resource won't be considered. - foreach(const QString &dir, dataDirPaths()) { - if(QFile::exists(dir + "translations/")) { - _translationDirPath = dir + "translations/"; - break; - } + +QString Quassel::translationDirPath() +{ + if (_translationDirPath.isEmpty()) { + // We support only one translation dir; fallback mechanisms wouldn't work else. + // This means that if we have a $data/translations dir, the internal :/i18n resource won't be considered. + foreach(const QString &dir, dataDirPaths()) { + if (QFile::exists(dir + "translations/")) { + _translationDirPath = dir + "translations/"; + break; + } + } + if (_translationDirPath.isEmpty()) + _translationDirPath = ":/i18n/"; } - if(_translationDirPath.isEmpty()) - _translationDirPath = ":/i18n/"; - } - return _translationDirPath; + return _translationDirPath; } -void Quassel::loadTranslation(const QLocale &locale) { - QTranslator *qtTranslator = QCoreApplication::instance()->findChild("QtTr"); - QTranslator *quasselTranslator = QCoreApplication::instance()->findChild("QuasselTr"); - if(qtTranslator) - qApp->removeTranslator(qtTranslator); - if(quasselTranslator) - qApp->removeTranslator(quasselTranslator); +void Quassel::loadTranslation(const QLocale &locale) +{ + QTranslator *qtTranslator = QCoreApplication::instance()->findChild("QtTr"); + QTranslator *quasselTranslator = QCoreApplication::instance()->findChild("QuasselTr"); + + if (qtTranslator) + qApp->removeTranslator(qtTranslator); + if (quasselTranslator) + qApp->removeTranslator(quasselTranslator); - // We use QLocale::C to indicate that we don't want a translation - if(locale.language() == QLocale::C) - return; + // We use QLocale::C to indicate that we don't want a translation + if (locale.language() == QLocale::C) + return; - qtTranslator = new QTranslator(qApp); - qtTranslator->setObjectName("QtTr"); - qApp->installTranslator(qtTranslator); + qtTranslator = new QTranslator(qApp); + qtTranslator->setObjectName("QtTr"); + qApp->installTranslator(qtTranslator); - quasselTranslator = new QTranslator(qApp); - quasselTranslator->setObjectName("QuasselTr"); - qApp->installTranslator(quasselTranslator); + quasselTranslator = new QTranslator(qApp); + quasselTranslator->setObjectName("QuasselTr"); + qApp->installTranslator(quasselTranslator); - QLocale::setDefault(locale); + QLocale::setDefault(locale); - bool success = qtTranslator->load(QString("qt_%1").arg(locale.name()), translationDirPath()); - if(!success) - qtTranslator->load(QString("qt_%1").arg(locale.name()), QLibraryInfo::location(QLibraryInfo::TranslationsPath)); - quasselTranslator->load(QString("%1").arg(locale.name()), translationDirPath()); + bool success = qtTranslator->load(QString("qt_%1").arg(locale.name()), translationDirPath()); + if (!success) + qtTranslator->load(QString("qt_%1").arg(locale.name()), QLibraryInfo::location(QLibraryInfo::TranslationsPath)); + quasselTranslator->load(QString("%1").arg(locale.name()), translationDirPath()); } diff --git a/src/common/quassel.h b/src/common/quassel.h index 30e02b20..1fe15ceb 100644 --- a/src/common/quassel.h +++ b/src/common/quassel.h @@ -29,149 +29,151 @@ class QFile; -class Quassel { - Q_DECLARE_TR_FUNCTIONS(Quassel) +class Quassel +{ + Q_DECLARE_TR_FUNCTIONS(Quassel) public: - enum RunMode { - Monolithic, - ClientOnly, - CoreOnly - }; - - struct BuildInfo { - QString fancyVersionString; // clickable rev - QString plainVersionString; // no tag - - QString baseVersion; - QString generatedVersion; - QString commitHash; - uint commitDate; - QString buildDate; - bool isSourceDirty; - uint protocolVersion; - uint clientNeedsProtocol; - uint coreNeedsProtocol; - - QString applicationName; - QString coreApplicationName; - QString clientApplicationName; - QString organizationName; - QString organizationDomain; - }; - - //! A list of features that are optional in core and/or client, but need runtime checking - /** Some features require an uptodate counterpart, but don't justify a protocol break. - * This is what we use this enum for. Add such features to it and check at runtime on the other - * side for their existence. - * - * This list should be cleaned up after every protocol break, as we can assume them to be present then. - */ - enum Feature { - SynchronizedMarkerLine = 0x0001, - SaslAuthentication = 0x0002, - - NumFeatures = 0x0002 - }; - Q_DECLARE_FLAGS(Features, Feature); - - //! The features the current version of Quassel supports (\sa Feature) - /** \return An ORed list of all enum values in Feature - */ - static Features features(); - - virtual ~Quassel(); - - static void setupBuildInfo(const QString &generated); - static inline const BuildInfo & buildInfo(); - static inline RunMode runMode(); - - static QString configDirPath(); - - //! Returns a list of data directory paths - /** There are several locations for applications to install their data files in. On Unix, - * a common location is /usr/share; others include $PREFIX/share and additional directories - * specified in the env variable XDG_DATA_DIRS. - * \return A list of directory paths to look for data files in - */ - static QStringList dataDirPaths(); - - //! Searches for a data file in the possible data directories - /** Data files can reside in $DATA_DIR/apps/quassel, where $DATA_DIR is one of the directories - * returned by \sa dataDirPaths(). - * \Note With KDE integration enabled, files are searched (only) in KDE's appdata dirs. - * \return The full path to the data file if found; a null QString else - */ - static QString findDataFilePath(const QString &filename); - - static QString translationDirPath(); - - //! Returns a list of directories we look for scripts in - /** We look for a subdirectory named "scripts" in the configdir and in all datadir paths. - * \return A list of directory paths containing executable scripts for /exec - */ - static QStringList scriptDirPaths(); - - static void loadTranslation(const QLocale &locale); - - static inline void setCliParser(AbstractCliParser *cliParser); - static inline AbstractCliParser *cliParser(); - static inline QString optionValue(const QString &option); - static inline bool isOptionSet(const QString &option); - - static const QString &coreDumpFileName(); - - static bool DEBUG; - - enum LogLevel { - DebugLevel, - InfoLevel, - WarningLevel, - ErrorLevel - }; - - static inline LogLevel logLevel(); - static inline QFile *logFile(); - static inline bool logToSyslog(); - - static void logFatalMessage(const char *msg); + enum RunMode { + Monolithic, + ClientOnly, + CoreOnly + }; + + struct BuildInfo { + QString fancyVersionString; // clickable rev + QString plainVersionString; // no tag + + QString baseVersion; + QString generatedVersion; + QString commitHash; + uint commitDate; + QString buildDate; + bool isSourceDirty; + uint protocolVersion; + uint clientNeedsProtocol; + uint coreNeedsProtocol; + + QString applicationName; + QString coreApplicationName; + QString clientApplicationName; + QString organizationName; + QString organizationDomain; + }; + + //! A list of features that are optional in core and/or client, but need runtime checking + /** Some features require an uptodate counterpart, but don't justify a protocol break. + * This is what we use this enum for. Add such features to it and check at runtime on the other + * side for their existence. + * + * This list should be cleaned up after every protocol break, as we can assume them to be present then. + */ + enum Feature { + SynchronizedMarkerLine = 0x0001, + SaslAuthentication = 0x0002, + + NumFeatures = 0x0002 + }; + Q_DECLARE_FLAGS(Features, Feature); + + //! The features the current version of Quassel supports (\sa Feature) + /** \return An ORed list of all enum values in Feature + */ + static Features features(); + + virtual ~Quassel(); + + static void setupBuildInfo(const QString &generated); + static inline const BuildInfo &buildInfo(); + static inline RunMode runMode(); + + static QString configDirPath(); + + //! Returns a list of data directory paths + /** There are several locations for applications to install their data files in. On Unix, + * a common location is /usr/share; others include $PREFIX/share and additional directories + * specified in the env variable XDG_DATA_DIRS. + * \return A list of directory paths to look for data files in + */ + static QStringList dataDirPaths(); + + //! Searches for a data file in the possible data directories + /** Data files can reside in $DATA_DIR/apps/quassel, where $DATA_DIR is one of the directories + * returned by \sa dataDirPaths(). + * \Note With KDE integration enabled, files are searched (only) in KDE's appdata dirs. + * \return The full path to the data file if found; a null QString else + */ + static QString findDataFilePath(const QString &filename); + + static QString translationDirPath(); + + //! Returns a list of directories we look for scripts in + /** We look for a subdirectory named "scripts" in the configdir and in all datadir paths. + * \return A list of directory paths containing executable scripts for /exec + */ + static QStringList scriptDirPaths(); + + static void loadTranslation(const QLocale &locale); + + static inline void setCliParser(AbstractCliParser *cliParser); + static inline AbstractCliParser *cliParser(); + static inline QString optionValue(const QString &option); + static inline bool isOptionSet(const QString &option); + + static const QString &coreDumpFileName(); + + static bool DEBUG; + + enum LogLevel { + DebugLevel, + InfoLevel, + WarningLevel, + ErrorLevel + }; + + static inline LogLevel logLevel(); + static inline QFile *logFile(); + static inline bool logToSyslog(); + + static void logFatalMessage(const char *msg); protected: - Quassel(); - virtual bool init(); - virtual void quit(); + Quassel(); + virtual bool init(); + virtual void quit(); - inline void setRunMode(RunMode mode); - inline void setDataDirPaths(const QStringList &paths); - QStringList findDataDirPaths() const; - inline void disableCrashhandler(); + inline void setRunMode(RunMode mode); + inline void setDataDirPaths(const QStringList &paths); + QStringList findDataDirPaths() const; + inline void disableCrashhandler(); private: - void registerMetaTypes(); - - static void handleSignal(int signal); - static void logBacktrace(const QString &filename); - - static Quassel *_instance; - static BuildInfo _buildInfo; - static AbstractCliParser *_cliParser; - static RunMode _runMode; - static bool _initialized; - static bool _handleCrashes; - - static QString _coreDumpFileName; - static QString _configDirPath; - static QStringList _dataDirPaths; - static QString _translationDirPath; - - static LogLevel _logLevel; - static QFile *_logFile; - static bool _logToSyslog; + void registerMetaTypes(); + + static void handleSignal(int signal); + static void logBacktrace(const QString &filename); + + static Quassel *_instance; + static BuildInfo _buildInfo; + static AbstractCliParser *_cliParser; + static RunMode _runMode; + static bool _initialized; + static bool _handleCrashes; + + static QString _coreDumpFileName; + static QString _configDirPath; + static QStringList _dataDirPaths; + static QString _translationDirPath; + + static LogLevel _logLevel; + static QFile *_logFile; + static bool _logToSyslog; }; + Q_DECLARE_OPERATORS_FOR_FLAGS(Quassel::Features); -const Quassel::BuildInfo & Quassel::buildInfo() { return _buildInfo; } +const Quassel::BuildInfo &Quassel::buildInfo() { return _buildInfo; } Quassel::RunMode Quassel::runMode() { return _runMode; } void Quassel::setRunMode(Quassel::RunMode mode) { _runMode = mode; } void Quassel::setDataDirPaths(const QStringList &paths) { _dataDirPaths = paths; } diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 24ddd5fc..10447eae 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -58,89 +58,106 @@ QHash Settings::settingsChangeNotifier; // */ // } -void Settings::notify(const QString &key, QObject *receiver, const char *slot) { - QObject::connect(notifier(normalizedKey(group, key)), SIGNAL(valueChanged(const QVariant &)), - receiver, slot); +void Settings::notify(const QString &key, QObject *receiver, const char *slot) +{ + QObject::connect(notifier(normalizedKey(group, key)), SIGNAL(valueChanged(const QVariant &)), + receiver, slot); } -void Settings::initAndNotify(const QString &key, QObject *receiver, const char *slot, const QVariant &defaultValue) { - notify(key, receiver, slot); - emit notifier(normalizedKey(group, key))->valueChanged(localValue(key, defaultValue)); -} -uint Settings::version() { - // we don't cache this value, and we ignore the group - create_qsettings; - uint ver = s.value("Config/Version", 0).toUInt(); - if(!ver) { - // No version, so create one - s.setValue("Config/Version", VERSION); - return VERSION; - } - return ver; +void Settings::initAndNotify(const QString &key, QObject *receiver, const char *slot, const QVariant &defaultValue) +{ + notify(key, receiver, slot); + emit notifier(normalizedKey(group, key))->valueChanged(localValue(key, defaultValue)); } -QStringList Settings::allLocalKeys() { - create_qsettings; - s.beginGroup(group); - QStringList res = s.allKeys(); - s.endGroup(); - return res; + +uint Settings::version() +{ + // we don't cache this value, and we ignore the group + create_qsettings; + uint ver = s.value("Config/Version", 0).toUInt(); + if (!ver) { + // No version, so create one + s.setValue("Config/Version", VERSION); + return VERSION; + } + return ver; } -QStringList Settings::localChildKeys(const QString &rootkey) { - QString g; - if(rootkey.isEmpty()) - g = group; - else - g = QString("%1/%2").arg(group, rootkey); - - create_qsettings; - s.beginGroup(g); - QStringList res = s.childKeys(); - s.endGroup(); - return res; + +QStringList Settings::allLocalKeys() +{ + create_qsettings; + s.beginGroup(group); + QStringList res = s.allKeys(); + s.endGroup(); + return res; } -QStringList Settings::localChildGroups(const QString &rootkey) { - QString g; - if(rootkey.isEmpty()) - g = group; - else - g = QString("%1/%2").arg(group, rootkey); - - create_qsettings; - s.beginGroup(g); - QStringList res = s.childGroups(); - s.endGroup(); - return res; + +QStringList Settings::localChildKeys(const QString &rootkey) +{ + QString g; + if (rootkey.isEmpty()) + g = group; + else + g = QString("%1/%2").arg(group, rootkey); + + create_qsettings; + s.beginGroup(g); + QStringList res = s.childKeys(); + s.endGroup(); + return res; } -void Settings::setLocalValue(const QString &key, const QVariant &data) { - QString normKey = normalizedKey(group, key); - create_qsettings; - s.setValue(normKey, data); - setCacheValue(normKey, data); - if(hasNotifier(normKey)) { - emit notifier(normKey)->valueChanged(data); - } + +QStringList Settings::localChildGroups(const QString &rootkey) +{ + QString g; + if (rootkey.isEmpty()) + g = group; + else + g = QString("%1/%2").arg(group, rootkey); + + create_qsettings; + s.beginGroup(g); + QStringList res = s.childGroups(); + s.endGroup(); + return res; } -const QVariant &Settings::localValue(const QString &key, const QVariant &def) { - QString normKey = normalizedKey(group, key); - if(!isCached(normKey)) { + +void Settings::setLocalValue(const QString &key, const QVariant &data) +{ + QString normKey = normalizedKey(group, key); create_qsettings; - setCacheValue(normKey, s.value(normKey, def)); - } - return cacheValue(normKey); + s.setValue(normKey, data); + setCacheValue(normKey, data); + if (hasNotifier(normKey)) { + emit notifier(normKey)->valueChanged(data); + } +} + + +const QVariant &Settings::localValue(const QString &key, const QVariant &def) +{ + QString normKey = normalizedKey(group, key); + if (!isCached(normKey)) { + create_qsettings; + setCacheValue(normKey, s.value(normKey, def)); + } + return cacheValue(normKey); } -void Settings::removeLocalKey(const QString &key) { - create_qsettings; - s.beginGroup(group); - s.remove(key); - s.endGroup(); - QString normKey = normalizedKey(group, key); - if(isCached(normKey)) - settingsCache.remove(normKey); + +void Settings::removeLocalKey(const QString &key) +{ + create_qsettings; + s.beginGroup(group); + s.remove(key); + s.endGroup(); + QString normKey = normalizedKey(group, key); + if (isCached(normKey)) + settingsCache.remove(normKey); } diff --git a/src/common/settings.h b/src/common/settings.h index e2920c24..a5aa9adc 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -29,88 +29,110 @@ #include "quassel.h" -class SettingsChangeNotifier : public QObject { - Q_OBJECT +class SettingsChangeNotifier : public QObject +{ + Q_OBJECT signals: - void valueChanged(const QVariant &newValue); + void valueChanged(const QVariant &newValue); private: - friend class Settings; + friend class Settings; }; -class Settings { + +class Settings +{ public: - enum Mode { Default, Custom }; + enum Mode { Default, Custom }; public: - //! Call the given slot on change of the given key - virtual void notify(const QString &key, QObject *receiver, const char *slot); + //! Call the given slot on change of the given key + virtual void notify(const QString &key, QObject *receiver, const char *slot); - //! Sets up notification and calls the given slot to set the initial value - void initAndNotify(const QString &key, QObject *receiver, const char *slot, const QVariant &defaultValue = QVariant()); + //! Sets up notification and calls the given slot to set the initial value + void initAndNotify(const QString &key, QObject *receiver, const char *slot, const QVariant &defaultValue = QVariant()); - virtual uint version(); + virtual uint version(); protected: - inline Settings(QString group_, QString appName_) : group(group_), appName(appName_) {} - inline virtual ~Settings() {} + inline Settings(QString group_, QString appName_) : group(group_), appName(appName_) {} + inline virtual ~Settings() {} - inline void setGroup(const QString &group_) { group = group_; } + inline void setGroup(const QString &group_) { group = group_; } - virtual QStringList allLocalKeys(); - virtual QStringList localChildKeys(const QString &rootkey = QString()); - virtual QStringList localChildGroups(const QString &rootkey = QString()); + virtual QStringList allLocalKeys(); + virtual QStringList localChildKeys(const QString &rootkey = QString()); + virtual QStringList localChildGroups(const QString &rootkey = QString()); - virtual void setLocalValue(const QString &key, const QVariant &data); - virtual const QVariant &localValue(const QString &key, const QVariant &def = QVariant()); + virtual void setLocalValue(const QString &key, const QVariant &data); + virtual const QVariant &localValue(const QString &key, const QVariant &def = QVariant()); - virtual void removeLocalKey(const QString &key); + virtual void removeLocalKey(const QString &key); - QString group; - QString appName; + QString group; + QString appName; private: - inline QSettings::Format format() { + inline QSettings::Format format() + { #ifdef Q_WS_WIN - return QSettings::IniFormat; + return QSettings::IniFormat; #else - return QSettings::NativeFormat; + return QSettings::NativeFormat; #endif - } - inline QString fileName() { - return Quassel::configDirPath() + appName - + ((format() == QSettings::NativeFormat) ? QLatin1String(".conf") : QLatin1String(".ini")); - } - - static QHash settingsCache; - static QHash settingsChangeNotifier; - - inline QString normalizedKey(const QString &group, const QString &key) { - if(group.isEmpty()) - return key; - return group + '/' + key; - } - - inline void setCacheValue(const QString &normKey, const QVariant &data) { - settingsCache[normKey] = data; - } - inline const QVariant &cacheValue(const QString &normKey) { - return settingsCache[normKey]; - } - inline bool isCached(const QString &normKey) { - return settingsCache.contains(normKey); - } - - inline SettingsChangeNotifier *notifier(const QString &normKey) { - if(!hasNotifier(normKey)) - settingsChangeNotifier[normKey] = new SettingsChangeNotifier(); - return settingsChangeNotifier[normKey]; - } - - inline bool hasNotifier(const QString &normKey) { - return settingsChangeNotifier.contains(normKey); - } + } + + + inline QString fileName() + { + return Quassel::configDirPath() + appName + + ((format() == QSettings::NativeFormat) ? QLatin1String(".conf") : QLatin1String(".ini")); + } + + + static QHash settingsCache; + static QHash settingsChangeNotifier; + + inline QString normalizedKey(const QString &group, const QString &key) + { + if (group.isEmpty()) + return key; + return group + '/' + key; + } + + + inline void setCacheValue(const QString &normKey, const QVariant &data) + { + settingsCache[normKey] = data; + } + + + inline const QVariant &cacheValue(const QString &normKey) + { + return settingsCache[normKey]; + } + + + inline bool isCached(const QString &normKey) + { + return settingsCache.contains(normKey); + } + + + inline SettingsChangeNotifier *notifier(const QString &normKey) + { + if (!hasNotifier(normKey)) + settingsChangeNotifier[normKey] = new SettingsChangeNotifier(); + return settingsChangeNotifier[normKey]; + } + + + inline bool hasNotifier(const QString &normKey) + { + return settingsChangeNotifier.contains(normKey); + } }; + #endif diff --git a/src/common/signalproxy.cpp b/src/common/signalproxy.cpp index 8943f754..a2661b55 100644 --- a/src/common/signalproxy.cpp +++ b/src/common/signalproxy.cpp @@ -46,1047 +46,1171 @@ // ================================================== // PeerSignalEvent // ================================================== -class PeerSignalEvent : public QEvent { +class PeerSignalEvent : public QEvent +{ public: - PeerSignalEvent(SignalProxy *sender, SignalProxy::RequestType requestType, const QVariantList ¶ms) : QEvent(QEvent::Type(SignalProxy::PeerSignal)), sender(sender), requestType(requestType), params(params) {} - SignalProxy *sender; - SignalProxy::RequestType requestType; - QVariantList params; + PeerSignalEvent(SignalProxy *sender, SignalProxy::RequestType requestType, const QVariantList ¶ms) : QEvent(QEvent::Type(SignalProxy::PeerSignal)), sender(sender), requestType(requestType), params(params) {} + SignalProxy *sender; + SignalProxy::RequestType requestType; + QVariantList params; }; -class RemovePeerEvent : public QEvent { + +class RemovePeerEvent : public QEvent +{ public: - RemovePeerEvent(QObject *peer) : QEvent(QEvent::Type(SignalProxy::RemovePeer)), peer(peer) {} - QObject *peer; + RemovePeerEvent(QObject *peer) : QEvent(QEvent::Type(SignalProxy::RemovePeer)), peer(peer) {} + QObject *peer; }; + // ================================================== // SignalRelay // ================================================== -class SignalProxy::SignalRelay : public QObject { +class SignalProxy::SignalRelay : public QObject +{ /* Q_OBJECT is not necessary or even allowed, because we implement qt_metacall ourselves (and don't use any other features of the meta object system) */ public: - SignalRelay(SignalProxy *parent) : QObject(parent), _proxy(parent) {} - inline SignalProxy *proxy() const { return _proxy; } + SignalRelay(SignalProxy *parent) : QObject(parent), _proxy(parent) {} + inline SignalProxy *proxy() const { return _proxy; } - int qt_metacall(QMetaObject::Call _c, int _id, void **_a); + int qt_metacall(QMetaObject::Call _c, int _id, void **_a); - void attachSignal(QObject *sender, int signalId, const QByteArray &funcName); - void detachSignal(QObject *sender, int signalId = -1); + void attachSignal(QObject *sender, int signalId, const QByteArray &funcName); + void detachSignal(QObject *sender, int signalId = -1); private: - struct Signal { - QObject *sender; - int signalId; - QByteArray signature; - Signal(QObject *sender, int sigId, const QByteArray &signature) : sender(sender), signalId(sigId), signature(signature) {} - Signal() : sender(0), signalId(-1) {} - }; - - SignalProxy *_proxy; - QHash _slots; + struct Signal { + QObject *sender; + int signalId; + QByteArray signature; + Signal(QObject *sender, int sigId, const QByteArray &signature) : sender(sender), signalId(sigId), signature(signature) {} + Signal() : sender(0), signalId(-1) {} + }; + + SignalProxy *_proxy; + QHash _slots; }; -void SignalProxy::SignalRelay::attachSignal(QObject *sender, int signalId, const QByteArray &funcName) { - // we ride without safetybelts here... all checking for valid method etc pp has to be done by the caller - // all connected methodIds are offset by the standard methodCount of QObject - int slotId; - for(int i = 0;; i++) { - if(!_slots.contains(i)) { - slotId = i; - break; + +void SignalProxy::SignalRelay::attachSignal(QObject *sender, int signalId, const QByteArray &funcName) +{ + // we ride without safetybelts here... all checking for valid method etc pp has to be done by the caller + // all connected methodIds are offset by the standard methodCount of QObject + int slotId; + for (int i = 0;; i++) { + if (!_slots.contains(i)) { + slotId = i; + break; + } } - } - QByteArray fn; - if(!funcName.isEmpty()) { - fn = QMetaObject::normalizedSignature(funcName); - } else { - fn = SIGNAL(fakeMethodSignature()); - fn = fn.replace("fakeMethodSignature()", sender->metaObject()->method(signalId).signature()); - } + QByteArray fn; + if (!funcName.isEmpty()) { + fn = QMetaObject::normalizedSignature(funcName); + } + else { + fn = SIGNAL(fakeMethodSignature()); + fn = fn.replace("fakeMethodSignature()", sender->metaObject()->method(signalId).signature()); + } - _slots[slotId] = Signal(sender, signalId, fn); + _slots[slotId] = Signal(sender, signalId, fn); - QMetaObject::connect(sender, signalId, this, QObject::staticMetaObject.methodCount() + slotId); + QMetaObject::connect(sender, signalId, this, QObject::staticMetaObject.methodCount() + slotId); } -void SignalProxy::SignalRelay::detachSignal(QObject *sender, int signalId) { - QHash::iterator slotIter = _slots.begin(); - while(slotIter != _slots.end()) { - if(slotIter->sender == sender && (signalId == -1 || slotIter->signalId == signalId)) { - slotIter = _slots.erase(slotIter); - if(signalId != -1) - break; - } else { - slotIter++; + +void SignalProxy::SignalRelay::detachSignal(QObject *sender, int signalId) +{ + QHash::iterator slotIter = _slots.begin(); + while (slotIter != _slots.end()) { + if (slotIter->sender == sender && (signalId == -1 || slotIter->signalId == signalId)) { + slotIter = _slots.erase(slotIter); + if (signalId != -1) + break; + } + else { + slotIter++; + } } - } } -int SignalProxy::SignalRelay::qt_metacall(QMetaObject::Call _c, int _id, void **_a) { - _id = QObject::qt_metacall(_c, _id, _a); - if(_id < 0) - return _id; - if(_c == QMetaObject::InvokeMetaMethod) { - if(_slots.contains(_id)) { - QObject *caller = sender(); +int SignalProxy::SignalRelay::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QObject::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; - SignalProxy::ExtendedMetaObject *eMeta = proxy()->extendedMetaObject(caller->metaObject()); - Q_ASSERT(eMeta); + if (_c == QMetaObject::InvokeMetaMethod) { + if (_slots.contains(_id)) { + QObject *caller = sender(); - const Signal &signal = _slots[_id]; + SignalProxy::ExtendedMetaObject *eMeta = proxy()->extendedMetaObject(caller->metaObject()); + Q_ASSERT(eMeta); - QVariantList params; - params << signal.signature; + const Signal &signal = _slots[_id]; - const QList &argTypes = eMeta->argTypes(signal.signalId); - for(int i = 0; i < argTypes.size(); i++) { - if(argTypes[i] == 0) { - qWarning() << "SignalRelay::qt_metacall(): received invalid data for argument number" << i << "of signal" << QString("%1::%2").arg(caller->metaObject()->className()).arg(caller->metaObject()->method(_id).signature()); - qWarning() << " - make sure all your data types are known by the Qt MetaSystem"; - return _id; - } - params << QVariant(argTypes[i], _a[i+1]); - } + QVariantList params; + params << signal.signature; + + const QList &argTypes = eMeta->argTypes(signal.signalId); + for (int i = 0; i < argTypes.size(); i++) { + if (argTypes[i] == 0) { + qWarning() << "SignalRelay::qt_metacall(): received invalid data for argument number" << i << "of signal" << QString("%1::%2").arg(caller->metaObject()->className()).arg(caller->metaObject()->method(_id).signature()); + qWarning() << " - make sure all your data types are known by the Qt MetaSystem"; + return _id; + } + params << QVariant(argTypes[i], _a[i+1]); + } - proxy()->dispatchSignal(SignalProxy::RpcCall, params); + proxy()->dispatchSignal(SignalProxy::RpcCall, params); + } + _id -= _slots.count(); } - _id -= _slots.count(); - } - return _id; + return _id; } + // ================================================== // Peers // ================================================== -void SignalProxy::IODevicePeer::dispatchSignal(const RequestType &requestType, const QVariantList ¶ms) { - QVariantList packedFunc; - packedFunc << (qint16)requestType - << params; - dispatchPackedFunc(QVariant(packedFunc)); +void SignalProxy::IODevicePeer::dispatchSignal(const RequestType &requestType, const QVariantList ¶ms) +{ + QVariantList packedFunc; + packedFunc << (qint16)requestType + << params; + dispatchPackedFunc(QVariant(packedFunc)); } -bool SignalProxy::IODevicePeer::isSecure() const { + +bool SignalProxy::IODevicePeer::isSecure() const +{ #ifdef HAVE_SSL - QSslSocket *sslSocket = qobject_cast(_device); - if(sslSocket) - return sslSocket->isEncrypted() || sslSocket->localAddress() == QHostAddress::LocalHost || sslSocket->localAddress() == QHostAddress::LocalHostIPv6; + QSslSocket *sslSocket = qobject_cast(_device); + if (sslSocket) + return sslSocket->isEncrypted() || sslSocket->localAddress() == QHostAddress::LocalHost || sslSocket->localAddress() == QHostAddress::LocalHostIPv6; #endif - QAbstractSocket *socket = qobject_cast(_device); - if(socket) - return socket->localAddress() == QHostAddress::LocalHost || socket->localAddress() == QHostAddress::LocalHostIPv6; + QAbstractSocket *socket = qobject_cast(_device); + if (socket) + return socket->localAddress() == QHostAddress::LocalHost || socket->localAddress() == QHostAddress::LocalHostIPv6; - return false; + return false; } -QString SignalProxy::IODevicePeer::address() const { - QAbstractSocket *socket = qobject_cast(_device); - if(socket) - return socket->peerAddress().toString(); - else - return QString(); + +QString SignalProxy::IODevicePeer::address() const +{ + QAbstractSocket *socket = qobject_cast(_device); + if (socket) + return socket->peerAddress().toString(); + else + return QString(); } -void SignalProxy::SignalProxyPeer::dispatchSignal(const RequestType &requestType, const QVariantList ¶ms) { - Qt::ConnectionType type = QThread::currentThread() == receiver->thread() - ? Qt::DirectConnection - : Qt::QueuedConnection; - if(type == Qt::DirectConnection) { - receiver->receivePeerSignal(sender, requestType, params); - } else { - QCoreApplication::postEvent(receiver, new PeerSignalEvent(sender, requestType, params)); - } +void SignalProxy::SignalProxyPeer::dispatchSignal(const RequestType &requestType, const QVariantList ¶ms) +{ + Qt::ConnectionType type = QThread::currentThread() == receiver->thread() + ? Qt::DirectConnection + : Qt::QueuedConnection; + + if (type == Qt::DirectConnection) { + receiver->receivePeerSignal(sender, requestType, params); + } + else { + QCoreApplication::postEvent(receiver, new PeerSignalEvent(sender, requestType, params)); + } } + // ================================================== // SignalProxy // ================================================== -SignalProxy::SignalProxy(QObject* parent) - : QObject(parent) +SignalProxy::SignalProxy(QObject *parent) + : QObject(parent) { - setProxyMode(Client); - init(); + setProxyMode(Client); + init(); } -SignalProxy::SignalProxy(ProxyMode mode, QObject* parent) - : QObject(parent) + +SignalProxy::SignalProxy(ProxyMode mode, QObject *parent) + : QObject(parent) { - setProxyMode(mode); - init(); + setProxyMode(mode); + init(); } -SignalProxy::SignalProxy(ProxyMode mode, QIODevice* device, QObject* parent) - : QObject(parent) + +SignalProxy::SignalProxy(ProxyMode mode, QIODevice *device, QObject *parent) + : QObject(parent) { - setProxyMode(mode); - addPeer(device); - init(); + setProxyMode(mode); + addPeer(device); + init(); } -SignalProxy::~SignalProxy() { - QHash::iterator classIter = _syncSlave.begin(); - while(classIter != _syncSlave.end()) { - ObjectId::iterator objIter = classIter->begin(); - while(objIter != classIter->end()) { - SyncableObject *obj = objIter.value(); - objIter = classIter->erase(objIter); - obj->stopSynchronize(this); + +SignalProxy::~SignalProxy() +{ + QHash::iterator classIter = _syncSlave.begin(); + while (classIter != _syncSlave.end()) { + ObjectId::iterator objIter = classIter->begin(); + while (objIter != classIter->end()) { + SyncableObject *obj = objIter.value(); + objIter = classIter->erase(objIter); + obj->stopSynchronize(this); + } + classIter++; } - classIter++; - } - _syncSlave.clear(); + _syncSlave.clear(); - removeAllPeers(); + removeAllPeers(); } -void SignalProxy::setProxyMode(ProxyMode mode) { - PeerHash::iterator peer = _peers.begin(); - while(peer != _peers.end()) { - if((*peer)->type() != AbstractPeer::IODevicePeer) { - IODevicePeer *ioPeer = static_cast(*peer); - if(ioPeer->isOpen()) { - qWarning() << "SignalProxy: Cannot change proxy mode while connected"; - return; - } - } - if((*peer)->type() != AbstractPeer::SignalProxyPeer) { - qWarning() << "SignalProxy: Cannot change proxy mode while connected to another internal SignalProxy"; - return; + +void SignalProxy::setProxyMode(ProxyMode mode) +{ + PeerHash::iterator peer = _peers.begin(); + while (peer != _peers.end()) { + if ((*peer)->type() != AbstractPeer::IODevicePeer) { + IODevicePeer *ioPeer = static_cast(*peer); + if (ioPeer->isOpen()) { + qWarning() << "SignalProxy: Cannot change proxy mode while connected"; + return; + } + } + if ((*peer)->type() != AbstractPeer::SignalProxyPeer) { + qWarning() << "SignalProxy: Cannot change proxy mode while connected to another internal SignalProxy"; + return; + } + peer++; } - peer++; - } - _proxyMode = mode; - if(mode == Server) - initServer(); - else - initClient(); + _proxyMode = mode; + if (mode == Server) + initServer(); + else + initClient(); } -void SignalProxy::init() { - _heartBeatInterval = 0; - _maxHeartBeatCount = 0; - _signalRelay = new SignalRelay(this); - connect(&_heartBeatTimer, SIGNAL(timeout()), this, SLOT(sendHeartBeat())); - setHeartBeatInterval(30); - setMaxHeartBeatCount(2); - _heartBeatTimer.start(); - _secure = false; - updateSecureState(); + +void SignalProxy::init() +{ + _heartBeatInterval = 0; + _maxHeartBeatCount = 0; + _signalRelay = new SignalRelay(this); + connect(&_heartBeatTimer, SIGNAL(timeout()), this, SLOT(sendHeartBeat())); + setHeartBeatInterval(30); + setMaxHeartBeatCount(2); + _heartBeatTimer.start(); + _secure = false; + updateSecureState(); } -void SignalProxy::initServer() { + +void SignalProxy::initServer() +{ } -void SignalProxy::initClient() { - attachSlot("__objectRenamed__", this, SLOT(objectRenamed(QByteArray, QString, QString))); + +void SignalProxy::initClient() +{ + attachSlot("__objectRenamed__", this, SLOT(objectRenamed(QByteArray, QString, QString))); } -bool SignalProxy::addPeer(QIODevice* iodev) { - if(!iodev) - return false; - if(_peers.contains(iodev)) - return true; +bool SignalProxy::addPeer(QIODevice *iodev) +{ + if (!iodev) + return false; - if(proxyMode() == Client && !_peers.isEmpty()) { - qWarning("SignalProxy: only one peer allowed in client mode!"); - return false; - } + if (_peers.contains(iodev)) + return true; - if(!iodev->isOpen()) { - qWarning("SignalProxy::addPeer(QIODevice *iodev): iodev needs to be open!"); - return false; - } + if (proxyMode() == Client && !_peers.isEmpty()) { + qWarning("SignalProxy: only one peer allowed in client mode!"); + return false; + } - connect(iodev, SIGNAL(disconnected()), this, SLOT(removePeerBySender())); - connect(iodev, SIGNAL(readyRead()), this, SLOT(dataAvailable())); + if (!iodev->isOpen()) { + qWarning("SignalProxy::addPeer(QIODevice *iodev): iodev needs to be open!"); + return false; + } + + connect(iodev, SIGNAL(disconnected()), this, SLOT(removePeerBySender())); + connect(iodev, SIGNAL(readyRead()), this, SLOT(dataAvailable())); #ifdef HAVE_SSL - QSslSocket *sslSocket = qobject_cast(iodev); - if(sslSocket) { - connect(iodev, SIGNAL(encrypted()), this, SLOT(updateSecureState())); - } + QSslSocket *sslSocket = qobject_cast(iodev); + if (sslSocket) { + connect(iodev, SIGNAL(encrypted()), this, SLOT(updateSecureState())); + } #endif - if(!iodev->parent()) - iodev->setParent(this); + if (!iodev->parent()) + iodev->setParent(this); - _peers[iodev] = new IODevicePeer(iodev, iodev->property("UseCompression").toBool()); + _peers[iodev] = new IODevicePeer(iodev, iodev->property("UseCompression").toBool()); - if(_peers.count() == 1) - emit connected(); + if (_peers.count() == 1) + emit connected(); - updateSecureState(); - return true; + updateSecureState(); + return true; } -void SignalProxy::setHeartBeatInterval(int secs) { - if(secs != _heartBeatInterval) { - _heartBeatInterval = secs; - _heartBeatTimer.setInterval(secs * 1000); - } + +void SignalProxy::setHeartBeatInterval(int secs) +{ + if (secs != _heartBeatInterval) { + _heartBeatInterval = secs; + _heartBeatTimer.setInterval(secs * 1000); + } } -void SignalProxy::setMaxHeartBeatCount(int max) { - _maxHeartBeatCount = max; + +void SignalProxy::setMaxHeartBeatCount(int max) +{ + _maxHeartBeatCount = max; } -bool SignalProxy::addPeer(SignalProxy* proxy) { - if(!proxy) - return false; - if(proxyMode() == proxy->proxyMode()) { - qWarning() << "SignalProxy::addPeer(): adding a SignalProxy as peer requires one proxy to be server and one client!"; - return false; - } +bool SignalProxy::addPeer(SignalProxy *proxy) +{ + if (!proxy) + return false; - if(_peers.contains(proxy)) { - return true; - } + if (proxyMode() == proxy->proxyMode()) { + qWarning() << "SignalProxy::addPeer(): adding a SignalProxy as peer requires one proxy to be server and one client!"; + return false; + } - if(proxyMode() == Client && !_peers.isEmpty()) { - qWarning("SignalProxy: only one peer allowed in client mode!"); - return false; - } + if (_peers.contains(proxy)) { + return true; + } + + if (proxyMode() == Client && !_peers.isEmpty()) { + qWarning("SignalProxy: only one peer allowed in client mode!"); + return false; + } - _peers[proxy] = new SignalProxyPeer(this, proxy); - proxy->addPeer(this); + _peers[proxy] = new SignalProxyPeer(this, proxy); + proxy->addPeer(this); - if(_peers.count() == 1) - emit connected(); + if (_peers.count() == 1) + emit connected(); - updateSecureState(); - return true; + updateSecureState(); + return true; } -void SignalProxy::removeAllPeers() { - Q_ASSERT(proxyMode() == Server || _peers.count() <= 1); - // wee need to copy that list since we modify it in the loop - QList peers = _peers.keys(); - foreach(QObject *peer, peers) { - removePeer(peer); - } + +void SignalProxy::removeAllPeers() +{ + Q_ASSERT(proxyMode() == Server || _peers.count() <= 1); + // wee need to copy that list since we modify it in the loop + QList peers = _peers.keys(); + foreach(QObject *peer, peers) { + removePeer(peer); + } } -void SignalProxy::removePeer(QObject* dev) { - if(_peers.isEmpty()) { - qWarning() << "SignalProxy::removePeer(): No peers in use!"; - return; - } - Q_ASSERT(dev); - if(!_peers.contains(dev)) { - qWarning() << "SignalProxy: unknown Peer" << dev; - return; - } +void SignalProxy::removePeer(QObject *dev) +{ + if (_peers.isEmpty()) { + qWarning() << "SignalProxy::removePeer(): No peers in use!"; + return; + } - AbstractPeer *peer = _peers[dev]; - _peers.remove(dev); + Q_ASSERT(dev); + if (!_peers.contains(dev)) { + qWarning() << "SignalProxy: unknown Peer" << dev; + return; + } - disconnect(dev, 0, this, 0); - if(peer->type() == AbstractPeer::IODevicePeer) - emit peerRemoved(static_cast(dev)); + AbstractPeer *peer = _peers[dev]; + _peers.remove(dev); - if(peer->type() == AbstractPeer::SignalProxyPeer) { - SignalProxy *proxy = static_cast(dev); - if(proxy->_peers.contains(this)) - proxy->removePeer(this); - } + disconnect(dev, 0, this, 0); + if (peer->type() == AbstractPeer::IODevicePeer) + emit peerRemoved(static_cast(dev)); + + if (peer->type() == AbstractPeer::SignalProxyPeer) { + SignalProxy *proxy = static_cast(dev); + if (proxy->_peers.contains(this)) + proxy->removePeer(this); + } - if(dev->parent() == this) - dev->deleteLater(); + if (dev->parent() == this) + dev->deleteLater(); - delete peer; + delete peer; - updateSecureState(); + updateSecureState(); - if(_peers.isEmpty()) - emit disconnected(); + if (_peers.isEmpty()) + emit disconnected(); } -void SignalProxy::removePeerBySender() { - removePeer(sender()); + +void SignalProxy::removePeerBySender() +{ + removePeer(sender()); } -void SignalProxy::renameObject(const SyncableObject *obj, const QString &newname, const QString &oldname) { - if(proxyMode() == Client) - return; - const QMetaObject *meta = obj->syncMetaObject(); - const QByteArray className(meta->className()); - objectRenamed(className, newname, oldname); +void SignalProxy::renameObject(const SyncableObject *obj, const QString &newname, const QString &oldname) +{ + if (proxyMode() == Client) + return; + + const QMetaObject *meta = obj->syncMetaObject(); + const QByteArray className(meta->className()); + objectRenamed(className, newname, oldname); - QVariantList params; - params << "__objectRenamed__" << className << newname << oldname; - dispatchSignal(RpcCall, params); + QVariantList params; + params << "__objectRenamed__" << className << newname << oldname; + dispatchSignal(RpcCall, params); } -void SignalProxy::objectRenamed(const QByteArray &classname, const QString &newname, const QString &oldname) { - if(_syncSlave.contains(classname) && _syncSlave[classname].contains(oldname) && oldname != newname) { - SyncableObject *obj = _syncSlave[classname][newname] = _syncSlave[classname].take(oldname); - requestInit(obj); - } + +void SignalProxy::objectRenamed(const QByteArray &classname, const QString &newname, const QString &oldname) +{ + if (_syncSlave.contains(classname) && _syncSlave[classname].contains(oldname) && oldname != newname) { + SyncableObject *obj = _syncSlave[classname][newname] = _syncSlave[classname].take(oldname); + requestInit(obj); + } } -const QMetaObject *SignalProxy::metaObject(const QObject *obj) { - if(const SyncableObject *syncObject = qobject_cast(obj)) - return syncObject->syncMetaObject(); - else - return obj->metaObject(); + +const QMetaObject *SignalProxy::metaObject(const QObject *obj) +{ + if (const SyncableObject *syncObject = qobject_cast(obj)) + return syncObject->syncMetaObject(); + else + return obj->metaObject(); } -SignalProxy::ExtendedMetaObject *SignalProxy::extendedMetaObject(const QMetaObject *meta) const { - if(_extendedMetaObjects.contains(meta)) - return _extendedMetaObjects[meta]; - else - return 0; + +SignalProxy::ExtendedMetaObject *SignalProxy::extendedMetaObject(const QMetaObject *meta) const +{ + if (_extendedMetaObjects.contains(meta)) + return _extendedMetaObjects[meta]; + else + return 0; } -SignalProxy::ExtendedMetaObject *SignalProxy::createExtendedMetaObject(const QMetaObject *meta, bool checkConflicts) { - if(!_extendedMetaObjects.contains(meta)) { - _extendedMetaObjects[meta] = new ExtendedMetaObject(meta, checkConflicts); - } - return _extendedMetaObjects[meta]; + +SignalProxy::ExtendedMetaObject *SignalProxy::createExtendedMetaObject(const QMetaObject *meta, bool checkConflicts) +{ + if (!_extendedMetaObjects.contains(meta)) { + _extendedMetaObjects[meta] = new ExtendedMetaObject(meta, checkConflicts); + } + return _extendedMetaObjects[meta]; } -bool SignalProxy::attachSignal(QObject *sender, const char* signal, const QByteArray& sigName) { - const QMetaObject* meta = sender->metaObject(); - QByteArray sig(meta->normalizedSignature(signal).mid(1)); - int methodId = meta->indexOfMethod(sig.constData()); - if(methodId == -1 || meta->method(methodId).methodType() != QMetaMethod::Signal) { - qWarning() << "SignalProxy::attachSignal(): No such signal" << signal; - return false; - } - createExtendedMetaObject(meta); - _signalRelay->attachSignal(sender, methodId, sigName); +bool SignalProxy::attachSignal(QObject *sender, const char *signal, const QByteArray &sigName) +{ + const QMetaObject *meta = sender->metaObject(); + QByteArray sig(meta->normalizedSignature(signal).mid(1)); + int methodId = meta->indexOfMethod(sig.constData()); + if (methodId == -1 || meta->method(methodId).methodType() != QMetaMethod::Signal) { + qWarning() << "SignalProxy::attachSignal(): No such signal" << signal; + return false; + } - disconnect(sender, SIGNAL(destroyed(QObject *)), this, SLOT(detachObject(QObject *))); - connect(sender, SIGNAL(destroyed(QObject *)), this, SLOT(detachObject(QObject *))); - return true; + createExtendedMetaObject(meta); + _signalRelay->attachSignal(sender, methodId, sigName); + + disconnect(sender, SIGNAL(destroyed(QObject *)), this, SLOT(detachObject(QObject *))); + connect(sender, SIGNAL(destroyed(QObject *)), this, SLOT(detachObject(QObject *))); + return true; } -bool SignalProxy::attachSlot(const QByteArray& sigName, QObject* recv, const char* slot) { - const QMetaObject* meta = recv->metaObject(); - int methodId = meta->indexOfMethod(meta->normalizedSignature(slot).mid(1)); - if(methodId == -1 || meta->method(methodId).methodType() == QMetaMethod::Method) { - qWarning() << "SignalProxy::attachSlot(): No such slot" << slot; - return false; - } - createExtendedMetaObject(meta); +bool SignalProxy::attachSlot(const QByteArray &sigName, QObject *recv, const char *slot) +{ + const QMetaObject *meta = recv->metaObject(); + int methodId = meta->indexOfMethod(meta->normalizedSignature(slot).mid(1)); + if (methodId == -1 || meta->method(methodId).methodType() == QMetaMethod::Method) { + qWarning() << "SignalProxy::attachSlot(): No such slot" << slot; + return false; + } + + createExtendedMetaObject(meta); - QByteArray funcName = QMetaObject::normalizedSignature(sigName.constData()); - _attachedSlots.insert(funcName, qMakePair(recv, methodId)); + QByteArray funcName = QMetaObject::normalizedSignature(sigName.constData()); + _attachedSlots.insert(funcName, qMakePair(recv, methodId)); - disconnect(recv, SIGNAL(destroyed(QObject *)), this, SLOT(detachObject(QObject *))); - connect(recv, SIGNAL(destroyed(QObject *)), this, SLOT(detachObject(QObject *))); - return true; + disconnect(recv, SIGNAL(destroyed(QObject *)), this, SLOT(detachObject(QObject *))); + connect(recv, SIGNAL(destroyed(QObject *)), this, SLOT(detachObject(QObject *))); + return true; } -void SignalProxy::synchronize(SyncableObject *obj) { - createExtendedMetaObject(obj, true); - // attaching as slave to receive sync Calls - QByteArray className(obj->syncMetaObject()->className()); - _syncSlave[className][obj->objectName()] = obj; +void SignalProxy::synchronize(SyncableObject *obj) +{ + createExtendedMetaObject(obj, true); - if(proxyMode() == Server) { - obj->setInitialized(); - emit objectInitialized(obj); - } else { - if(obj->isInitialized()) - emit objectInitialized(obj); - else - requestInit(obj); - } + // attaching as slave to receive sync Calls + QByteArray className(obj->syncMetaObject()->className()); + _syncSlave[className][obj->objectName()] = obj; - obj->synchronize(this); + if (proxyMode() == Server) { + obj->setInitialized(); + emit objectInitialized(obj); + } + else { + if (obj->isInitialized()) + emit objectInitialized(obj); + else + requestInit(obj); + } + + obj->synchronize(this); } -void SignalProxy::detachObject(QObject *obj) { - detachSignals(obj); - detachSlots(obj); + +void SignalProxy::detachObject(QObject *obj) +{ + detachSignals(obj); + detachSlots(obj); } -void SignalProxy::detachSignals(QObject *sender) { - _signalRelay->detachSignal(sender); + +void SignalProxy::detachSignals(QObject *sender) +{ + _signalRelay->detachSignal(sender); } -void SignalProxy::detachSlots(QObject* receiver) { - SlotHash::iterator slotIter = _attachedSlots.begin(); - while(slotIter != _attachedSlots.end()) { - if(slotIter.value().first == receiver) { - slotIter = _attachedSlots.erase(slotIter); - } else - slotIter++; - } + +void SignalProxy::detachSlots(QObject *receiver) +{ + SlotHash::iterator slotIter = _attachedSlots.begin(); + while (slotIter != _attachedSlots.end()) { + if (slotIter.value().first == receiver) { + slotIter = _attachedSlots.erase(slotIter); + } + else + slotIter++; + } } -void SignalProxy::stopSynchronize(SyncableObject *obj) { - // we can't use a className here, since it might be effed up, if we receive the call as a result of a decon - // gladly the objectName() is still valid. So we have only to iterate over the classes not each instance! *sigh* - QHash::iterator classIter = _syncSlave.begin(); - while(classIter != _syncSlave.end()) { - if(classIter->contains(obj->objectName()) && classIter.value()[obj->objectName()] == obj) { - classIter->remove(obj->objectName()); - break; + +void SignalProxy::stopSynchronize(SyncableObject *obj) +{ + // we can't use a className here, since it might be effed up, if we receive the call as a result of a decon + // gladly the objectName() is still valid. So we have only to iterate over the classes not each instance! *sigh* + QHash::iterator classIter = _syncSlave.begin(); + while (classIter != _syncSlave.end()) { + if (classIter->contains(obj->objectName()) && classIter.value()[obj->objectName()] == obj) { + classIter->remove(obj->objectName()); + break; + } + classIter++; } - classIter++; - } - obj->stopSynchronize(this); + obj->stopSynchronize(this); } -void SignalProxy::dispatchSignal(const RequestType &requestType, const QVariantList ¶ms) { - QVariant packedFunc(QVariantList() << (qint16)requestType << params); - PeerHash::iterator peer = _peers.begin(); - while(peer != _peers.end()) { - switch((*peer)->type()) { - case AbstractPeer::IODevicePeer: - { - IODevicePeer *ioPeer = static_cast(*peer); - if(ioPeer->isOpen()) - ioPeer->dispatchPackedFunc(packedFunc); - else - QCoreApplication::postEvent(this, new RemovePeerEvent(peer.key())); - } - break; - case AbstractPeer::SignalProxyPeer: - (*peer)->dispatchSignal(requestType, params); - break; - default: - Q_ASSERT(false); // there shouldn't be any peers with wrong / unknown type + +void SignalProxy::dispatchSignal(const RequestType &requestType, const QVariantList ¶ms) +{ + QVariant packedFunc(QVariantList() << (qint16)requestType << params); + PeerHash::iterator peer = _peers.begin(); + while (peer != _peers.end()) { + switch ((*peer)->type()) { + case AbstractPeer::IODevicePeer: + { + IODevicePeer *ioPeer = static_cast(*peer); + if (ioPeer->isOpen()) + ioPeer->dispatchPackedFunc(packedFunc); + else + QCoreApplication::postEvent(this, new RemovePeerEvent(peer.key())); + } + break; + case AbstractPeer::SignalProxyPeer: + (*peer)->dispatchSignal(requestType, params); + break; + default: + Q_ASSERT(false); // there shouldn't be any peers with wrong / unknown type + } + peer++; } - peer++; - } } -void SignalProxy::receivePackedFunc(AbstractPeer *sender, const QVariant &packedFunc) { - QVariantList params(packedFunc.toList()); - if(params.isEmpty()) { - qWarning() << "SignalProxy::receivePeerSignal(): received incompatible Data:" << packedFunc; - return; - } +void SignalProxy::receivePackedFunc(AbstractPeer *sender, const QVariant &packedFunc) +{ + QVariantList params(packedFunc.toList()); + + if (params.isEmpty()) { + qWarning() << "SignalProxy::receivePeerSignal(): received incompatible Data:" << packedFunc; + return; + } - RequestType requestType = (RequestType)params.takeFirst().value(); - receivePeerSignal(sender, requestType, params); + RequestType requestType = (RequestType)params.takeFirst().value(); + receivePeerSignal(sender, requestType, params); } -void SignalProxy::receivePeerSignal(AbstractPeer *sender, const RequestType &requestType, const QVariantList ¶ms) { - switch(requestType) { + +void SignalProxy::receivePeerSignal(AbstractPeer *sender, const RequestType &requestType, const QVariantList ¶ms) +{ + switch (requestType) { // list all RequestTypes that shouldnot trigger a heartbeat counter reset here - case HeartBeatReply: - break; - default: - if(sender->type() == AbstractPeer::IODevicePeer) { - IODevicePeer *ioPeer = static_cast(sender); - ioPeer->sentHeartBeats = 0; - } - } - - // qDebug() << "SignalProxy::receivePeerSignal)" << requestType << params; - switch(requestType) { - case RpcCall: - if(params.empty()) - qWarning() << "SignalProxy::receivePeerSignal(): received empty RPC-Call"; - else - handleSignal(params); - //handleSignal(params.takeFirst().toByteArray(), params); - break; + case HeartBeatReply: + break; + default: + if (sender->type() == AbstractPeer::IODevicePeer) { + IODevicePeer *ioPeer = static_cast(sender); + ioPeer->sentHeartBeats = 0; + } + } + + // qDebug() << "SignalProxy::receivePeerSignal)" << requestType << params; + switch (requestType) { + case RpcCall: + if (params.empty()) + qWarning() << "SignalProxy::receivePeerSignal(): received empty RPC-Call"; + else + handleSignal(params); + //handleSignal(params.takeFirst().toByteArray(), params); + break; - case Sync: - handleSync(sender, params); - break; + case Sync: + handleSync(sender, params); + break; - case InitRequest: - handleInitRequest(sender, params); - break; + case InitRequest: + handleInitRequest(sender, params); + break; - case InitData: - handleInitData(sender, params); - break; + case InitData: + handleInitData(sender, params); + break; - case HeartBeat: - receiveHeartBeat(sender, params); - break; + case HeartBeat: + receiveHeartBeat(sender, params); + break; - case HeartBeatReply: - receiveHeartBeatReply(sender, params); - break; + case HeartBeatReply: + receiveHeartBeatReply(sender, params); + break; - default: - qWarning() << "SignalProxy::receivePeerSignal(): received undefined CallType" << requestType << params; - } + default: + qWarning() << "SignalProxy::receivePeerSignal(): received undefined CallType" << requestType << params; + } } -void SignalProxy::receivePeerSignal(SignalProxy *sender, const RequestType &requestType, const QVariantList ¶ms) { - if(!_peers.contains(sender)) { - // we output only the pointer value. otherwise Qt would try to pretty print. As the object might already been destroyed, this is not a good idea. - qWarning() << "SignalProxy::receivePeerSignal(): received Signal from unknown Proxy" << reinterpret_cast(sender); - return; - } - receivePeerSignal(_peers[sender], requestType, params); + +void SignalProxy::receivePeerSignal(SignalProxy *sender, const RequestType &requestType, const QVariantList ¶ms) +{ + if (!_peers.contains(sender)) { + // we output only the pointer value. otherwise Qt would try to pretty print. As the object might already been destroyed, this is not a good idea. + qWarning() << "SignalProxy::receivePeerSignal(): received Signal from unknown Proxy" << reinterpret_cast(sender); + return; + } + receivePeerSignal(_peers[sender], requestType, params); } -void SignalProxy::handleSync(AbstractPeer *sender, QVariantList params) { - if(params.count() < 3) { - qWarning() << "received invalid Sync call" << params; - return; - } - QByteArray className = params.takeFirst().toByteArray(); - QString objectName = params.takeFirst().toString(); - QByteArray slot = params.takeFirst().toByteArray(); +void SignalProxy::handleSync(AbstractPeer *sender, QVariantList params) +{ + if (params.count() < 3) { + qWarning() << "received invalid Sync call" << params; + return; + } - if(!_syncSlave.contains(className) || !_syncSlave[className].contains(objectName)) { - qWarning() << QString("no registered receiver for sync call: %1::%2 (objectName=\"%3\"). Params are:").arg(QString(className)).arg(QString(slot)).arg(objectName) - << params; - return; - } + QByteArray className = params.takeFirst().toByteArray(); + QString objectName = params.takeFirst().toString(); + QByteArray slot = params.takeFirst().toByteArray(); - SyncableObject *receiver = _syncSlave[className][objectName]; - ExtendedMetaObject *eMeta = extendedMetaObject(receiver); - if(!eMeta->slotMap().contains(slot)) { - qWarning() << QString("no matching slot for sync call: %1::%2 (objectName=\"%3\"). Params are:").arg(QString(className)).arg(QString(slot)).arg(objectName) - << params; - return; - } - - int slotId = eMeta->slotMap()[slot]; - if(proxyMode() != eMeta->receiverMode(slotId)) { - qWarning("SignalProxy::handleSync(): invokeMethod for \"%s\" failed. Wrong ProxyMode!", eMeta->methodName(slotId).constData()); - return; - } - - QVariant returnValue((QVariant::Type)eMeta->returnType(slotId)); - if(!invokeSlot(receiver, slotId, params, returnValue)) { - qWarning("SignalProxy::handleSync(): invokeMethod for \"%s\" failed ", eMeta->methodName(slotId).constData()); - return; - } - - - if(returnValue.type() != QVariant::Invalid && eMeta->receiveMap().contains(slotId)) { - int receiverId = eMeta->receiveMap()[slotId]; - QVariantList returnParams; - returnParams << className - << objectName - << eMeta->methodName(receiverId); - //QByteArray(receiver->metaObject()->method(receiverId).signature()); - if(eMeta->argTypes(receiverId).count() > 1) - returnParams << params; - returnParams << returnValue; - sender->dispatchSignal(Sync, returnParams); - } - - // send emit update signal - invokeSlot(receiver, eMeta->updatedRemotelyId()); -} - -void SignalProxy::handleInitRequest(AbstractPeer *sender, const QVariantList ¶ms) { - if(params.count() != 2) { - qWarning() << "SignalProxy::handleInitRequest() received initRequest with invalid param Count:" - << params; - return; - } + if (!_syncSlave.contains(className) || !_syncSlave[className].contains(objectName)) { + qWarning() << QString("no registered receiver for sync call: %1::%2 (objectName=\"%3\"). Params are:").arg(QString(className)).arg(QString(slot)).arg(objectName) + << params; + return; + } + + SyncableObject *receiver = _syncSlave[className][objectName]; + ExtendedMetaObject *eMeta = extendedMetaObject(receiver); + if (!eMeta->slotMap().contains(slot)) { + qWarning() << QString("no matching slot for sync call: %1::%2 (objectName=\"%3\"). Params are:").arg(QString(className)).arg(QString(slot)).arg(objectName) + << params; + return; + } + + int slotId = eMeta->slotMap()[slot]; + if (proxyMode() != eMeta->receiverMode(slotId)) { + qWarning("SignalProxy::handleSync(): invokeMethod for \"%s\" failed. Wrong ProxyMode!", eMeta->methodName(slotId).constData()); + return; + } - QByteArray className(params[0].toByteArray()); - QString objectName(params[1].toString()); + QVariant returnValue((QVariant::Type)eMeta->returnType(slotId)); + if (!invokeSlot(receiver, slotId, params, returnValue)) { + qWarning("SignalProxy::handleSync(): invokeMethod for \"%s\" failed ", eMeta->methodName(slotId).constData()); + return; + } + + if (returnValue.type() != QVariant::Invalid && eMeta->receiveMap().contains(slotId)) { + int receiverId = eMeta->receiveMap()[slotId]; + QVariantList returnParams; + returnParams << className + << objectName + << eMeta->methodName(receiverId); + //QByteArray(receiver->metaObject()->method(receiverId).signature()); + if (eMeta->argTypes(receiverId).count() > 1) + returnParams << params; + returnParams << returnValue; + sender->dispatchSignal(Sync, returnParams); + } + + // send emit update signal + invokeSlot(receiver, eMeta->updatedRemotelyId()); +} - if(!_syncSlave.contains(className)) { - qWarning() << "SignalProxy::handleInitRequest() received initRequest for unregistered Class:" - << className; - return; - } - if(!_syncSlave[className].contains(objectName)) { - qWarning() << "SignalProxy::handleInitRequest() received initRequest for unregistered Object:" - << className << objectName; - return; - } +void SignalProxy::handleInitRequest(AbstractPeer *sender, const QVariantList ¶ms) +{ + if (params.count() != 2) { + qWarning() << "SignalProxy::handleInitRequest() received initRequest with invalid param Count:" + << params; + return; + } + + QByteArray className(params[0].toByteArray()); + QString objectName(params[1].toString()); + + if (!_syncSlave.contains(className)) { + qWarning() << "SignalProxy::handleInitRequest() received initRequest for unregistered Class:" + << className; + return; + } + + if (!_syncSlave[className].contains(objectName)) { + qWarning() << "SignalProxy::handleInitRequest() received initRequest for unregistered Object:" + << className << objectName; + return; + } - SyncableObject *obj = _syncSlave[className][objectName]; + SyncableObject *obj = _syncSlave[className][objectName]; - QVariantList params_; - params_ << className - << objectName - << initData(obj); + QVariantList params_; + params_ << className + << objectName + << initData(obj); - sender->dispatchSignal(InitData, params_); + sender->dispatchSignal(InitData, params_); } -void SignalProxy::handleInitData(AbstractPeer *sender, const QVariantList ¶ms) { - Q_UNUSED(sender) - if(params.count() != 3) { - qWarning() << "SignalProxy::handleInitData() received initData with invalid param Count:" - << params; - return; - } - QByteArray className(params[0].toByteArray()); - QString objectName(params[1].toString()); - QVariantMap propertyMap(params[2].toMap()); +void SignalProxy::handleInitData(AbstractPeer *sender, const QVariantList ¶ms) +{ + Q_UNUSED(sender) + if (params.count() != 3) { + qWarning() << "SignalProxy::handleInitData() received initData with invalid param Count:" + << params; + return; + } - if(!_syncSlave.contains(className)) { - qWarning() << "SignalProxy::handleInitData() received initData for unregistered Class:" - << className; - return; - } + QByteArray className(params[0].toByteArray()); + QString objectName(params[1].toString()); + QVariantMap propertyMap(params[2].toMap()); - if(!_syncSlave[className].contains(objectName)) { - qWarning() << "SignalProxy::handleInitData() received initData for unregistered Object:" - << className << objectName; - return; - } + if (!_syncSlave.contains(className)) { + qWarning() << "SignalProxy::handleInitData() received initData for unregistered Class:" + << className; + return; + } - SyncableObject *obj = _syncSlave[className][objectName]; - setInitData(obj, propertyMap); + if (!_syncSlave[className].contains(objectName)) { + qWarning() << "SignalProxy::handleInitData() received initData for unregistered Object:" + << className << objectName; + return; + } + + SyncableObject *obj = _syncSlave[className][objectName]; + setInitData(obj, propertyMap); } + //void SignalProxy::handleSignal(const QByteArray &funcName, const QVariantList ¶ms) { -void SignalProxy::handleSignal(const QVariantList &data) { - QVariantList params = data; - QByteArray funcName = params.takeFirst().toByteArray(); - - QObject* receiver; - int methodId; - SlotHash::const_iterator slot = _attachedSlots.constFind(funcName); - while(slot != _attachedSlots.constEnd() && slot.key() == funcName) { - receiver = (*slot).first; - methodId = (*slot).second; - if(!invokeSlot(receiver, methodId, params)) { - ExtendedMetaObject *eMeta = extendedMetaObject(receiver); - qWarning("SignalProxy::handleSignal(): invokeMethod for \"%s\" failed ", eMeta->methodName(methodId).constData()); - } - slot++; - } -} - -bool SignalProxy::invokeSlot(QObject *receiver, int methodId, const QVariantList ¶ms, QVariant &returnValue) { - ExtendedMetaObject *eMeta = extendedMetaObject(receiver); - const QList args = eMeta->argTypes(methodId); - const int numArgs = params.count() < args.count() - ? params.count() - : args.count(); - - if(eMeta->minArgCount(methodId) > params.count()) { - qWarning() << "SignalProxy::invokeSlot(): not enough params to invoke" << eMeta->methodName(methodId); - return false; - } - - void *_a[] = {0, // return type... - 0, 0, 0, 0 , 0, // and 10 args - that's the max size qt can handle with signals and slots - 0, 0, 0, 0 , 0}; - - // check for argument compatibility and build params array - for(int i = 0; i < numArgs; i++) { - if(!params[i].isValid()) { - qWarning() << "SignalProxy::invokeSlot(): received invalid data for argument number" << i << "of method" << QString("%1::%2()").arg(receiver->metaObject()->className()).arg(receiver->metaObject()->method(methodId).signature()); - qWarning() << " - make sure all your data types are known by the Qt MetaSystem"; - return false; - } - if(args[i] != QMetaType::type(params[i].typeName())) { - qWarning() << "SignalProxy::invokeSlot(): incompatible param types to invoke" << eMeta->methodName(methodId); - return false; - } - _a[i+1] = const_cast(params[i].constData()); - } - - if(returnValue.type() != QVariant::Invalid) - _a[0] = const_cast(returnValue.constData()); - - Qt::ConnectionType type = QThread::currentThread() == receiver->thread() - ? Qt::DirectConnection - : Qt::QueuedConnection; - - if(type == Qt::DirectConnection) { - return receiver->qt_metacall(QMetaObject::InvokeMetaMethod, methodId, _a) < 0; - } else { - qWarning() << "Queued Connections are not implemented yet"; - // note to self: qmetaobject.cpp:990 ff - return false; - } +void SignalProxy::handleSignal(const QVariantList &data) +{ + QVariantList params = data; + QByteArray funcName = params.takeFirst().toByteArray(); + + QObject *receiver; + int methodId; + SlotHash::const_iterator slot = _attachedSlots.constFind(funcName); + while (slot != _attachedSlots.constEnd() && slot.key() == funcName) { + receiver = (*slot).first; + methodId = (*slot).second; + if (!invokeSlot(receiver, methodId, params)) { + ExtendedMetaObject *eMeta = extendedMetaObject(receiver); + qWarning("SignalProxy::handleSignal(): invokeMethod for \"%s\" failed ", eMeta->methodName(methodId).constData()); + } + slot++; + } +} + + +bool SignalProxy::invokeSlot(QObject *receiver, int methodId, const QVariantList ¶ms, QVariant &returnValue) +{ + ExtendedMetaObject *eMeta = extendedMetaObject(receiver); + const QList args = eMeta->argTypes(methodId); + const int numArgs = params.count() < args.count() + ? params.count() + : args.count(); + + if (eMeta->minArgCount(methodId) > params.count()) { + qWarning() << "SignalProxy::invokeSlot(): not enough params to invoke" << eMeta->methodName(methodId); + return false; + } + + void *_a[] = { 0, // return type... + 0, 0, 0, 0, 0, // and 10 args - that's the max size qt can handle with signals and slots + 0, 0, 0, 0, 0 }; + // check for argument compatibility and build params array + for (int i = 0; i < numArgs; i++) { + if (!params[i].isValid()) { + qWarning() << "SignalProxy::invokeSlot(): received invalid data for argument number" << i << "of method" << QString("%1::%2()").arg(receiver->metaObject()->className()).arg(receiver->metaObject()->method(methodId).signature()); + qWarning() << " - make sure all your data types are known by the Qt MetaSystem"; + return false; + } + if (args[i] != QMetaType::type(params[i].typeName())) { + qWarning() << "SignalProxy::invokeSlot(): incompatible param types to invoke" << eMeta->methodName(methodId); + return false; + } + _a[i+1] = const_cast(params[i].constData()); + } + + if (returnValue.type() != QVariant::Invalid) + _a[0] = const_cast(returnValue.constData()); + + Qt::ConnectionType type = QThread::currentThread() == receiver->thread() + ? Qt::DirectConnection + : Qt::QueuedConnection; + + if (type == Qt::DirectConnection) { + return receiver->qt_metacall(QMetaObject::InvokeMetaMethod, methodId, _a) < 0; + } + else { + qWarning() << "Queued Connections are not implemented yet"; + // note to self: qmetaobject.cpp:990 ff + return false; + } } -bool SignalProxy::invokeSlot(QObject *receiver, int methodId, const QVariantList ¶ms) { - QVariant ret; - return invokeSlot(receiver, methodId, params, ret); + +bool SignalProxy::invokeSlot(QObject *receiver, int methodId, const QVariantList ¶ms) +{ + QVariant ret; + return invokeSlot(receiver, methodId, params, ret); } -void SignalProxy::dataAvailable() { - // yet again. it's a private slot. no need for checks. - QIODevice* ioDev = qobject_cast(sender()); - Q_ASSERT(_peers.contains(ioDev) && _peers[ioDev]->type() == AbstractPeer::IODevicePeer); - IODevicePeer *peer = static_cast(_peers[ioDev]); - QVariant var; - while(peer->readData(var)) - receivePackedFunc(peer, var); + +void SignalProxy::dataAvailable() +{ + // yet again. it's a private slot. no need for checks. + QIODevice *ioDev = qobject_cast(sender()); + Q_ASSERT(_peers.contains(ioDev) && _peers[ioDev]->type() == AbstractPeer::IODevicePeer); + IODevicePeer *peer = static_cast(_peers[ioDev]); + QVariant var; + while (peer->readData(var)) + receivePackedFunc(peer, var); } -void SignalProxy::writeDataToDevice(QIODevice *dev, const QVariant &item, bool compressed) { - QAbstractSocket* sock = qobject_cast(dev); - if(!dev->isOpen() || (sock && sock->state()!=QAbstractSocket::ConnectedState)) { - qWarning("SignalProxy: Can't call write on a closed device"); - return; - } - QByteArray block; - QDataStream out(&block, QIODevice::WriteOnly); - out.setVersion(QDataStream::Qt_4_2); - out << (quint32)0; +void SignalProxy::writeDataToDevice(QIODevice *dev, const QVariant &item, bool compressed) +{ + QAbstractSocket *sock = qobject_cast(dev); + if (!dev->isOpen() || (sock && sock->state() != QAbstractSocket::ConnectedState)) { + qWarning("SignalProxy: Can't call write on a closed device"); + return; + } + + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_2); + out << (quint32)0; - if(compressed) { - QByteArray rawItem; - QDataStream itemStream(&rawItem, QIODevice::WriteOnly); + if (compressed) { + QByteArray rawItem; + QDataStream itemStream(&rawItem, QIODevice::WriteOnly); - itemStream.setVersion(QDataStream::Qt_4_2); - itemStream << item; + itemStream.setVersion(QDataStream::Qt_4_2); + itemStream << item; - rawItem = qCompress(rawItem); + rawItem = qCompress(rawItem); - out << rawItem; - } else { - out << item; - } + out << rawItem; + } + else { + out << item; + } - out.device()->seek(0); - out << (quint32)(block.size() - sizeof(quint32)); + out.device()->seek(0); + out << (quint32)(block.size() - sizeof(quint32)); - dev->write(block); + dev->write(block); } -bool SignalProxy::readDataFromDevice(QIODevice *dev, quint32 &blockSize, QVariant &item, bool compressed) { - if(!dev) - return false; - QDataStream in(dev); - in.setVersion(QDataStream::Qt_4_2); +bool SignalProxy::readDataFromDevice(QIODevice *dev, quint32 &blockSize, QVariant &item, bool compressed) +{ + if (!dev) + return false; - if(blockSize == 0) { - if(dev->bytesAvailable() < (int)sizeof(quint32)) return false; - in >> blockSize; - } + QDataStream in(dev); + in.setVersion(QDataStream::Qt_4_2); - if(blockSize > 1 << 22) { - disconnectDevice(dev, tr("Peer tried to send package larger than max package size!")); - return false; - } + if (blockSize == 0) { + if (dev->bytesAvailable() < (int)sizeof(quint32)) return false; + in >> blockSize; + } - if(blockSize == 0) { - disconnectDevice(dev, tr("Peer tried to send 0 byte package!")); - return false; - } + if (blockSize > 1 << 22) { + disconnectDevice(dev, tr("Peer tried to send package larger than max package size!")); + return false; + } - if(dev->bytesAvailable() < blockSize) - return false; + if (blockSize == 0) { + disconnectDevice(dev, tr("Peer tried to send 0 byte package!")); + return false; + } - blockSize = 0; + if (dev->bytesAvailable() < blockSize) + return false; - if(compressed) { - QByteArray rawItem; - in >> rawItem; + blockSize = 0; - int nbytes = rawItem.size(); - if(nbytes <= 4) { - const char *data = rawItem.constData(); - if(nbytes < 4 || (data[0]!=0 || data[1]!=0 || data[2]!=0 || data[3]!=0)) { - disconnectDevice(dev, tr("Peer sent corrupted compressed data!")); + if (compressed) { + QByteArray rawItem; + in >> rawItem; + + int nbytes = rawItem.size(); + if (nbytes <= 4) { + const char *data = rawItem.constData(); + if (nbytes < 4 || (data[0] != 0 || data[1] != 0 || data[2] != 0 || data[3] != 0)) { + disconnectDevice(dev, tr("Peer sent corrupted compressed data!")); + return false; + } + } + + rawItem = qUncompress(rawItem); + + QDataStream itemStream(&rawItem, QIODevice::ReadOnly); + itemStream.setVersion(QDataStream::Qt_4_2); + itemStream >> item; + } + else { + in >> item; + } + + if (!item.isValid()) { + disconnectDevice(dev, tr("Peer sent corrupt data: unable to load QVariant!")); return false; - } } - rawItem = qUncompress(rawItem); + return true; +} - QDataStream itemStream(&rawItem, QIODevice::ReadOnly); - itemStream.setVersion(QDataStream::Qt_4_2); - itemStream >> item; - } else { - in >> item; - } - if(!item.isValid()) { - disconnectDevice(dev, tr("Peer sent corrupt data: unable to load QVariant!")); - return false; - } +void SignalProxy::requestInit(SyncableObject *obj) +{ + if (proxyMode() == Server || obj->isInitialized()) + return; - return true; + QVariantList params; + params << obj->syncMetaObject()->className() + << obj->objectName(); + dispatchSignal(InitRequest, params); } -void SignalProxy::requestInit(SyncableObject *obj) { - if(proxyMode() == Server || obj->isInitialized()) - return; - QVariantList params; - params << obj->syncMetaObject()->className() - << obj->objectName(); - dispatchSignal(InitRequest, params); +QVariantMap SignalProxy::initData(SyncableObject *obj) const +{ + return obj->toVariantMap(); } -QVariantMap SignalProxy::initData(SyncableObject *obj) const { - return obj->toVariantMap(); -} -void SignalProxy::setInitData(SyncableObject *obj, const QVariantMap &properties) { - if(obj->isInitialized()) - return; - obj->fromVariantMap(properties); - obj->setInitialized(); - emit objectInitialized(obj); - invokeSlot(obj, extendedMetaObject(obj)->updatedRemotelyId()); +void SignalProxy::setInitData(SyncableObject *obj, const QVariantMap &properties) +{ + if (obj->isInitialized()) + return; + obj->fromVariantMap(properties); + obj->setInitialized(); + emit objectInitialized(obj); + invokeSlot(obj, extendedMetaObject(obj)->updatedRemotelyId()); } -void SignalProxy::sendHeartBeat() { - QVariantList heartBeatParams; - heartBeatParams << QTime::currentTime(); - QList toClose; - PeerHash::iterator peer = _peers.begin(); - while(peer != _peers.end()) { - if((*peer)->type() == AbstractPeer::IODevicePeer) { - IODevicePeer *ioPeer = static_cast(*peer); - ioPeer->dispatchSignal(SignalProxy::HeartBeat, heartBeatParams); - if(ioPeer->sentHeartBeats > 0) { - updateLag(ioPeer, ioPeer->sentHeartBeats * _heartBeatTimer.interval()); - } - if(maxHeartBeatCount() >= 0 && ioPeer->sentHeartBeats >= maxHeartBeatCount()) - toClose.append(ioPeer); - else - ioPeer->sentHeartBeats++; +void SignalProxy::sendHeartBeat() +{ + QVariantList heartBeatParams; + heartBeatParams << QTime::currentTime(); + QList toClose; + + PeerHash::iterator peer = _peers.begin(); + while (peer != _peers.end()) { + if ((*peer)->type() == AbstractPeer::IODevicePeer) { + IODevicePeer *ioPeer = static_cast(*peer); + ioPeer->dispatchSignal(SignalProxy::HeartBeat, heartBeatParams); + if (ioPeer->sentHeartBeats > 0) { + updateLag(ioPeer, ioPeer->sentHeartBeats * _heartBeatTimer.interval()); + } + if (maxHeartBeatCount() >= 0 && ioPeer->sentHeartBeats >= maxHeartBeatCount()) + toClose.append(ioPeer); + else + ioPeer->sentHeartBeats++; + } + ++peer; } - ++peer; - } - foreach(IODevicePeer *ioPeer, toClose) { - qWarning() << "SignalProxy: Disconnecting peer:" << ioPeer->address() - << "(didn't receive a heartbeat for over" << ioPeer->sentHeartBeats * _heartBeatTimer.interval() / 1000 << "seconds)"; - ioPeer->close(); - } + foreach(IODevicePeer *ioPeer, toClose) { + qWarning() << "SignalProxy: Disconnecting peer:" << ioPeer->address() + << "(didn't receive a heartbeat for over" << ioPeer->sentHeartBeats *_heartBeatTimer.interval() / 1000 << "seconds)"; + ioPeer->close(); + } } -void SignalProxy::receiveHeartBeat(AbstractPeer *peer, const QVariantList ¶ms) { - peer->dispatchSignal(SignalProxy::HeartBeatReply, params); + +void SignalProxy::receiveHeartBeat(AbstractPeer *peer, const QVariantList ¶ms) +{ + peer->dispatchSignal(SignalProxy::HeartBeatReply, params); } -void SignalProxy::receiveHeartBeatReply(AbstractPeer *peer, const QVariantList ¶ms) { - if(peer->type() != AbstractPeer::IODevicePeer) { - qWarning() << "SignalProxy::receiveHeartBeatReply: received heart beat from a non IODevicePeer!"; - return; - } - IODevicePeer *ioPeer = static_cast(peer); - ioPeer->sentHeartBeats = 0; +void SignalProxy::receiveHeartBeatReply(AbstractPeer *peer, const QVariantList ¶ms) +{ + if (peer->type() != AbstractPeer::IODevicePeer) { + qWarning() << "SignalProxy::receiveHeartBeatReply: received heart beat from a non IODevicePeer!"; + return; + } + + IODevicePeer *ioPeer = static_cast(peer); + ioPeer->sentHeartBeats = 0; - if(params.isEmpty()) { - qWarning() << "SignalProxy: received heart beat reply with less params then sent from:" << ioPeer->address(); - return; - } + if (params.isEmpty()) { + qWarning() << "SignalProxy: received heart beat reply with less params then sent from:" << ioPeer->address(); + return; + } - QTime sendTime = params[0].value(); - updateLag(ioPeer, sendTime.msecsTo(QTime::currentTime()) / 2); + QTime sendTime = params[0].value(); + updateLag(ioPeer, sendTime.msecsTo(QTime::currentTime()) / 2); } -void SignalProxy::customEvent(QEvent *event) { - switch(+event->type()) { - case PeerSignal: + +void SignalProxy::customEvent(QEvent *event) +{ + switch (+event->type()) { + case PeerSignal: { - PeerSignalEvent *e = static_cast(event); - receivePeerSignal(e->sender, e->requestType, e->params); + PeerSignalEvent *e = static_cast(event); + receivePeerSignal(e->sender, e->requestType, e->params); } - event->accept(); - break; - case RemovePeer: + event->accept(); + break; + case RemovePeer: { - RemovePeerEvent *e = static_cast(event); - removePeer(e->peer); + RemovePeerEvent *e = static_cast(event); + removePeer(e->peer); + } + event->accept(); + default: + return; } - event->accept(); - default: - return; - } } -void SignalProxy::sync_call__(const SyncableObject *obj, SignalProxy::ProxyMode modeType, const char *funcname, va_list ap) { - // qDebug() << obj << modeType << "(" << _proxyMode << ")" << funcname; - if(modeType != _proxyMode) - return; - ExtendedMetaObject *eMeta = extendedMetaObject(obj); +void SignalProxy::sync_call__(const SyncableObject *obj, SignalProxy::ProxyMode modeType, const char *funcname, va_list ap) +{ + // qDebug() << obj << modeType << "(" << _proxyMode << ")" << funcname; + if (modeType != _proxyMode) + return; + + ExtendedMetaObject *eMeta = extendedMetaObject(obj); - QVariantList params; - params << eMeta->metaObject()->className() - << obj->objectName() - << QByteArray(funcname); + QVariantList params; + params << eMeta->metaObject()->className() + << obj->objectName() + << QByteArray(funcname); - const QList &argTypes = eMeta->argTypes(eMeta->methodId(QByteArray(funcname))); + const QList &argTypes = eMeta->argTypes(eMeta->methodId(QByteArray(funcname))); - for(int i = 0; i < argTypes.size(); i++) { - if(argTypes[i] == 0) { - qWarning() << Q_FUNC_INFO << "received invalid data for argument number" << i << "of signal" << QString("%1::%2").arg(eMeta->metaObject()->className()).arg(funcname); - qWarning() << " - make sure all your data types are known by the Qt MetaSystem"; - return; + for (int i = 0; i < argTypes.size(); i++) { + if (argTypes[i] == 0) { + qWarning() << Q_FUNC_INFO << "received invalid data for argument number" << i << "of signal" << QString("%1::%2").arg(eMeta->metaObject()->className()).arg(funcname); + qWarning() << " - make sure all your data types are known by the Qt MetaSystem"; + return; + } + params << QVariant(argTypes[i], va_arg(ap, void *)); } - params << QVariant(argTypes[i], va_arg(ap, void *)); - } - dispatchSignal(Sync, params); + dispatchSignal(Sync, params); } - -void SignalProxy::disconnectDevice(QIODevice *dev, const QString &reason) { - if(!reason.isEmpty()) - qWarning() << qPrintable(reason); - QAbstractSocket *sock = qobject_cast(dev); - if(sock) - qWarning() << qPrintable(tr("Disconnecting")) << qPrintable(sock->peerAddress().toString()); - dev->close(); +void SignalProxy::disconnectDevice(QIODevice *dev, const QString &reason) +{ + if (!reason.isEmpty()) + qWarning() << qPrintable(reason); + QAbstractSocket *sock = qobject_cast(dev); + if (sock) + qWarning() << qPrintable(tr("Disconnecting")) << qPrintable(sock->peerAddress().toString()); + dev->close(); } -void SignalProxy::updateLag(IODevicePeer *peer, int lag) { - peer->lag = lag; - if(proxyMode() == Client) { - emit lagUpdated(lag); - } + +void SignalProxy::updateLag(IODevicePeer *peer, int lag) +{ + peer->lag = lag; + if (proxyMode() == Client) { + emit lagUpdated(lag); + } } -void SignalProxy::dumpProxyStats() { - QString mode; - if(proxyMode() == Server) - mode = "Server"; - else - mode = "Client"; - int slaveCount = 0; - foreach(ObjectId oid, _syncSlave.values()) +void SignalProxy::dumpProxyStats() +{ + QString mode; + if (proxyMode() == Server) + mode = "Server"; + else + mode = "Client"; + + int slaveCount = 0; + foreach(ObjectId oid, _syncSlave.values()) slaveCount += oid.count(); - qDebug() << this; - qDebug() << " Proxy Mode:" << mode; - qDebug() << " attached Slots:" << _attachedSlots.count(); - qDebug() << " number of synced Slaves:" << slaveCount; - qDebug() << "number of Classes cached:" << _extendedMetaObjects.count(); + qDebug() << this; + qDebug() << " Proxy Mode:" << mode; + qDebug() << " attached Slots:" << _attachedSlots.count(); + qDebug() << " number of synced Slaves:" << slaveCount; + qDebug() << "number of Classes cached:" << _extendedMetaObjects.count(); } -void SignalProxy::updateSecureState() { - bool wasSecure = _secure; - _secure = !_peers.isEmpty(); - PeerHash::const_iterator peerIter; - for(peerIter = _peers.constBegin(); peerIter != _peers.constEnd(); peerIter++) { - _secure &= (*peerIter)->isSecure(); - } +void SignalProxy::updateSecureState() +{ + bool wasSecure = _secure; - if(wasSecure != _secure) - emit secureStateChanged(_secure); + _secure = !_peers.isEmpty(); + PeerHash::const_iterator peerIter; + for (peerIter = _peers.constBegin(); peerIter != _peers.constEnd(); peerIter++) { + _secure &= (*peerIter)->isSecure(); + } + + if (wasSecure != _secure) + emit secureStateChanged(_secure); } @@ -1094,155 +1218,165 @@ void SignalProxy::updateSecureState() { // ExtendedMetaObject // ================================================== SignalProxy::ExtendedMetaObject::ExtendedMetaObject(const QMetaObject *meta, bool checkConflicts) - : _meta(meta), + : _meta(meta), _updatedRemotelyId(_meta->indexOfSignal("updatedRemotely()")) { - for(int i = 0; i < _meta->methodCount(); i++) { - if(_meta->method(i).methodType() != QMetaMethod::Slot) - continue; - - if(QByteArray(_meta->method(i).signature()).contains('*')) - continue; // skip methods with ptr params - - QByteArray method = methodName(_meta->method(i)); - if(method.startsWith("init")) - continue; // skip initializers - - if(_methodIds.contains(method)) { - /* funny... moc creates for methods containing default parameters multiple metaMethod with separate methodIds. - we don't care... we just need the full fledged version - */ - const QMetaMethod ¤t = _meta->method(_methodIds[method]); - const QMetaMethod &candidate = _meta->method(i); - if(current.parameterTypes().count() > candidate.parameterTypes().count()) { - int minCount = candidate.parameterTypes().count(); - QList commonParams = current.parameterTypes().mid(0, minCount); - if(commonParams == candidate.parameterTypes()) - continue; // we already got the full featured version - } else { - int minCount = current.parameterTypes().count(); - QList commonParams = candidate.parameterTypes().mid(0, minCount); - if(commonParams == current.parameterTypes()) { - _methodIds[method] = i; // use the new one - continue; + for (int i = 0; i < _meta->methodCount(); i++) { + if (_meta->method(i).methodType() != QMetaMethod::Slot) + continue; + + if (QByteArray(_meta->method(i).signature()).contains('*')) + continue; // skip methods with ptr params + + QByteArray method = methodName(_meta->method(i)); + if (method.startsWith("init")) + continue; // skip initializers + + if (_methodIds.contains(method)) { + /* funny... moc creates for methods containing default parameters multiple metaMethod with separate methodIds. + we don't care... we just need the full fledged version + */ + const QMetaMethod ¤t = _meta->method(_methodIds[method]); + const QMetaMethod &candidate = _meta->method(i); + if (current.parameterTypes().count() > candidate.parameterTypes().count()) { + int minCount = candidate.parameterTypes().count(); + QList commonParams = current.parameterTypes().mid(0, minCount); + if (commonParams == candidate.parameterTypes()) + continue; // we already got the full featured version + } + else { + int minCount = current.parameterTypes().count(); + QList commonParams = candidate.parameterTypes().mid(0, minCount); + if (commonParams == current.parameterTypes()) { + _methodIds[method] = i; // use the new one + continue; + } + } + if (checkConflicts) { + qWarning() << "class" << meta->className() << "contains overloaded methods which is currently not supported!"; + qWarning() << " - " << _meta->method(i).signature() << "conflicts with" << _meta->method(_methodIds[method]).signature(); + } + continue; } - } - if(checkConflicts) { - qWarning() << "class" << meta->className() << "contains overloaded methods which is currently not supported!"; - qWarning() << " - " << _meta->method(i).signature() << "conflicts with" << _meta->method(_methodIds[method]).signature(); - } - continue; + _methodIds[method] = i; } - _methodIds[method] = i; - } } -const SignalProxy::ExtendedMetaObject::MethodDescriptor &SignalProxy::ExtendedMetaObject::methodDescriptor(int methodId) { - if(!_methods.contains(methodId)) { - _methods[methodId] = MethodDescriptor(_meta->method(methodId)); - } - return _methods[methodId]; -} -const QHash &SignalProxy::ExtendedMetaObject::receiveMap() { - if(_receiveMap.isEmpty()) { - QHash receiveMap; - - QMetaMethod requestSlot; - QByteArray returnTypeName; - QByteArray signature; - QByteArray methodName; - QByteArray params; - int paramsPos; - int receiverId; - const int methodCount = _meta->methodCount(); - for(int i = 0; i < methodCount; i++) { - requestSlot = _meta->method(i); - if(requestSlot.methodType() != QMetaMethod::Slot) - continue; - - returnTypeName = requestSlot.typeName(); - if(QMetaType::Void == (QMetaType::Type)returnType(i)) - continue; - - signature = QByteArray(requestSlot.signature()); - if(!signature.startsWith("request")) - continue; - - paramsPos = signature.indexOf('('); - if(paramsPos == -1) - continue; - - methodName = signature.left(paramsPos); - params = signature.mid(paramsPos); - - methodName = methodName.replace("request", "receive"); - params = params.left(params.count() - 1) + ", " + returnTypeName + ")"; - - signature = QMetaObject::normalizedSignature(methodName + params); - receiverId = _meta->indexOfSlot(signature); +const SignalProxy::ExtendedMetaObject::MethodDescriptor &SignalProxy::ExtendedMetaObject::methodDescriptor(int methodId) +{ + if (!_methods.contains(methodId)) { + _methods[methodId] = MethodDescriptor(_meta->method(methodId)); + } + return _methods[methodId]; +} - if(receiverId == -1) { - signature = QMetaObject::normalizedSignature(methodName + "(" + returnTypeName + ")"); - receiverId = _meta->indexOfSlot(signature); - } - if(receiverId != -1) { - receiveMap[i] = receiverId; - } +const QHash &SignalProxy::ExtendedMetaObject::receiveMap() +{ + if (_receiveMap.isEmpty()) { + QHash receiveMap; + + QMetaMethod requestSlot; + QByteArray returnTypeName; + QByteArray signature; + QByteArray methodName; + QByteArray params; + int paramsPos; + int receiverId; + const int methodCount = _meta->methodCount(); + for (int i = 0; i < methodCount; i++) { + requestSlot = _meta->method(i); + if (requestSlot.methodType() != QMetaMethod::Slot) + continue; + + returnTypeName = requestSlot.typeName(); + if (QMetaType::Void == (QMetaType::Type)returnType(i)) + continue; + + signature = QByteArray(requestSlot.signature()); + if (!signature.startsWith("request")) + continue; + + paramsPos = signature.indexOf('('); + if (paramsPos == -1) + continue; + + methodName = signature.left(paramsPos); + params = signature.mid(paramsPos); + + methodName = methodName.replace("request", "receive"); + params = params.left(params.count() - 1) + ", " + returnTypeName + ")"; + + signature = QMetaObject::normalizedSignature(methodName + params); + receiverId = _meta->indexOfSlot(signature); + + if (receiverId == -1) { + signature = QMetaObject::normalizedSignature(methodName + "(" + returnTypeName + ")"); + receiverId = _meta->indexOfSlot(signature); + } + + if (receiverId != -1) { + receiveMap[i] = receiverId; + } + } + _receiveMap = receiveMap; } - _receiveMap = receiveMap; - } - return _receiveMap; + return _receiveMap; } -QByteArray SignalProxy::ExtendedMetaObject::methodName(const QMetaMethod &method) { - QByteArray sig(method.signature()); - return sig.left(sig.indexOf("(")); + +QByteArray SignalProxy::ExtendedMetaObject::methodName(const QMetaMethod &method) +{ + QByteArray sig(method.signature()); + return sig.left(sig.indexOf("(")); } -QString SignalProxy::ExtendedMetaObject::methodBaseName(const QMetaMethod &method) { - QString methodname = QString(method.signature()).section("(", 0, 0); - // determine where we have to chop: - int upperCharPos; - if(method.methodType() == QMetaMethod::Slot) { - // we take evertyhing from the first uppercase char if it's slot - upperCharPos = methodname.indexOf(QRegExp("[A-Z]")); - if(upperCharPos == -1) - return QString(); - methodname = methodname.mid(upperCharPos); - } else { - // and if it's a signal we discard everything from the last uppercase char - upperCharPos = methodname.lastIndexOf(QRegExp("[A-Z]")); - if(upperCharPos == -1) - return QString(); - methodname = methodname.left(upperCharPos); - } +QString SignalProxy::ExtendedMetaObject::methodBaseName(const QMetaMethod &method) +{ + QString methodname = QString(method.signature()).section("(", 0, 0); + + // determine where we have to chop: + int upperCharPos; + if (method.methodType() == QMetaMethod::Slot) { + // we take evertyhing from the first uppercase char if it's slot + upperCharPos = methodname.indexOf(QRegExp("[A-Z]")); + if (upperCharPos == -1) + return QString(); + methodname = methodname.mid(upperCharPos); + } + else { + // and if it's a signal we discard everything from the last uppercase char + upperCharPos = methodname.lastIndexOf(QRegExp("[A-Z]")); + if (upperCharPos == -1) + return QString(); + methodname = methodname.left(upperCharPos); + } - methodname[0] = methodname[0].toUpper(); + methodname[0] = methodname[0].toUpper(); - return methodname; + return methodname; } + SignalProxy::ExtendedMetaObject::MethodDescriptor::MethodDescriptor(const QMetaMethod &method) - : _methodName(SignalProxy::ExtendedMetaObject::methodName(method)), + : _methodName(SignalProxy::ExtendedMetaObject::methodName(method)), _returnType(QMetaType::type(method.typeName())) { - // determine argTypes - QList paramTypes = method.parameterTypes(); - QList argTypes; - for(int i = 0; i < paramTypes.count(); i++) { - argTypes.append(QMetaType::type(paramTypes[i])); - } - _argTypes = argTypes; + // determine argTypes + QList paramTypes = method.parameterTypes(); + QList argTypes; + for (int i = 0; i < paramTypes.count(); i++) { + argTypes.append(QMetaType::type(paramTypes[i])); + } + _argTypes = argTypes; - // determine minArgCount - QString signature(method.signature()); - _minArgCount = method.parameterTypes().count() - signature.count("="); + // determine minArgCount + QString signature(method.signature()); + _minArgCount = method.parameterTypes().count() - signature.count("="); - _receiverMode = (_methodName.startsWith("request")) - ? SignalProxy::Server - : SignalProxy::Client; + _receiverMode = (_methodName.startsWith("request")) + ? SignalProxy::Server + : SignalProxy::Client; } - diff --git a/src/common/signalproxy.h b/src/common/signalproxy.h index 867ffdbd..e1a6bcf8 100644 --- a/src/common/signalproxy.h +++ b/src/common/signalproxy.h @@ -34,285 +34,294 @@ class SyncableObject; struct QMetaObject; -class SignalProxy : public QObject { - Q_OBJECT +class SignalProxy : public QObject +{ + Q_OBJECT - class AbstractPeer; - class IODevicePeer; - class SignalProxyPeer; + class AbstractPeer; + class IODevicePeer; + class SignalProxyPeer; - class SignalRelay; + class SignalRelay; public: - enum ProxyMode { - Server, - Client - }; - - enum RequestType { - Sync = 1, - RpcCall, - InitRequest, - InitData, - HeartBeat, - HeartBeatReply - }; - - enum ClientConnectionType { - SignalProxyConnection, - IODeviceConnection - }; - - enum CustomEvents { - PeerSignal = QEvent::User, - RemovePeer - }; - - SignalProxy(QObject *parent); - SignalProxy(ProxyMode mode, QObject *parent); - SignalProxy(ProxyMode mode, QIODevice *device, QObject *parent); - virtual ~SignalProxy(); - - void setProxyMode(ProxyMode mode); - inline ProxyMode proxyMode() const { return _proxyMode; } - - void setHeartBeatInterval(int secs); - inline int heartBeatInterval() const { return _heartBeatInterval; } - void setMaxHeartBeatCount(int max); - inline int maxHeartBeatCount() const { return _maxHeartBeatCount; } - - bool addPeer(QIODevice *iodev); - bool addPeer(SignalProxy *proxy); - void removePeer(QObject *peer); - void removeAllPeers(); - - bool attachSignal(QObject *sender, const char *signal, const QByteArray& sigName = QByteArray()); - bool attachSlot(const QByteArray& sigName, QObject *recv, const char *slot); - - void synchronize(SyncableObject *obj); - void stopSynchronize(SyncableObject *obj); - - //! Writes a QVariant to a device. - /** The data item is prefixed with the resulting blocksize, - * so the corresponding function readDataFromDevice() can check if enough data is available - * at the device to reread the item. - */ - static void writeDataToDevice(QIODevice *dev, const QVariant &item, bool compressed = false); - - //! Reads a data item from a device that has been written by writeDataToDevice(). - /** If not enough data bytes are available, the function returns false and the QVariant reference - * remains untouched. - */ - static bool readDataFromDevice(QIODevice *dev, quint32 &blockSize, QVariant &item, bool compressed = false); - - class ExtendedMetaObject; - ExtendedMetaObject *extendedMetaObject(const QMetaObject *meta) const; - ExtendedMetaObject *createExtendedMetaObject(const QMetaObject *meta, bool checkConflicts = false); - inline ExtendedMetaObject *extendedMetaObject(const QObject *obj) const { return extendedMetaObject(metaObject(obj)); } - inline ExtendedMetaObject *createExtendedMetaObject(const QObject *obj, bool checkConflicts = false) { return createExtendedMetaObject(metaObject(obj), checkConflicts); } - - bool isSecure() const { return _secure; } - void dumpProxyStats(); + enum ProxyMode { + Server, + Client + }; + + enum RequestType { + Sync = 1, + RpcCall, + InitRequest, + InitData, + HeartBeat, + HeartBeatReply + }; + + enum ClientConnectionType { + SignalProxyConnection, + IODeviceConnection + }; + + enum CustomEvents { + PeerSignal = QEvent::User, + RemovePeer + }; + + SignalProxy(QObject *parent); + SignalProxy(ProxyMode mode, QObject *parent); + SignalProxy(ProxyMode mode, QIODevice *device, QObject *parent); + virtual ~SignalProxy(); + + void setProxyMode(ProxyMode mode); + inline ProxyMode proxyMode() const { return _proxyMode; } + + void setHeartBeatInterval(int secs); + inline int heartBeatInterval() const { return _heartBeatInterval; } + void setMaxHeartBeatCount(int max); + inline int maxHeartBeatCount() const { return _maxHeartBeatCount; } + + bool addPeer(QIODevice *iodev); + bool addPeer(SignalProxy *proxy); + void removePeer(QObject *peer); + void removeAllPeers(); + + bool attachSignal(QObject *sender, const char *signal, const QByteArray &sigName = QByteArray()); + bool attachSlot(const QByteArray &sigName, QObject *recv, const char *slot); + + void synchronize(SyncableObject *obj); + void stopSynchronize(SyncableObject *obj); + + //! Writes a QVariant to a device. + /** The data item is prefixed with the resulting blocksize, + * so the corresponding function readDataFromDevice() can check if enough data is available + * at the device to reread the item. + */ + static void writeDataToDevice(QIODevice *dev, const QVariant &item, bool compressed = false); + + //! Reads a data item from a device that has been written by writeDataToDevice(). + /** If not enough data bytes are available, the function returns false and the QVariant reference + * remains untouched. + */ + static bool readDataFromDevice(QIODevice *dev, quint32 &blockSize, QVariant &item, bool compressed = false); + + class ExtendedMetaObject; + ExtendedMetaObject *extendedMetaObject(const QMetaObject *meta) const; + ExtendedMetaObject *createExtendedMetaObject(const QMetaObject *meta, bool checkConflicts = false); + inline ExtendedMetaObject *extendedMetaObject(const QObject *obj) const { return extendedMetaObject(metaObject(obj)); } + inline ExtendedMetaObject *createExtendedMetaObject(const QObject *obj, bool checkConflicts = false) { return createExtendedMetaObject(metaObject(obj), checkConflicts); } + + bool isSecure() const { return _secure; } + void dumpProxyStats(); public slots: - void detachObject(QObject *obj); - void detachSignals(QObject *sender); - void detachSlots(QObject *receiver); + void detachObject(QObject *obj); + void detachSignals(QObject *sender); + void detachSlots(QObject *receiver); protected: - void customEvent(QEvent *event); - void sync_call__(const SyncableObject *obj, ProxyMode modeType, const char *funcname, va_list ap); - void renameObject(const SyncableObject *obj, const QString &newname, const QString &oldname); + void customEvent(QEvent *event); + void sync_call__(const SyncableObject *obj, ProxyMode modeType, const char *funcname, va_list ap); + void renameObject(const SyncableObject *obj, const QString &newname, const QString &oldname); private slots: - void dataAvailable(); - void removePeerBySender(); - void objectRenamed(const QByteArray &classname, const QString &newname, const QString &oldname); - void sendHeartBeat(); - void receiveHeartBeat(AbstractPeer *peer, const QVariantList ¶ms); - void receiveHeartBeatReply(AbstractPeer *peer, const QVariantList ¶ms); + void dataAvailable(); + void removePeerBySender(); + void objectRenamed(const QByteArray &classname, const QString &newname, const QString &oldname); + void sendHeartBeat(); + void receiveHeartBeat(AbstractPeer *peer, const QVariantList ¶ms); + void receiveHeartBeatReply(AbstractPeer *peer, const QVariantList ¶ms); - void updateSecureState(); + void updateSecureState(); signals: - void peerRemoved(QIODevice *dev); - void connected(); - void disconnected(); - void objectInitialized(SyncableObject *); - void lagUpdated(int lag); - void securityChanged(bool); - void secureStateChanged(bool); + void peerRemoved(QIODevice *dev); + void connected(); + void disconnected(); + void objectInitialized(SyncableObject *); + void lagUpdated(int lag); + void securityChanged(bool); + void secureStateChanged(bool); private: - void init(); - void initServer(); - void initClient(); + void init(); + void initServer(); + void initClient(); - static const QMetaObject *metaObject(const QObject *obj); + static const QMetaObject *metaObject(const QObject *obj); - void dispatchSignal(QIODevice *receiver, const RequestType &requestType, const QVariantList ¶ms); - void dispatchSignal(const RequestType &requestType, const QVariantList ¶ms); + void dispatchSignal(QIODevice *receiver, const RequestType &requestType, const QVariantList ¶ms); + void dispatchSignal(const RequestType &requestType, const QVariantList ¶ms); - void receivePackedFunc(AbstractPeer *sender, const QVariant &packedFunc); - void receivePeerSignal(AbstractPeer *sender, const RequestType &requestType, const QVariantList ¶ms); - void receivePeerSignal(SignalProxy *sender, const RequestType &requestType, const QVariantList ¶ms); - void handleSync(AbstractPeer *sender, QVariantList params); - void handleInitRequest(AbstractPeer *sender, const QVariantList ¶ms); - void handleInitData(AbstractPeer *sender, const QVariantList ¶ms); - void handleSignal(const QVariantList &data); + void receivePackedFunc(AbstractPeer *sender, const QVariant &packedFunc); + void receivePeerSignal(AbstractPeer *sender, const RequestType &requestType, const QVariantList ¶ms); + void receivePeerSignal(SignalProxy *sender, const RequestType &requestType, const QVariantList ¶ms); + void handleSync(AbstractPeer *sender, QVariantList params); + void handleInitRequest(AbstractPeer *sender, const QVariantList ¶ms); + void handleInitData(AbstractPeer *sender, const QVariantList ¶ms); + void handleSignal(const QVariantList &data); - bool invokeSlot(QObject *receiver, int methodId, const QVariantList ¶ms, QVariant &returnValue); - bool invokeSlot(QObject *receiver, int methodId, const QVariantList ¶ms = QVariantList()); + bool invokeSlot(QObject *receiver, int methodId, const QVariantList ¶ms, QVariant &returnValue); + bool invokeSlot(QObject *receiver, int methodId, const QVariantList ¶ms = QVariantList()); - void requestInit(SyncableObject *obj); - QVariantMap initData(SyncableObject *obj) const; - void setInitData(SyncableObject *obj, const QVariantMap &properties); + void requestInit(SyncableObject *obj); + QVariantMap initData(SyncableObject *obj) const; + void setInitData(SyncableObject *obj, const QVariantMap &properties); - void updateLag(IODevicePeer *peer, int lag); + void updateLag(IODevicePeer *peer, int lag); public: - void dumpSyncMap(SyncableObject *object); - inline int peerCount() const { return _peers.size(); } + void dumpSyncMap(SyncableObject *object); + inline int peerCount() const { return _peers.size(); } private: - static void disconnectDevice(QIODevice *dev, const QString &reason = QString()); + static void disconnectDevice(QIODevice *dev, const QString &reason = QString()); - // a Hash of the actual used communication object to it's corresponding peer - // currently a communication object can either be an arbitrary QIODevice or another SignalProxy - typedef QHash PeerHash; - PeerHash _peers; + // a Hash of the actual used communication object to it's corresponding peer + // currently a communication object can either be an arbitrary QIODevice or another SignalProxy + typedef QHash PeerHash; + PeerHash _peers; - // containg a list of argtypes for fast access - QHash _extendedMetaObjects; + // containg a list of argtypes for fast access + QHash _extendedMetaObjects; - // SignalRelay for all manually attached signals - SignalRelay *_signalRelay; + // SignalRelay for all manually attached signals + SignalRelay *_signalRelay; - // RPC function -> (object, slot ID) - typedef QPair MethodId; - typedef QMultiHash SlotHash; - SlotHash _attachedSlots; + // RPC function -> (object, slot ID) + typedef QPair MethodId; + typedef QMultiHash SlotHash; + SlotHash _attachedSlots; - // slaves for sync - typedef QHash ObjectId; - QHash _syncSlave; + // slaves for sync + typedef QHash ObjectId; + QHash _syncSlave; + ProxyMode _proxyMode; + QTimer _heartBeatTimer; + int _heartBeatInterval; + int _maxHeartBeatCount; - ProxyMode _proxyMode; - QTimer _heartBeatTimer; - int _heartBeatInterval; - int _maxHeartBeatCount; + bool _secure; // determines if all connections are in a secured state (using ssl or internal connections) - bool _secure; // determines if all connections are in a secured state (using ssl or internal connections) - - friend class SignalRelay; - friend class SyncableObject; + friend class SignalRelay; + friend class SyncableObject; }; // ================================================== // ExtendedMetaObject // ================================================== -class SignalProxy::ExtendedMetaObject { - class MethodDescriptor { - public: - MethodDescriptor(const QMetaMethod &method); - MethodDescriptor() : _returnType(-1), _minArgCount(-1), _receiverMode(SignalProxy::Client) {} - - inline const QByteArray &methodName() const { return _methodName; } - inline const QList &argTypes() const { return _argTypes; } - inline int returnType() const { return _returnType; } - inline int minArgCount() const { return _minArgCount; } - inline SignalProxy::ProxyMode receiverMode() const { return _receiverMode; } - - private: - QByteArray _methodName; - QList _argTypes; - int _returnType; - int _minArgCount; - SignalProxy::ProxyMode _receiverMode; // Only acceptable as a Sync Call if the receiving SignalProxy is in this mode. - }; +class SignalProxy::ExtendedMetaObject +{ + class MethodDescriptor + { +public: + MethodDescriptor(const QMetaMethod &method); + MethodDescriptor() : _returnType(-1), _minArgCount(-1), _receiverMode(SignalProxy::Client) {} + + inline const QByteArray &methodName() const { return _methodName; } + inline const QList &argTypes() const { return _argTypes; } + inline int returnType() const { return _returnType; } + inline int minArgCount() const { return _minArgCount; } + inline SignalProxy::ProxyMode receiverMode() const { return _receiverMode; } + +private: + QByteArray _methodName; + QList _argTypes; + int _returnType; + int _minArgCount; + SignalProxy::ProxyMode _receiverMode; // Only acceptable as a Sync Call if the receiving SignalProxy is in this mode. + }; + public: - ExtendedMetaObject(const QMetaObject *meta, bool checkConflicts); + ExtendedMetaObject(const QMetaObject *meta, bool checkConflicts); - inline const QByteArray &methodName(int methodId) { return methodDescriptor(methodId).methodName(); } - inline const QList &argTypes(int methodId) { return methodDescriptor(methodId).argTypes(); } - inline int returnType(int methodId) { return methodDescriptor(methodId).returnType(); } - inline int minArgCount(int methodId) { return methodDescriptor(methodId).minArgCount(); } - inline SignalProxy::ProxyMode receiverMode(int methodId) { return methodDescriptor(methodId).receiverMode(); } + inline const QByteArray &methodName(int methodId) { return methodDescriptor(methodId).methodName(); } + inline const QList &argTypes(int methodId) { return methodDescriptor(methodId).argTypes(); } + inline int returnType(int methodId) { return methodDescriptor(methodId).returnType(); } + inline int minArgCount(int methodId) { return methodDescriptor(methodId).minArgCount(); } + inline SignalProxy::ProxyMode receiverMode(int methodId) { return methodDescriptor(methodId).receiverMode(); } - inline int methodId(const QByteArray &methodName) { return _methodIds.contains(methodName) ? _methodIds[methodName] : -1; } + inline int methodId(const QByteArray &methodName) { return _methodIds.contains(methodName) ? _methodIds[methodName] : -1; } - inline int updatedRemotelyId() { return _updatedRemotelyId; } + inline int updatedRemotelyId() { return _updatedRemotelyId; } - inline const QHash &slotMap() { return _methodIds; } - const QHash &receiveMap(); + inline const QHash &slotMap() { return _methodIds; } + const QHash &receiveMap(); - const QMetaObject *metaObject() const { return _meta; } + const QMetaObject *metaObject() const { return _meta; } - static QByteArray methodName(const QMetaMethod &method); - static QString methodBaseName(const QMetaMethod &method); + static QByteArray methodName(const QMetaMethod &method); + static QString methodBaseName(const QMetaMethod &method); private: - const MethodDescriptor &methodDescriptor(int methodId); + const MethodDescriptor &methodDescriptor(int methodId); - const QMetaObject *_meta; - int _updatedRemotelyId; // id of the updatedRemotely() signal - makes things faster + const QMetaObject *_meta; + int _updatedRemotelyId; // id of the updatedRemotely() signal - makes things faster - QHash _methods; - QHash _methodIds; - QHash _receiveMap; // if slot x is called then hand over the result to slot y + QHash _methods; + QHash _methodIds; + QHash _receiveMap; // if slot x is called then hand over the result to slot y }; // ================================================== // Peers // ================================================== -class SignalProxy::AbstractPeer { +class SignalProxy::AbstractPeer +{ public: - enum PeerType { - NotAPeer = 0, - IODevicePeer = 1, - SignalProxyPeer = 2 - }; - AbstractPeer() : _type(NotAPeer) {} - AbstractPeer(PeerType type) : _type(type) {} - virtual ~AbstractPeer() {} - inline PeerType type() const { return _type; } - virtual void dispatchSignal(const RequestType &requestType, const QVariantList ¶ms) = 0; - virtual bool isSecure() const = 0; + enum PeerType { + NotAPeer = 0, + IODevicePeer = 1, + SignalProxyPeer = 2 + }; + AbstractPeer() : _type(NotAPeer) {} + AbstractPeer(PeerType type) : _type(type) {} + virtual ~AbstractPeer() {} + inline PeerType type() const { return _type; } + virtual void dispatchSignal(const RequestType &requestType, const QVariantList ¶ms) = 0; + virtual bool isSecure() const = 0; private: - PeerType _type; + PeerType _type; }; -class SignalProxy::IODevicePeer : public SignalProxy::AbstractPeer { + +class SignalProxy::IODevicePeer : public SignalProxy::AbstractPeer +{ public: - IODevicePeer(QIODevice *device, bool compress) : AbstractPeer(AbstractPeer::IODevicePeer), _device(device), byteCount(0), usesCompression(compress), sentHeartBeats(0), lag(0) {} - virtual void dispatchSignal(const RequestType &requestType, const QVariantList ¶ms); - virtual bool isSecure() const; - inline void dispatchPackedFunc(const QVariant &packedFunc) { SignalProxy::writeDataToDevice(_device, packedFunc, usesCompression); } - QString address() const; - inline bool isOpen() const { return _device->isOpen(); } - inline void close() const { _device->close(); } - inline bool readData(QVariant &item) { return SignalProxy::readDataFromDevice(_device, byteCount, item, usesCompression); } + IODevicePeer(QIODevice *device, bool compress) : AbstractPeer(AbstractPeer::IODevicePeer), _device(device), byteCount(0), usesCompression(compress), sentHeartBeats(0), lag(0) {} + virtual void dispatchSignal(const RequestType &requestType, const QVariantList ¶ms); + virtual bool isSecure() const; + inline void dispatchPackedFunc(const QVariant &packedFunc) { SignalProxy::writeDataToDevice(_device, packedFunc, usesCompression); } + QString address() const; + inline bool isOpen() const { return _device->isOpen(); } + inline void close() const { _device->close(); } + inline bool readData(QVariant &item) { return SignalProxy::readDataFromDevice(_device, byteCount, item, usesCompression); } private: - QIODevice *_device; - quint32 byteCount; - bool usesCompression; + QIODevice *_device; + quint32 byteCount; + bool usesCompression; public: - int sentHeartBeats; - int lag; + int sentHeartBeats; + int lag; }; -class SignalProxy::SignalProxyPeer : public SignalProxy::AbstractPeer { + +class SignalProxy::SignalProxyPeer : public SignalProxy::AbstractPeer +{ public: - SignalProxyPeer(SignalProxy *sender, SignalProxy *receiver) : AbstractPeer(AbstractPeer::SignalProxyPeer), sender(sender), receiver(receiver) {} - virtual void dispatchSignal(const RequestType &requestType, const QVariantList ¶ms); - virtual inline bool isSecure() const { return true; } + SignalProxyPeer(SignalProxy *sender, SignalProxy *receiver) : AbstractPeer(AbstractPeer::SignalProxyPeer), sender(sender), receiver(receiver) {} + virtual void dispatchSignal(const RequestType &requestType, const QVariantList ¶ms); + virtual inline bool isSecure() const { return true; } private: - SignalProxy *sender; - SignalProxy *receiver; + SignalProxy *sender; + SignalProxy *receiver; }; + #endif diff --git a/src/common/syncableobject.cpp b/src/common/syncableobject.cpp index ac62f080..1b907c71 100644 --- a/src/common/syncableobject.cpp +++ b/src/common/syncableobject.cpp @@ -29,177 +29,205 @@ INIT_SYNCABLE_OBJECT(SyncableObject) SyncableObject::SyncableObject(QObject *parent) - : QObject(parent), + : QObject(parent), _initialized(false), _allowClientUpdates(false) { } + SyncableObject::SyncableObject(const QString &objectName, QObject *parent) - : QObject(parent), + : QObject(parent), _initialized(false), _allowClientUpdates(false) { - setObjectName(objectName); + setObjectName(objectName); } + SyncableObject::SyncableObject(const SyncableObject &other, QObject *parent) - : QObject(parent), + : QObject(parent), _initialized(other._initialized), _allowClientUpdates(other._allowClientUpdates) { } -SyncableObject::~SyncableObject() { - QList::iterator proxyIter = _signalProxies.begin(); - while(proxyIter != _signalProxies.end()) { - SignalProxy *proxy = (*proxyIter); - proxyIter = _signalProxies.erase(proxyIter); - proxy->stopSynchronize(this); - } + +SyncableObject::~SyncableObject() +{ + QList::iterator proxyIter = _signalProxies.begin(); + while (proxyIter != _signalProxies.end()) { + SignalProxy *proxy = (*proxyIter); + proxyIter = _signalProxies.erase(proxyIter); + proxy->stopSynchronize(this); + } } -SyncableObject &SyncableObject::operator=(const SyncableObject &other) { - if(this == &other) - return *this; - _initialized = other._initialized; - _allowClientUpdates = other._allowClientUpdates; - return *this; -} +SyncableObject &SyncableObject::operator=(const SyncableObject &other) +{ + if (this == &other) + return *this; -bool SyncableObject::isInitialized() const { - return _initialized; + _initialized = other._initialized; + _allowClientUpdates = other._allowClientUpdates; + return *this; } -void SyncableObject::setInitialized() { - _initialized = true; - emit initDone(); -} -QVariantMap SyncableObject::toVariantMap() { - QVariantMap properties; +bool SyncableObject::isInitialized() const +{ + return _initialized; +} - const QMetaObject* meta = metaObject(); - // we collect data from properties - QMetaProperty prop; - QString propName; - for(int i = 0; i < meta->propertyCount(); i++) { - prop = meta->property(i); - propName = QString(prop.name()); - if(propName == "objectName") - continue; - properties[propName] = prop.read(this); - } +void SyncableObject::setInitialized() +{ + _initialized = true; + emit initDone(); +} - // ...as well as methods, which have names starting with "init" - for(int i = 0; i < meta->methodCount(); i++) { - QMetaMethod method = meta->method(i); - QString methodname(SignalProxy::ExtendedMetaObject::methodName(method)); - if(!methodname.startsWith("init") || methodname.startsWith("initSet") || methodname.startsWith("initDone")) - continue; - QVariant::Type variantType = QVariant::nameToType(method.typeName()); - if(variantType == QVariant::Invalid && !QByteArray(method.typeName()).isEmpty()) { - qWarning() << "SyncableObject::toVariantMap(): cannot fetch init data for:" << this << method.signature() << "- Returntype is unknown to Qt's MetaSystem:" << QByteArray(method.typeName()); - continue; +QVariantMap SyncableObject::toVariantMap() +{ + QVariantMap properties; + + const QMetaObject *meta = metaObject(); + + // we collect data from properties + QMetaProperty prop; + QString propName; + for (int i = 0; i < meta->propertyCount(); i++) { + prop = meta->property(i); + propName = QString(prop.name()); + if (propName == "objectName") + continue; + properties[propName] = prop.read(this); } - QVariant value(variantType, (const void *) 0); - QGenericReturnArgument genericvalue = QGenericReturnArgument(method.typeName(), value.data()); - QMetaObject::invokeMethod(this, methodname.toAscii(), genericvalue); + // ...as well as methods, which have names starting with "init" + for (int i = 0; i < meta->methodCount(); i++) { + QMetaMethod method = meta->method(i); + QString methodname(SignalProxy::ExtendedMetaObject::methodName(method)); + if (!methodname.startsWith("init") || methodname.startsWith("initSet") || methodname.startsWith("initDone")) + continue; - properties[SignalProxy::ExtendedMetaObject::methodBaseName(method)] = value; - } - return properties; -} + QVariant::Type variantType = QVariant::nameToType(method.typeName()); + if (variantType == QVariant::Invalid && !QByteArray(method.typeName()).isEmpty()) { + qWarning() << "SyncableObject::toVariantMap(): cannot fetch init data for:" << this << method.signature() << "- Returntype is unknown to Qt's MetaSystem:" << QByteArray(method.typeName()); + continue; + } -void SyncableObject::fromVariantMap(const QVariantMap &properties) { - const QMetaObject *meta = metaObject(); + QVariant value(variantType, (const void *)0); + QGenericReturnArgument genericvalue = QGenericReturnArgument(method.typeName(), value.data()); + QMetaObject::invokeMethod(this, methodname.toAscii(), genericvalue); - QVariantMap::const_iterator iterator = properties.constBegin(); - QString propName; - while(iterator != properties.constEnd()) { - propName = iterator.key(); - if(propName == "objectName") { - iterator++; - continue; + properties[SignalProxy::ExtendedMetaObject::methodBaseName(method)] = value; } + return properties; +} - int propertyIndex = meta->indexOfProperty(propName.toAscii()); - if(propertyIndex == -1 || !meta->property(propertyIndex).isWritable()) - setInitValue(propName, iterator.value()); - else - setProperty(propName.toAscii(), iterator.value()); - // qDebug() << "<<< SYNC:" << name << iterator.value(); - iterator++; - } +void SyncableObject::fromVariantMap(const QVariantMap &properties) +{ + const QMetaObject *meta = metaObject(); + + QVariantMap::const_iterator iterator = properties.constBegin(); + QString propName; + while (iterator != properties.constEnd()) { + propName = iterator.key(); + if (propName == "objectName") { + iterator++; + continue; + } + + int propertyIndex = meta->indexOfProperty(propName.toAscii()); + + if (propertyIndex == -1 || !meta->property(propertyIndex).isWritable()) + setInitValue(propName, iterator.value()); + else + setProperty(propName.toAscii(), iterator.value()); + // qDebug() << "<<< SYNC:" << name << iterator.value(); + iterator++; + } } -bool SyncableObject::setInitValue(const QString &property, const QVariant &value) { - QString handlername = QString("initSet") + property; - handlername[7] = handlername[7].toUpper(); - QString methodSignature = QString("%1(%2)").arg(handlername).arg(value.typeName()); - int methodIdx = metaObject()->indexOfMethod(methodSignature.toAscii().constData()); - if(methodIdx < 0) { - QByteArray normedMethodName = QMetaObject::normalizedSignature(methodSignature.toAscii().constData()); - methodIdx = metaObject()->indexOfMethod(normedMethodName.constData()); - } - if(methodIdx < 0) { - return false; - } +bool SyncableObject::setInitValue(const QString &property, const QVariant &value) +{ + QString handlername = QString("initSet") + property; + handlername[7] = handlername[7].toUpper(); + + QString methodSignature = QString("%1(%2)").arg(handlername).arg(value.typeName()); + int methodIdx = metaObject()->indexOfMethod(methodSignature.toAscii().constData()); + if (methodIdx < 0) { + QByteArray normedMethodName = QMetaObject::normalizedSignature(methodSignature.toAscii().constData()); + methodIdx = metaObject()->indexOfMethod(normedMethodName.constData()); + } + if (methodIdx < 0) { + return false; + } - QGenericArgument param(value.typeName(), value.constData()); - return QMetaObject::invokeMethod(this, handlername.toAscii(), param); + QGenericArgument param(value.typeName(), value.constData()); + return QMetaObject::invokeMethod(this, handlername.toAscii(), param); } -void SyncableObject::renameObject(const QString &newName) { - const QString oldName = objectName(); - if(oldName != newName) { - setObjectName(newName); - foreach(SignalProxy *proxy, _signalProxies) { - proxy->renameObject(this, newName, oldName); + +void SyncableObject::renameObject(const QString &newName) +{ + const QString oldName = objectName(); + if (oldName != newName) { + setObjectName(newName); + foreach(SignalProxy *proxy, _signalProxies) { + proxy->renameObject(this, newName, oldName); + } } - } } -void SyncableObject::update(const QVariantMap &properties) { - fromVariantMap(properties); - SYNC(ARG(properties)) - emit updated(); + +void SyncableObject::update(const QVariantMap &properties) +{ + fromVariantMap(properties); + SYNC(ARG(properties)) + emit updated(); } -void SyncableObject::requestUpdate(const QVariantMap &properties) { - if(allowClientUpdates()) { - update(properties); - } - REQUEST(ARG(properties)) + +void SyncableObject::requestUpdate(const QVariantMap &properties) +{ + if (allowClientUpdates()) { + update(properties); + } + REQUEST(ARG(properties)) } -void SyncableObject::sync_call__(SignalProxy::ProxyMode modeType, const char *funcname, ...) const { - //qDebug() << Q_FUNC_INFO << modeType << funcname; - foreach(SignalProxy *proxy, _signalProxies) { - va_list ap; - va_start(ap, funcname); - proxy->sync_call__(this, modeType, funcname, ap); - va_end(ap); - } + +void SyncableObject::sync_call__(SignalProxy::ProxyMode modeType, const char *funcname, ...) const +{ + //qDebug() << Q_FUNC_INFO << modeType << funcname; + foreach(SignalProxy *proxy, _signalProxies) { + va_list ap; + va_start(ap, funcname); + proxy->sync_call__(this, modeType, funcname, ap); + va_end(ap); + } } -void SyncableObject::synchronize(SignalProxy *proxy) { - if(_signalProxies.contains(proxy)) - return; - _signalProxies << proxy; + +void SyncableObject::synchronize(SignalProxy *proxy) +{ + if (_signalProxies.contains(proxy)) + return; + _signalProxies << proxy; } -void SyncableObject::stopSynchronize(SignalProxy *proxy) { - for(int i = 0; i < _signalProxies.count(); i++) { - if(_signalProxies[i] == proxy) { - _signalProxies.removeAt(i); - break; + +void SyncableObject::stopSynchronize(SignalProxy *proxy) +{ + for (int i = 0; i < _signalProxies.count(); i++) { + if (_signalProxies[i] == proxy) { + _signalProxies.removeAt(i); + break; + } } - } } diff --git a/src/common/syncableobject.h b/src/common/syncableobject.h index bec189a6..b4bda6df 100644 --- a/src/common/syncableobject.h +++ b/src/common/syncableobject.h @@ -28,14 +28,12 @@ #include "signalproxy.h" - - #define SYNCABLE_OBJECT static const int _classNameOffset__; #define INIT_SYNCABLE_OBJECT(x) const int x ::_classNameOffset__ = QByteArray(staticMetaObject.className()).length() + 2; #ifdef Q_CC_MSVC # define SYNC(...) sync_call__(SignalProxy::Server, (__FUNCTION__ + _classNameOffset__), __VA_ARGS__); -# define REQUEST(...) sync_call__(SignalProxy::Client, (__FUNCTION__ + _classNameOffset__) , __VA_ARGS__); +# define REQUEST(...) sync_call__(SignalProxy::Client, (__FUNCTION__ + _classNameOffset__), __VA_ARGS__); #else # define SYNC(...) sync_call__(SignalProxy::Server, __func__, __VA_ARGS__); # define REQUEST(...) sync_call__(SignalProxy::Client, __func__, __VA_ARGS__); @@ -44,74 +42,74 @@ #define SYNC_OTHER(x, ...) sync_call__(SignalProxy::Server, #x, __VA_ARGS__); #define REQUEST_OTHER(x, ...) sync_call__(SignalProxy::Client, #x, __VA_ARGS__); - -#define ARG(x) const_cast(reinterpret_cast(&x)) +#define ARG(x) const_cast(reinterpret_cast(&x)) #define NO_ARG 0 - -class SyncableObject : public QObject { - SYNCABLE_OBJECT - Q_OBJECT +class SyncableObject : public QObject +{ + SYNCABLE_OBJECT + Q_OBJECT public: - SyncableObject(QObject *parent = 0); - SyncableObject(const QString &objectName, QObject *parent = 0); - SyncableObject(const SyncableObject &other, QObject *parent = 0); - ~SyncableObject(); - - //! Stores the object's state into a QVariantMap. - /** The default implementation takes dynamic properties as well as getters that have - * names starting with "init" and stores them in a QVariantMap. Override this method in - * derived classes in order to store the object state in a custom form. - * \note This is used by SignalProxy to transmit the state of the object to clients - * that request the initial object state. Later updates use a different mechanism - * and assume that the state is completely covered by properties and init* getters. - * DO NOT OVERRIDE THIS unless you know exactly what you do! - * - * \return The object's state in a QVariantMap - */ - virtual QVariantMap toVariantMap(); - - //! Initialize the object's state from a given QVariantMap. - /** \see toVariantMap() for important information concerning this method. - */ - virtual void fromVariantMap(const QVariantMap &properties); - - virtual bool isInitialized() const; - - virtual const QMetaObject *syncMetaObject() const { return metaObject(); }; - - inline void setAllowClientUpdates(bool allow) { _allowClientUpdates = allow; } - inline bool allowClientUpdates() const { return _allowClientUpdates; } + SyncableObject(QObject *parent = 0); + SyncableObject(const QString &objectName, QObject *parent = 0); + SyncableObject(const SyncableObject &other, QObject *parent = 0); + ~SyncableObject(); + + //! Stores the object's state into a QVariantMap. + /** The default implementation takes dynamic properties as well as getters that have + * names starting with "init" and stores them in a QVariantMap. Override this method in + * derived classes in order to store the object state in a custom form. + * \note This is used by SignalProxy to transmit the state of the object to clients + * that request the initial object state. Later updates use a different mechanism + * and assume that the state is completely covered by properties and init* getters. + * DO NOT OVERRIDE THIS unless you know exactly what you do! + * + * \return The object's state in a QVariantMap + */ + virtual QVariantMap toVariantMap(); + + //! Initialize the object's state from a given QVariantMap. + /** \see toVariantMap() for important information concerning this method. + */ + virtual void fromVariantMap(const QVariantMap &properties); + + virtual bool isInitialized() const; + + virtual const QMetaObject *syncMetaObject() const { return metaObject(); }; + + inline void setAllowClientUpdates(bool allow) { _allowClientUpdates = allow; } + inline bool allowClientUpdates() const { return _allowClientUpdates; } public slots: - virtual void setInitialized(); - void requestUpdate(const QVariantMap &properties); - virtual void update(const QVariantMap &properties); + virtual void setInitialized(); + void requestUpdate(const QVariantMap &properties); + virtual void update(const QVariantMap &properties); protected: - void sync_call__(SignalProxy::ProxyMode modeType, const char *funcname, ...) const; + void sync_call__(SignalProxy::ProxyMode modeType, const char *funcname, ...) const; - void renameObject(const QString &newName); - SyncableObject &operator=(const SyncableObject &other); + void renameObject(const QString &newName); + SyncableObject &operator=(const SyncableObject &other); signals: - void initDone(); - void updatedRemotely(); - void updated(); + void initDone(); + void updatedRemotely(); + void updated(); private: - void synchronize(SignalProxy *proxy); - void stopSynchronize(SignalProxy *proxy); + void synchronize(SignalProxy *proxy); + void stopSynchronize(SignalProxy *proxy); - bool setInitValue(const QString &property, const QVariant &value); + bool setInitValue(const QString &property, const QVariant &value); - bool _initialized; - bool _allowClientUpdates; + bool _initialized; + bool _allowClientUpdates; - QList _signalProxies; + QList _signalProxies; - friend class SignalProxy; + friend class SignalProxy; }; + #endif diff --git a/src/common/types.h b/src/common/types.h index 9424ec8a..98847ff6 100644 --- a/src/common/types.h +++ b/src/common/types.h @@ -27,11 +27,12 @@ #include #include -class SignedId { - protected: +class SignedId +{ +protected: qint32 id; - public: +public: inline SignedId(int _id = 0) { id = _id; } inline qint32 toInt() const { return id; } inline bool isValid() const { return id > 0; } @@ -54,6 +55,7 @@ class SignedId { friend QDataStream &operator>>(QDataStream &in, SignedId &signedId); }; + inline QDataStream &operator<<(QDataStream &out, const SignedId &signedId) { out << signedId.toInt(); return out; } inline QDataStream &operator>>(QDataStream &in, SignedId &signedId) { in >> signedId.id; return in; } inline QTextStream &operator<<(QTextStream &out, const SignedId &signedId) { out << QString::number(signedId.toInt()); return out; } @@ -61,32 +63,32 @@ inline QDebug operator<<(QDebug dbg, const SignedId &signedId) { dbg.space() << inline uint qHash(const SignedId &id) { return qHash(id.toInt()); } struct UserId : public SignedId { - inline UserId(int _id = 0) : SignedId(_id) {} - //inline operator QVariant() const { return QVariant::fromValue(*this); } // no automatic conversion! + inline UserId(int _id = 0) : SignedId(_id) {} + //inline operator QVariant() const { return QVariant::fromValue(*this); } // no automatic conversion! }; struct MsgId : public SignedId { - inline MsgId(int _id = 0) : SignedId(_id) {} - //inline operator QVariant() const { return QVariant::fromValue(*this); } + inline MsgId(int _id = 0) : SignedId(_id) {} + //inline operator QVariant() const { return QVariant::fromValue(*this); } }; struct BufferId : public SignedId { - inline BufferId(int _id = 0) : SignedId(_id) {} - //inline operator QVariant() const { return QVariant::fromValue(*this); } + inline BufferId(int _id = 0) : SignedId(_id) {} + //inline operator QVariant() const { return QVariant::fromValue(*this); } }; struct NetworkId : public SignedId { - inline NetworkId(int _id = 0) : SignedId(_id) {} - //inline operator QVariant() const { return QVariant::fromValue(*this); } + inline NetworkId(int _id = 0) : SignedId(_id) {} + //inline operator QVariant() const { return QVariant::fromValue(*this); } }; struct IdentityId : public SignedId { - inline IdentityId(int _id = 0) : SignedId(_id) {} - //inline operator QVariant() const { return QVariant::fromValue(*this); } + inline IdentityId(int _id = 0) : SignedId(_id) {} + //inline operator QVariant() const { return QVariant::fromValue(*this); } }; struct AccountId : public SignedId { - inline AccountId(int _id = 0) : SignedId(_id) {} + inline AccountId(int _id = 0) : SignedId(_id) {} }; Q_DECLARE_METATYPE(UserId) @@ -104,11 +106,11 @@ typedef QList BufferIdList; //! Base class for exceptions. struct Exception { - Exception(QString msg = "Unknown Exception") : _msg(msg) {} - virtual ~Exception() {} // make gcc happy - virtual inline QString msg() { return _msg; } + Exception(QString msg = "Unknown Exception") : _msg(msg) {} + virtual ~Exception() {} // make gcc happy + virtual inline QString msg() { return _msg; } - protected: +protected: QString _msg; }; diff --git a/src/common/util.cpp b/src/common/util.cpp index a55946c3..0fdff636 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -29,119 +29,136 @@ class QMetaMethod; -QString nickFromMask(QString mask) { - return mask.section('!', 0, 0); +QString nickFromMask(QString mask) +{ + return mask.section('!', 0, 0); } -QString userFromMask(QString mask) { - QString userhost = mask.section('!', 1); - if(userhost.isEmpty()) return QString(); - return userhost.section('@', 0, 0); + +QString userFromMask(QString mask) +{ + QString userhost = mask.section('!', 1); + if (userhost.isEmpty()) return QString(); + return userhost.section('@', 0, 0); } -QString hostFromMask(QString mask) { - QString userhost = mask.section('!', 1); - if(userhost.isEmpty()) return QString(); - return userhost.section('@', 1); + +QString hostFromMask(QString mask) +{ + QString userhost = mask.section('!', 1); + if (userhost.isEmpty()) return QString(); + return userhost.section('@', 1); } -bool isChannelName(QString str) { - return QString("#&!+").contains(str[0]); + +bool isChannelName(QString str) +{ + return QString("#&!+").contains(str[0]); } -QString stripFormatCodes(QString str) { - str.remove(QRegExp("\x03(\\d\\d?(,\\d\\d?)?)?")); - str.remove('\x02'); - str.remove('\x0f'); - str.remove('\x12'); - str.remove('\x16'); - str.remove('\x1d'); - str.remove('\x1f'); - return str; + +QString stripFormatCodes(QString str) +{ + str.remove(QRegExp("\x03(\\d\\d?(,\\d\\d?)?)?")); + str.remove('\x02'); + str.remove('\x0f'); + str.remove('\x12'); + str.remove('\x16'); + str.remove('\x1d'); + str.remove('\x1f'); + return str; } -QString stripAcceleratorMarkers(const QString &label_) { - QString label = label_; - int p = 0; - forever { - p = label.indexOf('&', p); - if(p < 0 || p + 1 >= label.length()) - break; - if(label.at(p + 1).isLetterOrNumber() || label.at(p + 1) == '&') - label.remove(p, 1); +QString stripAcceleratorMarkers(const QString &label_) +{ + QString label = label_; + int p = 0; + forever { + p = label.indexOf('&', p); + if (p < 0 || p + 1 >= label.length()) + break; + + if (label.at(p + 1).isLetterOrNumber() || label.at(p + 1) == '&') + label.remove(p, 1); - ++p; - } - return label; + ++p; + } + return label; } -QString decodeString(const QByteArray &input, QTextCodec *codec) { - // First, we check if it's utf8. It is very improbable to encounter a string that looks like - // valid utf8, but in fact is not. This means that if the input string passes as valid utf8, it - // is safe to assume that it is. - // Q_ASSERT(sizeof(const char) == sizeof(quint8)); // In God we trust... - bool isUtf8 = true; - int cnt = 0; - for(int i = 0; i < input.size(); i++) { - if(cnt) { - // We check a part of a multibyte char. These need to be of the form 10yyyyyy. - if((input[i] & 0xc0) != 0x80) { isUtf8 = false; break; } - cnt--; - continue; + +QString decodeString(const QByteArray &input, QTextCodec *codec) +{ + // First, we check if it's utf8. It is very improbable to encounter a string that looks like + // valid utf8, but in fact is not. This means that if the input string passes as valid utf8, it + // is safe to assume that it is. + // Q_ASSERT(sizeof(const char) == sizeof(quint8)); // In God we trust... + bool isUtf8 = true; + int cnt = 0; + for (int i = 0; i < input.size(); i++) { + if (cnt) { + // We check a part of a multibyte char. These need to be of the form 10yyyyyy. + if ((input[i] & 0xc0) != 0x80) { isUtf8 = false; break; } + cnt--; + continue; + } + if ((input[i] & 0x80) == 0x00) continue; // 7 bit is always ok + if ((input[i] & 0xf8) == 0xf0) { cnt = 3; continue; } // 4-byte char 11110xxx 10yyyyyy 10zzzzzz 10vvvvvv + if ((input[i] & 0xf0) == 0xe0) { cnt = 2; continue; } // 3-byte char 1110xxxx 10yyyyyy 10zzzzzz + if ((input[i] & 0xe0) == 0xc0) { cnt = 1; continue; } // 2-byte char 110xxxxx 10yyyyyy + isUtf8 = false; break; // 8 bit char, but not utf8! + } + if (isUtf8 && cnt == 0) { + QString s = QString::fromUtf8(input); + //qDebug() << "Detected utf8:" << s; + return s; } - if((input[i] & 0x80) == 0x00) continue; // 7 bit is always ok - if((input[i] & 0xf8) == 0xf0) { cnt = 3; continue; } // 4-byte char 11110xxx 10yyyyyy 10zzzzzz 10vvvvvv - if((input[i] & 0xf0) == 0xe0) { cnt = 2; continue; } // 3-byte char 1110xxxx 10yyyyyy 10zzzzzz - if((input[i] & 0xe0) == 0xc0) { cnt = 1; continue; } // 2-byte char 110xxxxx 10yyyyyy - isUtf8 = false; break; // 8 bit char, but not utf8! - } - if(isUtf8 && cnt == 0) { - QString s = QString::fromUtf8(input); - //qDebug() << "Detected utf8:" << s; - return s; - } - //QTextCodec *codec = QTextCodec::codecForName(encoding.toAscii()); - if(!codec) return QString::fromAscii(input); - return codec->toUnicode(input); + //QTextCodec *codec = QTextCodec::codecForName(encoding.toAscii()); + if (!codec) return QString::fromAscii(input); + return codec->toUnicode(input); } -uint editingDistance(const QString &s1, const QString &s2) { - uint n = s1.size()+1; - uint m = s2.size()+1; - QVector< QVector< uint > >matrix(n,QVector(m,0)); - for(uint i = 0; i < n; i++) - matrix[i][0] = i; +uint editingDistance(const QString &s1, const QString &s2) +{ + uint n = s1.size()+1; + uint m = s2.size()+1; + QVector > matrix(n, QVector(m, 0)); + + for (uint i = 0; i < n; i++) + matrix[i][0] = i; - for(uint i = 0; i < m; i++) - matrix[0][i] = i; + for (uint i = 0; i < m; i++) + matrix[0][i] = i; - uint min; - for(uint i = 1; i < n; i++) { - for(uint j = 1; j < m; j++) { - uint deleteChar = matrix[i-1][j] + 1; - uint insertChar = matrix[i][j-1] + 1; + uint min; + for (uint i = 1; i < n; i++) { + for (uint j = 1; j < m; j++) { + uint deleteChar = matrix[i-1][j] + 1; + uint insertChar = matrix[i][j-1] + 1; - if(deleteChar < insertChar) - min = deleteChar; - else - min = insertChar; + if (deleteChar < insertChar) + min = deleteChar; + else + min = insertChar; - if(s1[i-1] == s2[j-1]) { - uint inheritChar = matrix[i-1][j-1]; - if(inheritChar < min) - min = inheritChar; - } + if (s1[i-1] == s2[j-1]) { + uint inheritChar = matrix[i-1][j-1]; + if (inheritChar < min) + min = inheritChar; + } - matrix[i][j] = min; + matrix[i][j] = min; + } } - } - return matrix[n-1][m-1]; + return matrix[n-1][m-1]; } -QString secondsToString(int timeInSeconds) { - QList< QPair > timeUnit; + +QString secondsToString(int timeInSeconds) +{ + QList > timeUnit; timeUnit.append(qMakePair(365*24*60*60, QCoreApplication::translate("Quassel::secondsToString()", "year"))); timeUnit.append(qMakePair(24*60*60, QCoreApplication::translate("Quassel::secondsToString()", "day"))); timeUnit.append(qMakePair(60*60, QCoreApplication::translate("Quassel::secondsToString()", "h"))); @@ -149,23 +166,25 @@ QString secondsToString(int timeInSeconds) { timeUnit.append(qMakePair(1, QCoreApplication::translate("Quassel::secondsToString()", "sec"))); QStringList returnString; - for(int i=0; i < timeUnit.size(); i++) { - int n = timeInSeconds / timeUnit[i].first; - if(n > 0) { - returnString += QString("%1 %2").arg(QString::number(n), timeUnit[i].second); - } - timeInSeconds = timeInSeconds % timeUnit[i].first; + for (int i = 0; i < timeUnit.size(); i++) { + int n = timeInSeconds / timeUnit[i].first; + if (n > 0) { + returnString += QString("%1 %2").arg(QString::number(n), timeUnit[i].second); + } + timeInSeconds = timeInSeconds % timeUnit[i].first; } return returnString.join(", "); } -QByteArray prettyDigest(const QByteArray &digest) { - QByteArray hexDigest = digest.toHex().toUpper(); - QByteArray prettyDigest; - prettyDigest.fill(':', hexDigest.count() + (hexDigest.count() / 2) - 1); - for(int i = 0; i * 2 < hexDigest.count(); i++) { - prettyDigest.replace(i * 3, 2, hexDigest.mid(i * 2, 2)); - } - return prettyDigest; +QByteArray prettyDigest(const QByteArray &digest) +{ + QByteArray hexDigest = digest.toHex().toUpper(); + QByteArray prettyDigest; + prettyDigest.fill(':', hexDigest.count() + (hexDigest.count() / 2) - 1); + + for (int i = 0; i * 2 < hexDigest.count(); i++) { + prettyDigest.replace(i * 3, 2, hexDigest.mid(i * 2, 2)); + } + return prettyDigest; } diff --git a/src/common/util.h b/src/common/util.h index d7bac87f..6311401b 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -26,7 +26,6 @@ #include #include - // TODO Use versions from Network instead QString nickFromMask(QString mask); QString userFromMask(QString mask); @@ -53,23 +52,27 @@ QString decodeString(const QByteArray &input, QTextCodec *codec = 0); uint editingDistance(const QString &s1, const QString &s2); template -QVariantList toVariantList(const QList &list) { - QVariantList variants; - for(int i = 0; i < list.count(); i++) { - variants << QVariant::fromValue(list[i]); - } - return variants; +QVariantList toVariantList(const QList &list) +{ + QVariantList variants; + for (int i = 0; i < list.count(); i++) { + variants << QVariant::fromValue(list[i]); + } + return variants; } + template -QList fromVariantList(const QVariantList &variants) { - QList list; - for(int i = 0; i < variants.count(); i++) { - list << variants[i].value(); - } - return list; +QList fromVariantList(const QVariantList &variants) +{ + QList list; + for (int i = 0; i < variants.count(); i++) { + list << variants[i].value(); + } + return list; } + QByteArray prettyDigest(const QByteArray &digest); #endif diff --git a/src/core/abstractsqlstorage.cpp b/src/core/abstractsqlstorage.cpp index 00c818fe..f588ef4e 100644 --- a/src/core/abstractsqlstorage.cpp +++ b/src/core/abstractsqlstorage.cpp @@ -31,346 +31,384 @@ int AbstractSqlStorage::_nextConnectionId = 0; AbstractSqlStorage::AbstractSqlStorage(QObject *parent) - : Storage(parent), + : Storage(parent), _schemaVersion(0) { } -AbstractSqlStorage::~AbstractSqlStorage() { - // disconnect the connections, so their deletion is no longer interessting for us - QHash::iterator conIter; - for(conIter = _connectionPool.begin(); conIter != _connectionPool.end(); conIter++) { - QSqlDatabase::removeDatabase(conIter.value()->name()); - disconnect(conIter.value(), 0, this, 0); - } + +AbstractSqlStorage::~AbstractSqlStorage() +{ + // disconnect the connections, so their deletion is no longer interessting for us + QHash::iterator conIter; + for (conIter = _connectionPool.begin(); conIter != _connectionPool.end(); conIter++) { + QSqlDatabase::removeDatabase(conIter.value()->name()); + disconnect(conIter.value(), 0, this, 0); + } } -QSqlDatabase AbstractSqlStorage::logDb() { - if(!_connectionPool.contains(QThread::currentThread())) - addConnectionToPool(); - return QSqlDatabase::database(_connectionPool[QThread::currentThread()]->name()); +QSqlDatabase AbstractSqlStorage::logDb() +{ + if (!_connectionPool.contains(QThread::currentThread())) + addConnectionToPool(); + + return QSqlDatabase::database(_connectionPool[QThread::currentThread()]->name()); } -void AbstractSqlStorage::addConnectionToPool() { - QMutexLocker locker(&_connectionPoolMutex); - // we have to recheck if the connection pool already contains a connection for - // this thread. Since now (after the lock) we can only tell for sure - if(_connectionPool.contains(QThread::currentThread())) - return; - QThread *currentThread = QThread::currentThread(); +void AbstractSqlStorage::addConnectionToPool() +{ + QMutexLocker locker(&_connectionPoolMutex); + // we have to recheck if the connection pool already contains a connection for + // this thread. Since now (after the lock) we can only tell for sure + if (_connectionPool.contains(QThread::currentThread())) + return; - int connectionId = _nextConnectionId++; + QThread *currentThread = QThread::currentThread(); - Connection *connection = new Connection(QLatin1String(QString("quassel_%1_con_%2").arg(driverName()).arg(connectionId).toLatin1())); - connection->moveToThread(currentThread); - connect(this, SIGNAL(destroyed()), connection, SLOT(deleteLater())); - connect(currentThread, SIGNAL(destroyed()), connection, SLOT(deleteLater())); - connect(connection, SIGNAL(destroyed()), this, SLOT(connectionDestroyed())); - _connectionPool[currentThread] = connection; + int connectionId = _nextConnectionId++; - QSqlDatabase db = QSqlDatabase::addDatabase(driverName(), connection->name()); - db.setDatabaseName(databaseName()); + Connection *connection = new Connection(QLatin1String(QString("quassel_%1_con_%2").arg(driverName()).arg(connectionId).toLatin1())); + connection->moveToThread(currentThread); + connect(this, SIGNAL(destroyed()), connection, SLOT(deleteLater())); + connect(currentThread, SIGNAL(destroyed()), connection, SLOT(deleteLater())); + connect(connection, SIGNAL(destroyed()), this, SLOT(connectionDestroyed())); + _connectionPool[currentThread] = connection; - if(!hostName().isEmpty()) - db.setHostName(hostName()); + QSqlDatabase db = QSqlDatabase::addDatabase(driverName(), connection->name()); + db.setDatabaseName(databaseName()); - if(port() != -1) - db.setPort(port()); + if (!hostName().isEmpty()) + db.setHostName(hostName()); - if(!userName().isEmpty()) { - db.setUserName(userName()); - db.setPassword(password()); - } + if (port() != -1) + db.setPort(port()); - if(!db.open()) { - qWarning() << "Unable to open database" << displayName() << "for thread" << QThread::currentThread(); - qWarning() << "-" << db.lastError().text(); - } else { - initDbSession(db); - } + if (!userName().isEmpty()) { + db.setUserName(userName()); + db.setPassword(password()); + } + + if (!db.open()) { + qWarning() << "Unable to open database" << displayName() << "for thread" << QThread::currentThread(); + qWarning() << "-" << db.lastError().text(); + } + else { + initDbSession(db); + } } -Storage::State AbstractSqlStorage::init(const QVariantMap &settings) { - setConnectionProperties(settings); - _debug = Quassel::isOptionSet("debug"); +Storage::State AbstractSqlStorage::init(const QVariantMap &settings) +{ + setConnectionProperties(settings); - QSqlDatabase db = logDb(); - if(!db.isValid() || !db.isOpen()) - return NotAvailable; + _debug = Quassel::isOptionSet("debug"); - if(installedSchemaVersion() == -1) { - qCritical() << "Storage Schema is missing!"; - return NeedsSetup; - } + QSqlDatabase db = logDb(); + if (!db.isValid() || !db.isOpen()) + return NotAvailable; - if(installedSchemaVersion() > schemaVersion()) { - qCritical() << "Installed Schema is newer then any known Version."; - return NotAvailable; - } + if (installedSchemaVersion() == -1) { + qCritical() << "Storage Schema is missing!"; + return NeedsSetup; + } - if(installedSchemaVersion() < schemaVersion()) { - qWarning() << qPrintable(tr("Installed Schema (version %1) is not up to date. Upgrading to version %2...").arg(installedSchemaVersion()).arg(schemaVersion())); - if(!upgradeDb()) { - qWarning() << qPrintable(tr("Upgrade failed...")); - return NotAvailable; + if (installedSchemaVersion() > schemaVersion()) { + qCritical() << "Installed Schema is newer then any known Version."; + return NotAvailable; } - } - quInfo() << qPrintable(displayName()) << "Storage Backend is ready. Quassel Schema Version:" << installedSchemaVersion(); - return IsReady; + if (installedSchemaVersion() < schemaVersion()) { + qWarning() << qPrintable(tr("Installed Schema (version %1) is not up to date. Upgrading to version %2...").arg(installedSchemaVersion()).arg(schemaVersion())); + if (!upgradeDb()) { + qWarning() << qPrintable(tr("Upgrade failed...")); + return NotAvailable; + } + } + + quInfo() << qPrintable(displayName()) << "Storage Backend is ready. Quassel Schema Version:" << installedSchemaVersion(); + return IsReady; } -QString AbstractSqlStorage::queryString(const QString &queryName, int version) { - if(version == 0) - version = schemaVersion(); - QFileInfo queryInfo(QString(":/SQL/%1/%2/%3.sql").arg(displayName()).arg(version).arg(queryName)); - if(!queryInfo.exists() || !queryInfo.isFile() || !queryInfo.isReadable()) { - qCritical() << "Unable to read SQL-Query" << queryName << "for engine" << displayName(); - return QString(); - } +QString AbstractSqlStorage::queryString(const QString &queryName, int version) +{ + if (version == 0) + version = schemaVersion(); - QFile queryFile(queryInfo.filePath()); - if(!queryFile.open(QIODevice::ReadOnly | QIODevice::Text)) - return QString(); - QString query = QTextStream(&queryFile).readAll(); - queryFile.close(); + QFileInfo queryInfo(QString(":/SQL/%1/%2/%3.sql").arg(displayName()).arg(version).arg(queryName)); + if (!queryInfo.exists() || !queryInfo.isFile() || !queryInfo.isReadable()) { + qCritical() << "Unable to read SQL-Query" << queryName << "for engine" << displayName(); + return QString(); + } - return query.trimmed(); -} + QFile queryFile(queryInfo.filePath()); + if (!queryFile.open(QIODevice::ReadOnly | QIODevice::Text)) + return QString(); + QString query = QTextStream(&queryFile).readAll(); + queryFile.close(); -QStringList AbstractSqlStorage::setupQueries() { - QStringList queries; - QDir dir = QDir(QString(":/SQL/%1/%2/").arg(displayName()).arg(schemaVersion())); - foreach(QFileInfo fileInfo, dir.entryInfoList(QStringList() << "setup*", QDir::NoFilter, QDir::Name)) { - queries << queryString(fileInfo.baseName()); - } - return queries; + return query.trimmed(); } -bool AbstractSqlStorage::setup(const QVariantMap &settings) { - setConnectionProperties(settings); - QSqlDatabase db = logDb(); - if(!db.isOpen()) { - qCritical() << "Unable to setup Logging Backend!"; - return false; - } - - db.transaction(); - foreach(QString queryString, setupQueries()) { - QSqlQuery query = db.exec(queryString); - if(!watchQuery(query)) { - qCritical() << "Unable to setup Logging Backend!"; - db.rollback(); - return false; + +QStringList AbstractSqlStorage::setupQueries() +{ + QStringList queries; + QDir dir = QDir(QString(":/SQL/%1/%2/").arg(displayName()).arg(schemaVersion())); + foreach(QFileInfo fileInfo, dir.entryInfoList(QStringList() << "setup*", QDir::NoFilter, QDir::Name)) { + queries << queryString(fileInfo.baseName()); } - } - bool success = setupSchemaVersion(schemaVersion()); - if(success) - db.commit(); - else - db.rollback(); - return success; + return queries; } -QStringList AbstractSqlStorage::upgradeQueries(int version) { - QStringList queries; - QDir dir = QDir(QString(":/SQL/%1/%2/").arg(displayName()).arg(version)); - foreach(QFileInfo fileInfo, dir.entryInfoList(QStringList() << "upgrade*", QDir::NoFilter, QDir::Name)) { - queries << queryString(fileInfo.baseName(), version); - } - return queries; + +bool AbstractSqlStorage::setup(const QVariantMap &settings) +{ + setConnectionProperties(settings); + QSqlDatabase db = logDb(); + if (!db.isOpen()) { + qCritical() << "Unable to setup Logging Backend!"; + return false; + } + + db.transaction(); + foreach(QString queryString, setupQueries()) { + QSqlQuery query = db.exec(queryString); + if (!watchQuery(query)) { + qCritical() << "Unable to setup Logging Backend!"; + db.rollback(); + return false; + } + } + bool success = setupSchemaVersion(schemaVersion()); + if (success) + db.commit(); + else + db.rollback(); + return success; } -bool AbstractSqlStorage::upgradeDb() { - if(schemaVersion() <= installedSchemaVersion()) - return true; - QSqlDatabase db = logDb(); +QStringList AbstractSqlStorage::upgradeQueries(int version) +{ + QStringList queries; + QDir dir = QDir(QString(":/SQL/%1/%2/").arg(displayName()).arg(version)); + foreach(QFileInfo fileInfo, dir.entryInfoList(QStringList() << "upgrade*", QDir::NoFilter, QDir::Name)) { + queries << queryString(fileInfo.baseName(), version); + } + return queries; +} + - for(int ver = installedSchemaVersion() + 1; ver <= schemaVersion(); ver++) { - foreach(QString queryString, upgradeQueries(ver)) { - QSqlQuery query = db.exec(queryString); - if(!watchQuery(query)) { - qCritical() << "Unable to upgrade Logging Backend!"; - return false; - } +bool AbstractSqlStorage::upgradeDb() +{ + if (schemaVersion() <= installedSchemaVersion()) + return true; + + QSqlDatabase db = logDb(); + + for (int ver = installedSchemaVersion() + 1; ver <= schemaVersion(); ver++) { + foreach(QString queryString, upgradeQueries(ver)) { + QSqlQuery query = db.exec(queryString); + if (!watchQuery(query)) { + qCritical() << "Unable to upgrade Logging Backend!"; + return false; + } + } } - } - return updateSchemaVersion(schemaVersion()); + return updateSchemaVersion(schemaVersion()); } -int AbstractSqlStorage::schemaVersion() { - // returns the newest Schema Version! - // not the currently used one! (though it can be the same) - if(_schemaVersion > 0) +int AbstractSqlStorage::schemaVersion() +{ + // returns the newest Schema Version! + // not the currently used one! (though it can be the same) + if (_schemaVersion > 0) + return _schemaVersion; + + int version; + bool ok; + QDir dir = QDir(":/SQL/" + displayName()); + foreach(QFileInfo fileInfo, dir.entryInfoList()) { + if (!fileInfo.isDir()) + continue; + + version = fileInfo.fileName().toInt(&ok); + if (!ok) + continue; + + if (version > _schemaVersion) + _schemaVersion = version; + } return _schemaVersion; - - int version; - bool ok; - QDir dir = QDir(":/SQL/" + displayName()); - foreach(QFileInfo fileInfo, dir.entryInfoList()) { - if(!fileInfo.isDir()) - continue; - - version = fileInfo.fileName().toInt(&ok); - if(!ok) - continue; - - if(version > _schemaVersion) - _schemaVersion = version; - } - return _schemaVersion; } -bool AbstractSqlStorage::watchQuery(QSqlQuery &query) { - bool queryError = query.lastError().isValid(); - if(queryError || _debug) { - if(queryError) - qCritical() << "unhandled Error in QSqlQuery!"; - qCritical() << " last Query:\n" << qPrintable(query.lastQuery()); - qCritical() << " executed Query:\n" << qPrintable(query.executedQuery()); - QVariantMap boundValues = query.boundValues(); - QStringList valueStrings; - QVariantMap::const_iterator iter; - for(iter = boundValues.constBegin(); iter != boundValues.constEnd(); iter++) { - QString value; - QSqlField field; - if(query.driver()) { - // let the driver do the formatting - field.setType(iter.value().type()); - if(iter.value().isNull()) - field.clear(); - else - field.setValue(iter.value()); - value = query.driver()->formatValue(field); - } else { - switch(iter.value().type()) { - case QVariant::Invalid: - value = "NULL"; - break; - case QVariant::Int: - value = iter.value().toString(); - break; - default: - value = QString("'%1'").arg(iter.value().toString()); - } - } - valueStrings << QString("%1=%2").arg(iter.key(), value); + +bool AbstractSqlStorage::watchQuery(QSqlQuery &query) +{ + bool queryError = query.lastError().isValid(); + if (queryError || _debug) { + if (queryError) + qCritical() << "unhandled Error in QSqlQuery!"; + qCritical() << " last Query:\n" << qPrintable(query.lastQuery()); + qCritical() << " executed Query:\n" << qPrintable(query.executedQuery()); + QVariantMap boundValues = query.boundValues(); + QStringList valueStrings; + QVariantMap::const_iterator iter; + for (iter = boundValues.constBegin(); iter != boundValues.constEnd(); iter++) { + QString value; + QSqlField field; + if (query.driver()) { + // let the driver do the formatting + field.setType(iter.value().type()); + if (iter.value().isNull()) + field.clear(); + else + field.setValue(iter.value()); + value = query.driver()->formatValue(field); + } + else { + switch (iter.value().type()) { + case QVariant::Invalid: + value = "NULL"; + break; + case QVariant::Int: + value = iter.value().toString(); + break; + default: + value = QString("'%1'").arg(iter.value().toString()); + } + } + valueStrings << QString("%1=%2").arg(iter.key(), value); + } + qCritical() << " bound Values:" << qPrintable(valueStrings.join(", ")); + qCritical() << " Error Number:" << query.lastError().number(); + qCritical() << " Error Message:" << qPrintable(query.lastError().text()); + qCritical() << " Driver Message:" << qPrintable(query.lastError().driverText()); + qCritical() << " DB Message:" << qPrintable(query.lastError().databaseText()); + + return !queryError; } - qCritical() << " bound Values:" << qPrintable(valueStrings.join(", ")); - qCritical() << " Error Number:" << query.lastError().number(); - qCritical() << " Error Message:" << qPrintable(query.lastError().text()); - qCritical() << " Driver Message:" << qPrintable(query.lastError().driverText()); - qCritical() << " DB Message:" << qPrintable(query.lastError().databaseText()); - - return !queryError; - } - return true; + return true; } -void AbstractSqlStorage::connectionDestroyed() { - QMutexLocker locker(&_connectionPoolMutex); - _connectionPool.remove(sender()->thread()); + +void AbstractSqlStorage::connectionDestroyed() +{ + QMutexLocker locker(&_connectionPoolMutex); + _connectionPool.remove(sender()->thread()); } + // ======================================== // AbstractSqlStorage::Connection // ======================================== AbstractSqlStorage::Connection::Connection(const QString &name, QObject *parent) - : QObject(parent), + : QObject(parent), _name(name.toLatin1()) { } -AbstractSqlStorage::Connection::~Connection() { - { - QSqlDatabase db = QSqlDatabase::database(name(), false); - if(db.isOpen()) { - db.commit(); - db.close(); + +AbstractSqlStorage::Connection::~Connection() +{ + { + QSqlDatabase db = QSqlDatabase::database(name(), false); + if (db.isOpen()) { + db.commit(); + db.close(); + } } - } - QSqlDatabase::removeDatabase(name()); + QSqlDatabase::removeDatabase(name()); } - - // ======================================== // AbstractSqlMigrator // ======================================== AbstractSqlMigrator::AbstractSqlMigrator() - : _query(0) + : _query(0) { } -void AbstractSqlMigrator::newQuery(const QString &query, QSqlDatabase db) { - Q_ASSERT(!_query); - _query = new QSqlQuery(db); - _query->prepare(query); + +void AbstractSqlMigrator::newQuery(const QString &query, QSqlDatabase db) +{ + Q_ASSERT(!_query); + _query = new QSqlQuery(db); + _query->prepare(query); } -void AbstractSqlMigrator::resetQuery() { - delete _query; - _query = 0; + +void AbstractSqlMigrator::resetQuery() +{ + delete _query; + _query = 0; } -bool AbstractSqlMigrator::exec() { - Q_ASSERT(_query); - _query->exec(); - return !_query->lastError().isValid(); + +bool AbstractSqlMigrator::exec() +{ + Q_ASSERT(_query); + _query->exec(); + return !_query->lastError().isValid(); } -QString AbstractSqlMigrator::migrationObject(MigrationObject moType) { - switch(moType) { - case QuasselUser: - return "QuasselUser"; - case Sender: - return "Sender"; - case Identity: - return "Identity"; - case IdentityNick: - return "IdentityNick"; - case Network: - return "Network"; - case Buffer: - return "Buffer"; - case Backlog: - return "Backlog"; - case IrcServer: - return "IrcServer"; - case UserSetting: - return "UserSetting"; - }; - return QString(); + +QString AbstractSqlMigrator::migrationObject(MigrationObject moType) +{ + switch (moType) { + case QuasselUser: + return "QuasselUser"; + case Sender: + return "Sender"; + case Identity: + return "Identity"; + case IdentityNick: + return "IdentityNick"; + case Network: + return "Network"; + case Buffer: + return "Buffer"; + case Backlog: + return "Backlog"; + case IrcServer: + return "IrcServer"; + case UserSetting: + return "UserSetting"; + }; + return QString(); } -QVariantList AbstractSqlMigrator::boundValues() { - QVariantList values; - if(!_query) - return values; - int numValues = _query->boundValues().count(); - for(int i = 0; i < numValues; i++) { - values << _query->boundValue(i); - } - return values; +QVariantList AbstractSqlMigrator::boundValues() +{ + QVariantList values; + if (!_query) + return values; + + int numValues = _query->boundValues().count(); + for (int i = 0; i < numValues; i++) { + values << _query->boundValue(i); + } + return values; } -void AbstractSqlMigrator::dumpStatus() { - qWarning() << " executed Query:"; - qWarning() << qPrintable(executedQuery()); - qWarning() << " bound Values:"; - QList list = boundValues(); - for (int i = 0; i < list.size(); ++i) - qWarning() << i << ": " << list.at(i).toString().toAscii().data(); - qWarning() << " Error Number:" << lastError().number(); - qWarning() << " Error Message:" << lastError().text(); + +void AbstractSqlMigrator::dumpStatus() +{ + qWarning() << " executed Query:"; + qWarning() << qPrintable(executedQuery()); + qWarning() << " bound Values:"; + QList list = boundValues(); + for (int i = 0; i < list.size(); ++i) + qWarning() << i << ": " << list.at(i).toString().toAscii().data(); + qWarning() << " Error Number:" << lastError().number(); + qWarning() << " Error Message:" << lastError().text(); } @@ -378,136 +416,142 @@ void AbstractSqlMigrator::dumpStatus() { // AbstractSqlMigrationReader // ======================================== AbstractSqlMigrationReader::AbstractSqlMigrationReader() - : AbstractSqlMigrator(), + : AbstractSqlMigrator(), _writer(0) { } -bool AbstractSqlMigrationReader::migrateTo(AbstractSqlMigrationWriter *writer) { - if(!transaction()) { - qWarning() << "AbstractSqlMigrationReader::migrateTo(): unable to start reader's transaction!"; - return false; - } - if(!writer->transaction()) { - qWarning() << "AbstractSqlMigrationReader::migrateTo(): unable to start writer's transaction!"; - rollback(); // close the reader transaction; - return false; - } - - _writer = writer; - - // due to the incompatibility across Migration objects we can't run this in a loop... :/ - QuasselUserMO quasselUserMo; - if(!transferMo(QuasselUser, quasselUserMo)) - return false; - - IdentityMO identityMo; - if(!transferMo(Identity, identityMo)) - return false; - - IdentityNickMO identityNickMo; - if(!transferMo(IdentityNick, identityNickMo)) - return false; - - NetworkMO networkMo; - if(!transferMo(Network, networkMo)) - return false; - - BufferMO bufferMo; - if(!transferMo(Buffer, bufferMo)) - return false; - - SenderMO senderMo; - if(!transferMo(Sender, senderMo)) - return false; - - BacklogMO backlogMo; - if(!transferMo(Backlog, backlogMo)) - return false; - - IrcServerMO ircServerMo; - if(!transferMo(IrcServer, ircServerMo)) - return false; - - UserSettingMO userSettingMo; - if(!transferMo(UserSetting, userSettingMo)) - return false; - - if(!_writer->postProcess()) - abortMigration(); - return finalizeMigration(); + +bool AbstractSqlMigrationReader::migrateTo(AbstractSqlMigrationWriter *writer) +{ + if (!transaction()) { + qWarning() << "AbstractSqlMigrationReader::migrateTo(): unable to start reader's transaction!"; + return false; + } + if (!writer->transaction()) { + qWarning() << "AbstractSqlMigrationReader::migrateTo(): unable to start writer's transaction!"; + rollback(); // close the reader transaction; + return false; + } + + _writer = writer; + + // due to the incompatibility across Migration objects we can't run this in a loop... :/ + QuasselUserMO quasselUserMo; + if (!transferMo(QuasselUser, quasselUserMo)) + return false; + + IdentityMO identityMo; + if (!transferMo(Identity, identityMo)) + return false; + + IdentityNickMO identityNickMo; + if (!transferMo(IdentityNick, identityNickMo)) + return false; + + NetworkMO networkMo; + if (!transferMo(Network, networkMo)) + return false; + + BufferMO bufferMo; + if (!transferMo(Buffer, bufferMo)) + return false; + + SenderMO senderMo; + if (!transferMo(Sender, senderMo)) + return false; + + BacklogMO backlogMo; + if (!transferMo(Backlog, backlogMo)) + return false; + + IrcServerMO ircServerMo; + if (!transferMo(IrcServer, ircServerMo)) + return false; + + UserSettingMO userSettingMo; + if (!transferMo(UserSetting, userSettingMo)) + return false; + + if (!_writer->postProcess()) + abortMigration(); + return finalizeMigration(); } -void AbstractSqlMigrationReader::abortMigration(const QString &errorMsg) { - qWarning() << "Migration Failed!"; - if(!errorMsg.isNull()) { - qWarning() << qPrintable(errorMsg); - } - if(lastError().isValid()) { - qWarning() << "ReaderError:"; - dumpStatus(); - } - - - if(_writer->lastError().isValid()) { - qWarning() << "WriterError:"; - _writer->dumpStatus(); - } - - rollback(); - _writer->rollback(); - _writer = 0; + +void AbstractSqlMigrationReader::abortMigration(const QString &errorMsg) +{ + qWarning() << "Migration Failed!"; + if (!errorMsg.isNull()) { + qWarning() << qPrintable(errorMsg); + } + if (lastError().isValid()) { + qWarning() << "ReaderError:"; + dumpStatus(); + } + + if (_writer->lastError().isValid()) { + qWarning() << "WriterError:"; + _writer->dumpStatus(); + } + + rollback(); + _writer->rollback(); + _writer = 0; } -bool AbstractSqlMigrationReader::finalizeMigration() { - resetQuery(); - _writer->resetQuery(); - commit(); - if(!_writer->commit()) { +bool AbstractSqlMigrationReader::finalizeMigration() +{ + resetQuery(); + _writer->resetQuery(); + + commit(); + if (!_writer->commit()) { + _writer = 0; + return false; + } _writer = 0; - return false; - } - _writer = 0; - return true; + return true; } + template -bool AbstractSqlMigrationReader::transferMo(MigrationObject moType, T &mo) { - resetQuery(); - _writer->resetQuery(); - - if(!prepareQuery(moType)) { - abortMigration(QString("AbstractSqlMigrationReader::migrateTo(): unable to prepare reader query of type %1!").arg(AbstractSqlMigrator::migrationObject(moType))); - return false; - } - if(!_writer->prepareQuery(moType)) { - abortMigration(QString("AbstractSqlMigrationReader::migrateTo(): unable to prepare writer query of type %1!").arg(AbstractSqlMigrator::migrationObject(moType))); - return false; - } - - qDebug() << qPrintable(QString("Transferring %1...").arg(AbstractSqlMigrator::migrationObject(moType))); - int i = 0; - QFile file; - file.open(stdout, QIODevice::WriteOnly); - - while(readMo(mo)) { - if(!_writer->writeMo(mo)) { - abortMigration(QString("AbstractSqlMigrationReader::transferMo(): unable to transfer Migratable Object of type %1!").arg(AbstractSqlMigrator::migrationObject(moType))); - return false; +bool AbstractSqlMigrationReader::transferMo(MigrationObject moType, T &mo) +{ + resetQuery(); + _writer->resetQuery(); + + if (!prepareQuery(moType)) { + abortMigration(QString("AbstractSqlMigrationReader::migrateTo(): unable to prepare reader query of type %1!").arg(AbstractSqlMigrator::migrationObject(moType))); + return false; } - i++; - if(i % 1000 == 0) { - file.write("*"); - file.flush(); + if (!_writer->prepareQuery(moType)) { + abortMigration(QString("AbstractSqlMigrationReader::migrateTo(): unable to prepare writer query of type %1!").arg(AbstractSqlMigrator::migrationObject(moType))); + return false; + } + + qDebug() << qPrintable(QString("Transferring %1...").arg(AbstractSqlMigrator::migrationObject(moType))); + int i = 0; + QFile file; + file.open(stdout, QIODevice::WriteOnly); + + while (readMo(mo)) { + if (!_writer->writeMo(mo)) { + abortMigration(QString("AbstractSqlMigrationReader::transferMo(): unable to transfer Migratable Object of type %1!").arg(AbstractSqlMigrator::migrationObject(moType))); + return false; + } + i++; + if (i % 1000 == 0) { + file.write("*"); + file.flush(); + } + } + if (i > 1000) { + file.write("\n"); + file.flush(); } - } - if(i > 1000) { - file.write("\n"); - file.flush(); - } - - qDebug() << "Done."; - return true; -} + qDebug() << "Done."; + return true; +} diff --git a/src/core/abstractsqlstorage.h b/src/core/abstractsqlstorage.h index d0046a9f..d821e614 100644 --- a/src/core/abstractsqlstorage.h +++ b/src/core/abstractsqlstorage.h @@ -30,298 +30,306 @@ class AbstractSqlMigrationReader; class AbstractSqlMigrationWriter; -class AbstractSqlStorage : public Storage { - Q_OBJECT +class AbstractSqlStorage : public Storage +{ + Q_OBJECT public: - AbstractSqlStorage(QObject *parent = 0); - virtual ~AbstractSqlStorage(); + AbstractSqlStorage(QObject *parent = 0); + virtual ~AbstractSqlStorage(); - virtual inline AbstractSqlMigrationReader *createMigrationReader() { return 0; } - virtual inline AbstractSqlMigrationWriter *createMigrationWriter() { return 0; } + virtual inline AbstractSqlMigrationReader *createMigrationReader() { return 0; } + virtual inline AbstractSqlMigrationWriter *createMigrationWriter() { return 0; } public slots: - virtual State init(const QVariantMap &settings = QVariantMap()); - virtual bool setup(const QVariantMap &settings = QVariantMap()); + virtual State init(const QVariantMap &settings = QVariantMap()); + virtual bool setup(const QVariantMap &settings = QVariantMap()); protected: - inline virtual void sync() {}; + inline virtual void sync() {}; - QSqlDatabase logDb(); + QSqlDatabase logDb(); - QString queryString(const QString &queryName, int version); - inline QString queryString(const QString &queryName) { return queryString(queryName, 0); } + QString queryString(const QString &queryName, int version); + inline QString queryString(const QString &queryName) { return queryString(queryName, 0); } - QStringList setupQueries(); + QStringList setupQueries(); - QStringList upgradeQueries(int ver); - bool upgradeDb(); + QStringList upgradeQueries(int ver); + bool upgradeDb(); - bool watchQuery(QSqlQuery &query); + bool watchQuery(QSqlQuery &query); - int schemaVersion(); - virtual int installedSchemaVersion() { return -1; }; - virtual bool updateSchemaVersion(int newVersion) = 0; - virtual bool setupSchemaVersion(int version) = 0; + int schemaVersion(); + virtual int installedSchemaVersion() { return -1; }; + virtual bool updateSchemaVersion(int newVersion) = 0; + virtual bool setupSchemaVersion(int version) = 0; - virtual void setConnectionProperties(const QVariantMap &properties) = 0; - virtual QString driverName() = 0; - inline virtual QString hostName() { return QString(); } - inline virtual int port() { return -1; } - virtual QString databaseName() = 0; - inline virtual QString userName() { return QString(); } - inline virtual QString password() { return QString(); } + virtual void setConnectionProperties(const QVariantMap &properties) = 0; + virtual QString driverName() = 0; + inline virtual QString hostName() { return QString(); } + inline virtual int port() { return -1; } + virtual QString databaseName() = 0; + inline virtual QString userName() { return QString(); } + inline virtual QString password() { return QString(); } - - //! Initialize db specific features on connect - /** This is called every time a connection to a specific SQL backend is established - * the default implementation does nothing. - * - * When reimplementing this method, don't use logDB() inside this function as - * this would cause as we're just about to initialize that DB connection. - */ - inline virtual void initDbSession(QSqlDatabase & /* db */) {} + //! Initialize db specific features on connect + /** This is called every time a connection to a specific SQL backend is established + * the default implementation does nothing. + * + * When reimplementing this method, don't use logDB() inside this function as + * this would cause as we're just about to initialize that DB connection. + */ + inline virtual void initDbSession(QSqlDatabase & /* db */) {} private slots: - void connectionDestroyed(); + void connectionDestroyed(); private: - void addConnectionToPool(); - - int _schemaVersion; - bool _debug; - - static int _nextConnectionId; - QMutex _connectionPoolMutex; - // we let a Connection Object manage each actual db connection - // those objects reside in the thread the connection belongs to - // which allows us thread safe termination of a connection - class Connection; - QHash _connectionPool; + void addConnectionToPool(); + + int _schemaVersion; + bool _debug; + + static int _nextConnectionId; + QMutex _connectionPoolMutex; + // we let a Connection Object manage each actual db connection + // those objects reside in the thread the connection belongs to + // which allows us thread safe termination of a connection + class Connection; + QHash _connectionPool; }; + // ======================================== // AbstractSqlStorage::Connection // ======================================== -class AbstractSqlStorage::Connection : public QObject { - Q_OBJECT +class AbstractSqlStorage::Connection : public QObject +{ + Q_OBJECT public: - Connection(const QString &name, QObject *parent = 0); - ~Connection(); + Connection(const QString &name, QObject *parent = 0); + ~Connection(); - inline QLatin1String name() const { return QLatin1String(_name); } + inline QLatin1String name() const { return QLatin1String(_name); } private: - QByteArray _name; + QByteArray _name; }; // ======================================== // AbstractSqlMigrator // ======================================== -class AbstractSqlMigrator { +class AbstractSqlMigrator +{ public: - // migration objects - struct QuasselUserMO { - UserId id; - QString username; - QString password; - }; - - struct SenderMO { - int senderId; - QString sender; - SenderMO() : senderId(0) {} - }; - - struct IdentityMO { - IdentityId id; - UserId userid; - QString identityname; - QString realname; - QString awayNick; - bool awayNickEnabled; - QString awayReason; - bool awayReasonEnabled; - bool autoAwayEnabled; - int autoAwayTime; - QString autoAwayReason; - bool autoAwayReasonEnabled; - bool detachAwayEnabled; - QString detachAwayReason; - bool detchAwayReasonEnabled; - QString ident; - QString kickReason; - QString partReason; - QString quitReason; - QByteArray sslCert; - QByteArray sslKey; - }; - - struct IdentityNickMO { - int nickid; - IdentityId identityId; - QString nick; - }; - - struct NetworkMO { - NetworkId networkid; - UserId userid; - QString networkname; - IdentityId identityid; - QString encodingcodec; - QString decodingcodec; - QString servercodec; - bool userandomserver; - QString perform; - bool useautoidentify; - QString autoidentifyservice; - QString autoidentifypassword; - bool useautoreconnect; - int autoreconnectinterval; - int autoreconnectretries; - bool unlimitedconnectretries; - bool rejoinchannels; - bool connected; - QString usermode; - QString awaymessage; - QString attachperform; - QString detachperform; - bool usesasl; - QString saslaccount; - QString saslpassword; - }; - - struct BufferMO { - BufferId bufferid; - UserId userid; - int groupid; - NetworkId networkid; - QString buffername; - QString buffercname; - int buffertype; - int lastseenmsgid; - int markerlinemsgid; - QString key; - bool joined; - }; - - struct BacklogMO { - MsgId messageid; - QDateTime time; // has to be in UTC! - BufferId bufferid; - int type; - int flags; - int senderid; - QString message; - }; - - struct IrcServerMO { - int serverid; - UserId userid; - NetworkId networkid; - QString hostname; - int port; - QString password; - bool ssl; - int sslversion; - bool useproxy; - int proxytype; - QString proxyhost; - int proxyport; - QString proxyuser; - QString proxypass; - }; - - struct UserSettingMO { - UserId userid; - QString settingname; - QByteArray settingvalue; - }; - - enum MigrationObject { - QuasselUser, - Sender, - Identity, - IdentityNick, - Network, - Buffer, - Backlog, - IrcServer, - UserSetting - }; - - AbstractSqlMigrator(); - virtual ~AbstractSqlMigrator() {} - - static QString migrationObject(MigrationObject moType); + // migration objects + struct QuasselUserMO { + UserId id; + QString username; + QString password; + }; + + struct SenderMO { + int senderId; + QString sender; + SenderMO() : senderId(0) {} + }; + + struct IdentityMO { + IdentityId id; + UserId userid; + QString identityname; + QString realname; + QString awayNick; + bool awayNickEnabled; + QString awayReason; + bool awayReasonEnabled; + bool autoAwayEnabled; + int autoAwayTime; + QString autoAwayReason; + bool autoAwayReasonEnabled; + bool detachAwayEnabled; + QString detachAwayReason; + bool detchAwayReasonEnabled; + QString ident; + QString kickReason; + QString partReason; + QString quitReason; + QByteArray sslCert; + QByteArray sslKey; + }; + + struct IdentityNickMO { + int nickid; + IdentityId identityId; + QString nick; + }; + + struct NetworkMO { + NetworkId networkid; + UserId userid; + QString networkname; + IdentityId identityid; + QString encodingcodec; + QString decodingcodec; + QString servercodec; + bool userandomserver; + QString perform; + bool useautoidentify; + QString autoidentifyservice; + QString autoidentifypassword; + bool useautoreconnect; + int autoreconnectinterval; + int autoreconnectretries; + bool unlimitedconnectretries; + bool rejoinchannels; + bool connected; + QString usermode; + QString awaymessage; + QString attachperform; + QString detachperform; + bool usesasl; + QString saslaccount; + QString saslpassword; + }; + + struct BufferMO { + BufferId bufferid; + UserId userid; + int groupid; + NetworkId networkid; + QString buffername; + QString buffercname; + int buffertype; + int lastseenmsgid; + int markerlinemsgid; + QString key; + bool joined; + }; + + struct BacklogMO { + MsgId messageid; + QDateTime time; // has to be in UTC! + BufferId bufferid; + int type; + int flags; + int senderid; + QString message; + }; + + struct IrcServerMO { + int serverid; + UserId userid; + NetworkId networkid; + QString hostname; + int port; + QString password; + bool ssl; + int sslversion; + bool useproxy; + int proxytype; + QString proxyhost; + int proxyport; + QString proxyuser; + QString proxypass; + }; + + struct UserSettingMO { + UserId userid; + QString settingname; + QByteArray settingvalue; + }; + + enum MigrationObject { + QuasselUser, + Sender, + Identity, + IdentityNick, + Network, + Buffer, + Backlog, + IrcServer, + UserSetting + }; + + AbstractSqlMigrator(); + virtual ~AbstractSqlMigrator() {} + + static QString migrationObject(MigrationObject moType); protected: - void newQuery(const QString &query, QSqlDatabase db); - virtual void resetQuery(); - virtual bool prepareQuery(MigrationObject mo) = 0; - bool exec(); - inline bool next() { return _query->next(); } - inline QVariant value(int index) { return _query->value(index); } - inline void bindValue(const QString &placeholder, const QVariant &val) { _query->bindValue(placeholder, val); } - inline void bindValue(int pos, const QVariant &val) { _query->bindValue(pos, val); } - - inline QSqlError lastError() { return _query ? _query->lastError() : QSqlError(); } - void dumpStatus(); - inline QString executedQuery() { return _query ? _query->executedQuery() : QString(); } - inline QVariantList boundValues(); - - virtual bool transaction() = 0; - virtual void rollback() = 0; - virtual bool commit() = 0; + void newQuery(const QString &query, QSqlDatabase db); + virtual void resetQuery(); + virtual bool prepareQuery(MigrationObject mo) = 0; + bool exec(); + inline bool next() { return _query->next(); } + inline QVariant value(int index) { return _query->value(index); } + inline void bindValue(const QString &placeholder, const QVariant &val) { _query->bindValue(placeholder, val); } + inline void bindValue(int pos, const QVariant &val) { _query->bindValue(pos, val); } + + inline QSqlError lastError() { return _query ? _query->lastError() : QSqlError(); } + void dumpStatus(); + inline QString executedQuery() { return _query ? _query->executedQuery() : QString(); } + inline QVariantList boundValues(); + + virtual bool transaction() = 0; + virtual void rollback() = 0; + virtual bool commit() = 0; private: - QSqlQuery *_query; + QSqlQuery *_query; }; -class AbstractSqlMigrationReader : public AbstractSqlMigrator { + +class AbstractSqlMigrationReader : public AbstractSqlMigrator +{ public: - AbstractSqlMigrationReader(); + AbstractSqlMigrationReader(); - virtual bool readMo(QuasselUserMO &user) = 0; - virtual bool readMo(IdentityMO &identity) = 0; - virtual bool readMo(IdentityNickMO &identityNick) = 0; - virtual bool readMo(NetworkMO &network) = 0; - virtual bool readMo(BufferMO &buffer) = 0; - virtual bool readMo(SenderMO &sender) = 0; - virtual bool readMo(BacklogMO &backlog) = 0; - virtual bool readMo(IrcServerMO &ircserver) = 0; - virtual bool readMo(UserSettingMO &userSetting) = 0; + virtual bool readMo(QuasselUserMO &user) = 0; + virtual bool readMo(IdentityMO &identity) = 0; + virtual bool readMo(IdentityNickMO &identityNick) = 0; + virtual bool readMo(NetworkMO &network) = 0; + virtual bool readMo(BufferMO &buffer) = 0; + virtual bool readMo(SenderMO &sender) = 0; + virtual bool readMo(BacklogMO &backlog) = 0; + virtual bool readMo(IrcServerMO &ircserver) = 0; + virtual bool readMo(UserSettingMO &userSetting) = 0; - bool migrateTo(AbstractSqlMigrationWriter *writer); + bool migrateTo(AbstractSqlMigrationWriter *writer); private: - void abortMigration(const QString &errorMsg = QString()); - bool finalizeMigration(); + void abortMigration(const QString &errorMsg = QString()); + bool finalizeMigration(); - template bool transferMo(MigrationObject moType, T &mo); + template bool transferMo(MigrationObject moType, T &mo); - AbstractSqlMigrationWriter *_writer; + AbstractSqlMigrationWriter *_writer; }; -class AbstractSqlMigrationWriter : public AbstractSqlMigrator { + +class AbstractSqlMigrationWriter : public AbstractSqlMigrator +{ public: - virtual bool writeMo(const QuasselUserMO &user) = 0; - virtual bool writeMo(const IdentityMO &identity) = 0; - virtual bool writeMo(const IdentityNickMO &identityNick) = 0; - virtual bool writeMo(const NetworkMO &network) = 0; - virtual bool writeMo(const BufferMO &buffer) = 0; - virtual bool writeMo(const SenderMO &sender) = 0; - virtual bool writeMo(const BacklogMO &backlog) = 0; - virtual bool writeMo(const IrcServerMO &ircserver) = 0; - virtual bool writeMo(const UserSettingMO &userSetting) = 0; - - inline bool migrateFrom(AbstractSqlMigrationReader *reader) { return reader->migrateTo(this); } - - // called after migration process - virtual inline bool postProcess() { return true; } - friend class AbstractSqlMigrationReader; + virtual bool writeMo(const QuasselUserMO &user) = 0; + virtual bool writeMo(const IdentityMO &identity) = 0; + virtual bool writeMo(const IdentityNickMO &identityNick) = 0; + virtual bool writeMo(const NetworkMO &network) = 0; + virtual bool writeMo(const BufferMO &buffer) = 0; + virtual bool writeMo(const SenderMO &sender) = 0; + virtual bool writeMo(const BacklogMO &backlog) = 0; + virtual bool writeMo(const IrcServerMO &ircserver) = 0; + virtual bool writeMo(const UserSettingMO &userSetting) = 0; + + inline bool migrateFrom(AbstractSqlMigrationReader *reader) { return reader->migrateTo(this); } + + // called after migration process + virtual inline bool postProcess() { return true; } + friend class AbstractSqlMigrationReader; }; + #endif diff --git a/src/core/cipher.cpp b/src/core/cipher.cpp index 92b8fad1..5ca31293 100644 --- a/src/core/cipher.cpp +++ b/src/core/cipher.cpp @@ -15,449 +15,462 @@ #include "cipher.h" #include "logger.h" - Cipher::Cipher() { - m_primeNum = QCA::BigInteger("12745216229761186769575009943944198619149164746831579719941140425076456621824834322853258804883232842877311723249782818608677050956745409379781245497526069657222703636504651898833151008222772087491045206203033063108075098874712912417029101508315117935752962862335062591404043092163187352352197487303798807791605274487594646923"); - setType("blowfish"); + m_primeNum = QCA::BigInteger("12745216229761186769575009943944198619149164746831579719941140425076456621824834322853258804883232842877311723249782818608677050956745409379781245497526069657222703636504651898833151008222772087491045206203033063108075098874712912417029101508315117935752962862335062591404043092163187352352197487303798807791605274487594646923"); + setType("blowfish"); } + Cipher::Cipher(QByteArray key, QString cipherType) { - m_primeNum = QCA::BigInteger("12745216229761186769575009943944198619149164746831579719941140425076456621824834322853258804883232842877311723249782818608677050956745409379781245497526069657222703636504651898833151008222772087491045206203033063108075098874712912417029101508315117935752962862335062591404043092163187352352197487303798807791605274487594646923"); - setKey(key); - setType(cipherType); + m_primeNum = QCA::BigInteger("12745216229761186769575009943944198619149164746831579719941140425076456621824834322853258804883232842877311723249782818608677050956745409379781245497526069657222703636504651898833151008222772087491045206203033063108075098874712912417029101508315117935752962862335062591404043092163187352352197487303798807791605274487594646923"); + setKey(key); + setType(cipherType); } + Cipher::~Cipher() {} bool Cipher::setKey(QByteArray key) { - if(key.isEmpty()) - return false; + if (key.isEmpty()) + return false; - if(key.mid(0,4).toLower() == "ecb:") - { - m_cbc = false; - m_key = key.mid(4); - } - //strip cbc: if included - else if(key.mid(0,4).toLower() == "cbc:") - { - m_cbc = true; - m_key = key.mid(4); - } - else - { + if (key.mid(0, 4).toLower() == "ecb:") + { + m_cbc = false; + m_key = key.mid(4); + } + //strip cbc: if included + else if (key.mid(0, 4).toLower() == "cbc:") + { + m_cbc = true; + m_key = key.mid(4); + } + else + { // if(Preferences::self()->encryptionType()) // m_cbc = true; // else - m_cbc = false; - m_key = key; - } - return true; + m_cbc = false; + m_key = key; + } + return true; } + bool Cipher::setType(const QString &type) { - //TODO check QCA::isSupported() - m_type = type; - return true; + //TODO check QCA::isSupported() + m_type = type; + return true; } + QByteArray Cipher::decrypt(QByteArray cipherText) { - QByteArray pfx = ""; - bool error = false; // used to flag non cbc, seems like good practice not to parse w/o regard for set encryption type - - //if we get cbc - if(cipherText.mid(0,5) == "+OK *") - { - //if we have cbc - if(m_cbc) - cipherText = cipherText.mid(5); - //if we don't - else + QByteArray pfx = ""; + bool error = false; // used to flag non cbc, seems like good practice not to parse w/o regard for set encryption type + + //if we get cbc + if (cipherText.mid(0, 5) == "+OK *") { - cipherText = cipherText.mid(5); - pfx = "ERROR_NONECB: "; - error = true; + //if we have cbc + if (m_cbc) + cipherText = cipherText.mid(5); + //if we don't + else + { + cipherText = cipherText.mid(5); + pfx = "ERROR_NONECB: "; + error = true; + } } - } - //if we get ecb - else if(cipherText.mid(0,4) == "+OK " || cipherText.mid(0,5) == "mcps ") - { - //if we had cbc - if(m_cbc) + //if we get ecb + else if (cipherText.mid(0, 4) == "+OK " || cipherText.mid(0, 5) == "mcps ") { - cipherText = (cipherText.mid(0,4) == "+OK ") ? cipherText.mid(4) : cipherText.mid(5); - pfx = "ERROR_NONCBC: "; - error = true; + //if we had cbc + if (m_cbc) + { + cipherText = (cipherText.mid(0, 4) == "+OK ") ? cipherText.mid(4) : cipherText.mid(5); + pfx = "ERROR_NONCBC: "; + error = true; + } + //if we don't + else + { + if (cipherText.mid(0, 4) == "+OK ") + cipherText = cipherText.mid(4); + else + cipherText = cipherText.mid(5); + } } - //if we don't + //all other cases we fail else - { - if(cipherText.mid(0,4) == "+OK ") - cipherText = cipherText.mid(4); - else - cipherText = cipherText.mid(5); - } - } - //all other cases we fail - else - return cipherText; - - QByteArray temp; - // (if cbc and no error we parse cbc) || (if ecb and error we parse cbc) - if((m_cbc && !error) || (!m_cbc && error)) - { - cipherText = cipherText; - temp = blowfishCBC(cipherText, false); + return cipherText; - if(temp == cipherText) + QByteArray temp; + // (if cbc and no error we parse cbc) || (if ecb and error we parse cbc) + if ((m_cbc && !error) || (!m_cbc && error)) { - // kDebug("Decryption from CBC Failed"); - return cipherText+' '+'\n'; + cipherText = cipherText; + temp = blowfishCBC(cipherText, false); + + if (temp == cipherText) + { + // kDebug("Decryption from CBC Failed"); + return cipherText+' '+'\n'; + } + else + cipherText = temp; } else - cipherText = temp; - } - else - { - temp = blowfishECB(cipherText, false); - - if(temp == cipherText) { - // kDebug("Decryption from ECB Failed"); - return cipherText+' '+'\n'; + temp = blowfishECB(cipherText, false); + + if (temp == cipherText) + { + // kDebug("Decryption from ECB Failed"); + return cipherText+' '+'\n'; + } + else + cipherText = temp; } - else - cipherText = temp; - } - // TODO FIXME the proper fix for this is to show encryption differently e.g. [nick] instead of - // don't hate me for the mircryption reference there. - if (cipherText.at(0) == 1) - pfx = "\x0"; - cipherText = pfx+cipherText+' '+'\n'; // FIXME(??) why is there an added space here? - return cipherText; + // TODO FIXME the proper fix for this is to show encryption differently e.g. [nick] instead of + // don't hate me for the mircryption reference there. + if (cipherText.at(0) == 1) + pfx = "\x0"; + cipherText = pfx+cipherText+' '+'\n'; // FIXME(??) why is there an added space here? + return cipherText; } + QByteArray Cipher::initKeyExchange() { - QCA::Initializer init; - m_tempKey = QCA::KeyGenerator().createDH(QCA::DLGroup(m_primeNum, QCA::BigInteger(2))).toDH(); + QCA::Initializer init; + m_tempKey = QCA::KeyGenerator().createDH(QCA::DLGroup(m_primeNum, QCA::BigInteger(2))).toDH(); - if(m_tempKey.isNull()) - return QByteArray(); + if (m_tempKey.isNull()) + return QByteArray(); - QByteArray publicKey = m_tempKey.toPublicKey().toDH().y().toArray().toByteArray(); + QByteArray publicKey = m_tempKey.toPublicKey().toDH().y().toArray().toByteArray(); - //remove leading 0 - if(publicKey.length() > 135 && publicKey.at(0) == '\0') - publicKey = publicKey.mid(1); + //remove leading 0 + if (publicKey.length() > 135 && publicKey.at(0) == '\0') + publicKey = publicKey.mid(1); - return publicKey.toBase64().append('A'); + return publicKey.toBase64().append('A'); } + QByteArray Cipher::parseInitKeyX(QByteArray key) { - QCA::Initializer init; + QCA::Initializer init; - if(key.length() != 181) - return QByteArray(); + if (key.length() != 181) + return QByteArray(); - QCA::SecureArray remoteKey = QByteArray::fromBase64(key.left(180)); - QCA::DLGroup group(m_primeNum, QCA::BigInteger(2)); - QCA::DHPrivateKey privateKey = QCA::KeyGenerator().createDH(group).toDH(); + QCA::SecureArray remoteKey = QByteArray::fromBase64(key.left(180)); + QCA::DLGroup group(m_primeNum, QCA::BigInteger(2)); + QCA::DHPrivateKey privateKey = QCA::KeyGenerator().createDH(group).toDH(); - if(privateKey.isNull()) - return QByteArray(); + if (privateKey.isNull()) + return QByteArray(); - QByteArray publicKey = privateKey.y().toArray().toByteArray(); + QByteArray publicKey = privateKey.y().toArray().toByteArray(); - //remove leading 0 - if(publicKey.length() > 135 && publicKey.at(0) == '\0') - publicKey = publicKey.mid(1); + //remove leading 0 + if (publicKey.length() > 135 && publicKey.at(0) == '\0') + publicKey = publicKey.mid(1); - QCA::DHPublicKey remotePub(group, remoteKey); + QCA::DHPublicKey remotePub(group, remoteKey); - if(remotePub.isNull()) - return QByteArray(); + if (remotePub.isNull()) + return QByteArray(); - QByteArray sharedKey = privateKey.deriveKey(remotePub).toByteArray(); - sharedKey = QCA::Hash("sha256").hash(sharedKey).toByteArray().toBase64(); + QByteArray sharedKey = privateKey.deriveKey(remotePub).toByteArray(); + sharedKey = QCA::Hash("sha256").hash(sharedKey).toByteArray().toBase64(); - //remove trailing = because mircryption and fish think it's a swell idea. - while(sharedKey.endsWith('=')) sharedKey.chop(1); + //remove trailing = because mircryption and fish think it's a swell idea. + while (sharedKey.endsWith('=')) sharedKey.chop(1); - bool success = setKey(sharedKey); + bool success = setKey(sharedKey); - if(!success) - return QByteArray(); + if (!success) + return QByteArray(); - return publicKey.toBase64().append('A'); + return publicKey.toBase64().append('A'); } + bool Cipher::parseFinishKeyX(QByteArray key) { - QCA::Initializer init; + QCA::Initializer init; - if(key.length() != 181) - return false; + if (key.length() != 181) + return false; - QCA::SecureArray remoteKey = QByteArray::fromBase64(key.left(180)); - QCA::DLGroup group(m_primeNum, QCA::BigInteger(2)); + QCA::SecureArray remoteKey = QByteArray::fromBase64(key.left(180)); + QCA::DLGroup group(m_primeNum, QCA::BigInteger(2)); - QCA::DHPublicKey remotePub(group, remoteKey); + QCA::DHPublicKey remotePub(group, remoteKey); - if(remotePub.isNull()) - return false; + if (remotePub.isNull()) + return false; - if(m_tempKey.isNull()) - return false; + if (m_tempKey.isNull()) + return false; - QByteArray sharedKey = m_tempKey.deriveKey(remotePub).toByteArray(); - sharedKey = QCA::Hash("sha256").hash(sharedKey).toByteArray().toBase64(); + QByteArray sharedKey = m_tempKey.deriveKey(remotePub).toByteArray(); + sharedKey = QCA::Hash("sha256").hash(sharedKey).toByteArray().toBase64(); - //remove trailng = because mircryption and fish think it's a swell idea. - while(sharedKey.endsWith('=')) sharedKey.chop(1); + //remove trailng = because mircryption and fish think it's a swell idea. + while (sharedKey.endsWith('=')) sharedKey.chop(1); - bool success = setKey(sharedKey); + bool success = setKey(sharedKey); - return success; + return success; } + QByteArray Cipher::decryptTopic(QByteArray cipherText) { - if(cipherText.mid(0,4) == "+OK ")// FiSH style topic - cipherText = cipherText.mid(4); - else if(cipherText.left(5) == "«m«") - cipherText = cipherText.mid(5,cipherText.length()-10); - else - return cipherText; + if (cipherText.mid(0, 4) == "+OK ") // FiSH style topic + cipherText = cipherText.mid(4); + else if (cipherText.left(5) == "«m«") + cipherText = cipherText.mid(5, cipherText.length()-10); + else + return cipherText; - QByteArray temp; - //TODO currently no backwards sanity checks for topic, it seems to use different standards - //if somebody figures them out they can enable it and add "ERROR_NONECB/CBC" warnings - if(m_cbc) - temp = blowfishCBC(cipherText.mid(1), false); - else - temp = blowfishECB(cipherText, false); + QByteArray temp; + //TODO currently no backwards sanity checks for topic, it seems to use different standards + //if somebody figures them out they can enable it and add "ERROR_NONECB/CBC" warnings + if (m_cbc) + temp = blowfishCBC(cipherText.mid(1), false); + else + temp = blowfishECB(cipherText, false); - if(temp == cipherText) - { - return cipherText; - } - else - cipherText = temp; + if (temp == cipherText) + { + return cipherText; + } + else + cipherText = temp; - if(cipherText.mid(0,2) == "@@") - cipherText = cipherText.mid(2); + if (cipherText.mid(0, 2) == "@@") + cipherText = cipherText.mid(2); - return cipherText; + return cipherText; } -bool Cipher::encrypt(QByteArray& cipherText) + +bool Cipher::encrypt(QByteArray &cipherText) { - if (cipherText.left(3) == "+p ") //don't encode if...? - cipherText = cipherText.mid(3); - else - { - if(m_cbc) //encode in ecb or cbc decide how to determine later + if (cipherText.left(3) == "+p ") //don't encode if...? + cipherText = cipherText.mid(3); + else { - QByteArray temp = blowfishCBC(cipherText, true); + if (m_cbc) //encode in ecb or cbc decide how to determine later + { + QByteArray temp = blowfishCBC(cipherText, true); + + if (temp == cipherText) + { + // kDebug("CBC Encoding Failed"); + return false; + } + + cipherText = "+OK *" + temp; + } + else + { + QByteArray temp = blowfishECB(cipherText, true); + + if (temp == cipherText) + { + // kDebug("ECB Encoding Failed"); + return false; + } + + cipherText = "+OK " + temp; + } + } + return true; +} - if(temp == cipherText) - { - // kDebug("CBC Encoding Failed"); - return false; - } - cipherText = "+OK *" + temp; +//THE BELOW WORKS AKA DO NOT TOUCH UNLESS YOU KNOW WHAT YOU'RE DOING +QByteArray Cipher::blowfishCBC(QByteArray cipherText, bool direction) +{ + QCA::Initializer init; + QByteArray temp = cipherText; + if (direction) + { + // make sure cipherText is an interval of 8 bits. We do this before so that we + // know there's at least 8 bytes to en/decryption this ensures QCA doesn't fail + while ((temp.length() % 8) != 0) temp.append('\0'); + + QCA::InitializationVector iv(8); + temp.prepend(iv.toByteArray()); // prefix with 8bits of IV for mircryptions *CUSTOM* cbc implementation } else { - QByteArray temp = blowfishECB(cipherText, true); - - if(temp == cipherText) - { - // kDebug("ECB Encoding Failed"); - return false; - } + temp = QByteArray::fromBase64(temp); + //supposedly nescessary if we get a truncated message also allows for decryption of 'crazy' + //en/decoding clients that use STANDARDIZED PADDING TECHNIQUES + while ((temp.length() % 8) != 0) temp.append('\0'); + } - cipherText = "+OK " + temp; - } - } - return true; -} + QCA::Direction dir = (direction) ? QCA::Encode : QCA::Decode; + QCA::Cipher cipher(m_type, QCA::Cipher::CBC, QCA::Cipher::NoPadding, dir, m_key, QCA::InitializationVector(QByteArray("0"))); + QByteArray temp2 = cipher.update(QCA::MemoryRegion(temp)).toByteArray(); + temp2 += cipher.final().toByteArray(); -//THE BELOW WORKS AKA DO NOT TOUCH UNLESS YOU KNOW WHAT YOU'RE DOING -QByteArray Cipher::blowfishCBC(QByteArray cipherText, bool direction) -{ - QCA::Initializer init; - QByteArray temp = cipherText; - if(direction) - { - // make sure cipherText is an interval of 8 bits. We do this before so that we - // know there's at least 8 bytes to en/decryption this ensures QCA doesn't fail - while((temp.length() % 8) != 0) temp.append('\0'); - - QCA::InitializationVector iv(8); - temp.prepend(iv.toByteArray()); // prefix with 8bits of IV for mircryptions *CUSTOM* cbc implementation - } - else - { - temp = QByteArray::fromBase64(temp); - //supposedly nescessary if we get a truncated message also allows for decryption of 'crazy' - //en/decoding clients that use STANDARDIZED PADDING TECHNIQUES - while((temp.length() % 8) != 0) temp.append('\0'); - } - - QCA::Direction dir = (direction) ? QCA::Encode : QCA::Decode; - QCA::Cipher cipher(m_type, QCA::Cipher::CBC, QCA::Cipher::NoPadding, dir, m_key, QCA::InitializationVector(QByteArray("0"))); - QByteArray temp2 = cipher.update(QCA::MemoryRegion(temp)).toByteArray(); - temp2 += cipher.final().toByteArray(); - - if(!cipher.ok()) - return cipherText; + if (!cipher.ok()) + return cipherText; - if(direction) //send in base64 - temp2 = temp2.toBase64(); - else //cut off the 8bits of IV - temp2 = temp2.remove(0,8); + if (direction) //send in base64 + temp2 = temp2.toBase64(); + else //cut off the 8bits of IV + temp2 = temp2.remove(0, 8); - return temp2; + return temp2; } + QByteArray Cipher::blowfishECB(QByteArray cipherText, bool direction) { - QCA::Initializer init; - QByteArray temp = cipherText; - - //do padding ourselves - if(direction) - { - while((temp.length() % 8) != 0) temp.append('\0'); - } - else - { - temp = b64ToByte(temp); - while((temp.length() % 8) != 0) temp.append('\0'); - } - - QCA::Direction dir = (direction) ? QCA::Encode : QCA::Decode; - QCA::Cipher cipher(m_type, QCA::Cipher::ECB, QCA::Cipher::NoPadding, dir, m_key); - QByteArray temp2 = cipher.update(QCA::MemoryRegion(temp)).toByteArray(); - temp2 += cipher.final().toByteArray(); - - if(!cipher.ok()) - return cipherText; + QCA::Initializer init; + QByteArray temp = cipherText; - if(direction) - temp2 = byteToB64(temp2); + //do padding ourselves + if (direction) + { + while ((temp.length() % 8) != 0) temp.append('\0'); + } + else + { + temp = b64ToByte(temp); + while ((temp.length() % 8) != 0) temp.append('\0'); + } + + QCA::Direction dir = (direction) ? QCA::Encode : QCA::Decode; + QCA::Cipher cipher(m_type, QCA::Cipher::ECB, QCA::Cipher::NoPadding, dir, m_key); + QByteArray temp2 = cipher.update(QCA::MemoryRegion(temp)).toByteArray(); + temp2 += cipher.final().toByteArray(); - return temp2; + if (!cipher.ok()) + return cipherText; + + if (direction) + temp2 = byteToB64(temp2); + + return temp2; } + //Custom non RFC 2045 compliant Base64 enc/dec code for mircryption / FiSH compatibility QByteArray Cipher::byteToB64(QByteArray text) { - int left = 0; - int right = 0; - int k = -1; - int v; - QString base64 = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; - QByteArray encoded; - while (k < (text.length() - 1)) { - k++; - v=text.at(k); if (v<0) v+=256; - left = v << 24; - k++; - v=text.at(k); if (v<0) v+=256; - left += v << 16; - k++; - v=text.at(k); if (v<0) v+=256; - left += v << 8; - k++; - v=text.at(k); if (v<0) v+=256; - left += v; - - k++; - v=text.at(k); if (v<0) v+=256; - right = v << 24; - k++; - v=text.at(k); if (v<0) v+=256; - right += v << 16; - k++; - v=text.at(k); if (v<0) v+=256; - right += v << 8; - k++; - v=text.at(k); if (v<0) v+=256; - right += v; - - for (int i = 0; i < 6; i++) { - encoded.append(base64.at(right & 0x3F).toAscii()); - right = right >> 6; - } - - //TODO make sure the .toascii doesn't break anything - for (int i = 0; i < 6; i++) { - encoded.append(base64.at(left & 0x3F).toAscii()); - left = left >> 6; + int left = 0; + int right = 0; + int k = -1; + int v; + QString base64 = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + QByteArray encoded; + while (k < (text.length() - 1)) { + k++; + v = text.at(k); if (v < 0) v += 256; + left = v << 24; + k++; + v = text.at(k); if (v < 0) v += 256; + left += v << 16; + k++; + v = text.at(k); if (v < 0) v += 256; + left += v << 8; + k++; + v = text.at(k); if (v < 0) v += 256; + left += v; + + k++; + v = text.at(k); if (v < 0) v += 256; + right = v << 24; + k++; + v = text.at(k); if (v < 0) v += 256; + right += v << 16; + k++; + v = text.at(k); if (v < 0) v += 256; + right += v << 8; + k++; + v = text.at(k); if (v < 0) v += 256; + right += v; + + for (int i = 0; i < 6; i++) { + encoded.append(base64.at(right & 0x3F).toAscii()); + right = right >> 6; + } + + //TODO make sure the .toascii doesn't break anything + for (int i = 0; i < 6; i++) { + encoded.append(base64.at(left & 0x3F).toAscii()); + left = left >> 6; + } } - } - return encoded; + return encoded; } + QByteArray Cipher::b64ToByte(QByteArray text) { - QString base64 = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; - QByteArray decoded; - int k = -1; - while (k < (text.length() - 1)) { - int right = 0; - int left = 0; - int v = 0; - int w = 0; - int z = 0; - - for (int i = 0; i < 6; i++) { - k++; - v = base64.indexOf(text.at(k)); - right |= v << (i * 6); - } - - for (int i = 0; i < 6; i++) { - k++; - v = base64.indexOf(text.at(k)); - left |= v << (i * 6); - } - - for (int i = 0; i < 4; i++) { - w = ((left & (0xFF << ((3 - i) * 8)))); - z = w >> ((3 - i) * 8); - if(z < 0) {z = z + 256;} - decoded.append(z); + QString base64 = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + QByteArray decoded; + int k = -1; + while (k < (text.length() - 1)) { + int right = 0; + int left = 0; + int v = 0; + int w = 0; + int z = 0; + + for (int i = 0; i < 6; i++) { + k++; + v = base64.indexOf(text.at(k)); + right |= v << (i * 6); + } + + for (int i = 0; i < 6; i++) { + k++; + v = base64.indexOf(text.at(k)); + left |= v << (i * 6); + } + + for (int i = 0; i < 4; i++) { + w = ((left & (0xFF << ((3 - i) * 8)))); + z = w >> ((3 - i) * 8); + if (z < 0) { z = z + 256; } + decoded.append(z); + } + + for (int i = 0; i < 4; i++) { + w = ((right & (0xFF << ((3 - i) * 8)))); + z = w >> ((3 - i) * 8); + if (z < 0) { z = z + 256; } + decoded.append(z); + } } - - for (int i = 0; i < 4; i++) { - w = ((right & (0xFF << ((3 - i) * 8)))); - z = w >> ((3 - i) * 8); - if(z < 0) {z = z + 256;} - decoded.append(z); - } - } - return decoded; + return decoded; } + bool Cipher::neededFeaturesAvailable() { - QCA::Initializer init; + QCA::Initializer init; - if (QCA::isSupported("blowfish-ecb") && QCA::isSupported("blowfish-cbc") && QCA::isSupported("dh")) - return true; + if (QCA::isSupported("blowfish-ecb") && QCA::isSupported("blowfish-cbc") && QCA::isSupported("dh")) + return true; - qWarning() << "QCA provider plugin not found. It is usually provided by the qca-ossl plugin."; - return false; + qWarning() << "QCA provider plugin not found. It is usually provided by the qca-ossl plugin."; + return false; } diff --git a/src/core/cipher.h b/src/core/cipher.h index 33a2bf8c..e7f88b38 100644 --- a/src/core/cipher.h +++ b/src/core/cipher.h @@ -15,17 +15,17 @@ #ifndef CIPHER_H #define CIPHER_H -#include +#include class Cipher { - public: +public: Cipher(); - explicit Cipher(QByteArray key, QString cipherType=QString("blowfish")); + explicit Cipher(QByteArray key, QString cipherType = QString("blowfish")); ~Cipher(); QByteArray decrypt(QByteArray cipher); QByteArray decryptTopic(QByteArray cipher); - bool encrypt(QByteArray& cipher); + bool encrypt(QByteArray &cipher); QByteArray initKeyExchange(); QByteArray parseInitKeyX(QByteArray key); bool parseFinishKeyX(QByteArray key); @@ -35,7 +35,7 @@ class Cipher QString type() { return m_type; } static bool neededFeaturesAvailable(); - private: +private: //direction is true for encrypt, false for decrypt QByteArray blowfishCBC(QByteArray cipherText, bool direction); QByteArray blowfishECB(QByteArray cipherText, bool direction); @@ -49,4 +49,6 @@ class Cipher QString m_type; bool m_cbc; }; + + #endif // CIPHER_H diff --git a/src/core/core.cpp b/src/core/core.cpp index 6dc4fa70..50e4ae05 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -51,11 +51,12 @@ // ============================== const int Core::AddClientEventId = QEvent::registerEventType(); -class AddClientEvent : public QEvent { +class AddClientEvent : public QEvent +{ public: - AddClientEvent(QTcpSocket *socket, UserId uid) : QEvent(QEvent::Type(Core::AddClientEventId)), socket(socket), userId(uid) {} - QTcpSocket *socket; - UserId userId; + AddClientEvent(QTcpSocket *socket, UserId uid) : QEvent(QEvent::Type(Core::AddClientEventId)), socket(socket), userId(uid) {} + QTcpSocket *socket; + UserId userId; }; @@ -64,30 +65,34 @@ public: // ============================== Core *Core::instanceptr = 0; -Core *Core::instance() { - if(instanceptr) return instanceptr; - instanceptr = new Core(); - instanceptr->init(); - return instanceptr; +Core *Core::instance() +{ + if (instanceptr) return instanceptr; + instanceptr = new Core(); + instanceptr->init(); + return instanceptr; } -void Core::destroy() { - delete instanceptr; - instanceptr = 0; + +void Core::destroy() +{ + delete instanceptr; + instanceptr = 0; } + Core::Core() - : _storage(0) + : _storage(0) { #ifdef HAVE_UMASK - umask(S_IRWXG | S_IRWXO); + umask(S_IRWXG | S_IRWXO); #endif - _startTime = QDateTime::currentDateTime().toUTC(); // for uptime :) + _startTime = QDateTime::currentDateTime().toUTC(); // for uptime :) - Quassel::loadTranslation(QLocale::system()); + Quassel::loadTranslation(QLocale::system()); - // FIXME: MIGRATION 0.3 -> 0.4: Move database and core config to new location - // Move settings, note this does not delete the old files + // FIXME: MIGRATION 0.3 -> 0.4: Move database and core config to new location + // Move settings, note this does not delete the old files #ifdef Q_WS_MAC QSettings newSettings("quassel-irc.org", "quasselcore"); #else @@ -98,931 +103,1020 @@ Core::Core() QSettings::Format format = QSettings::NativeFormat; # endif QString newFilePath = Quassel::configDirPath() + "quasselcore" - + ((format == QSettings::NativeFormat) ? QLatin1String(".conf") : QLatin1String(".ini")); + + ((format == QSettings::NativeFormat) ? QLatin1String(".conf") : QLatin1String(".ini")); QSettings newSettings(newFilePath, format); #endif /* Q_WS_MAC */ - if(newSettings.value("Config/Version").toUInt() == 0) { + if (newSettings.value("Config/Version").toUInt() == 0) { # ifdef Q_WS_MAC - QString org = "quassel-irc.org"; + QString org = "quassel-irc.org"; # else - QString org = "Quassel Project"; + QString org = "Quassel Project"; # endif - QSettings oldSettings(org, "Quassel Core"); - if(oldSettings.allKeys().count()) { - qWarning() << "\n\n*** IMPORTANT: Config and data file locations have changed. Attempting to auto-migrate your core settings..."; - foreach(QString key, oldSettings.allKeys()) - newSettings.setValue(key, oldSettings.value(key)); - newSettings.setValue("Config/Version", 1); - qWarning() << "* Your core settings have been migrated to" << newSettings.fileName(); + QSettings oldSettings(org, "Quassel Core"); + if (oldSettings.allKeys().count()) { + qWarning() << "\n\n*** IMPORTANT: Config and data file locations have changed. Attempting to auto-migrate your core settings..."; + foreach(QString key, oldSettings.allKeys()) + newSettings.setValue(key, oldSettings.value(key)); + newSettings.setValue("Config/Version", 1); + qWarning() << "* Your core settings have been migrated to" << newSettings.fileName(); #ifndef Q_WS_MAC /* we don't need to move the db and cert for mac */ #ifdef Q_OS_WIN32 - QString quasselDir = qgetenv("APPDATA") + "/quassel/"; + QString quasselDir = qgetenv("APPDATA") + "/quassel/"; #elif defined Q_WS_MAC - QString quasselDir = QDir::homePath() + "/Library/Application Support/Quassel/"; + QString quasselDir = QDir::homePath() + "/Library/Application Support/Quassel/"; #else - QString quasselDir = QDir::homePath() + "/.quassel/"; + QString quasselDir = QDir::homePath() + "/.quassel/"; #endif - QFileInfo info(Quassel::configDirPath() + "quassel-storage.sqlite"); - if(!info.exists()) { - // move database, if we found it - QFile oldDb(quasselDir + "quassel-storage.sqlite"); - if(oldDb.exists()) { - bool success = oldDb.rename(Quassel::configDirPath() + "quassel-storage.sqlite"); - if(success) - qWarning() << "* Your database has been moved to" << Quassel::configDirPath() + "quassel-storage.sqlite"; - else - qWarning() << "!!! Moving your database has failed. Please move it manually into" << Quassel::configDirPath(); - } - } - // move certificate - QFileInfo certInfo(quasselDir + "quasselCert.pem"); - if(certInfo.exists()) { - QFile cert(quasselDir + "quasselCert.pem"); - bool success = cert.rename(Quassel::configDirPath() + "quasselCert.pem"); - if(success) - qWarning() << "* Your certificate has been moved to" << Quassel::configDirPath() + "quasselCert.pem"; - else - qWarning() << "!!! Moving your certificate has failed. Please move it manually into" << Quassel::configDirPath(); - } + QFileInfo info(Quassel::configDirPath() + "quassel-storage.sqlite"); + if (!info.exists()) { + // move database, if we found it + QFile oldDb(quasselDir + "quassel-storage.sqlite"); + if (oldDb.exists()) { + bool success = oldDb.rename(Quassel::configDirPath() + "quassel-storage.sqlite"); + if (success) + qWarning() << "* Your database has been moved to" << Quassel::configDirPath() + "quassel-storage.sqlite"; + else + qWarning() << "!!! Moving your database has failed. Please move it manually into" << Quassel::configDirPath(); + } + } + // move certificate + QFileInfo certInfo(quasselDir + "quasselCert.pem"); + if (certInfo.exists()) { + QFile cert(quasselDir + "quasselCert.pem"); + bool success = cert.rename(Quassel::configDirPath() + "quasselCert.pem"); + if (success) + qWarning() << "* Your certificate has been moved to" << Quassel::configDirPath() + "quasselCert.pem"; + else + qWarning() << "!!! Moving your certificate has failed. Please move it manually into" << Quassel::configDirPath(); + } #endif /* !Q_WS_MAC */ - qWarning() << "*** Migration completed.\n\n"; + qWarning() << "*** Migration completed.\n\n"; + } + } + // MIGRATION end + + // check settings version + // so far, we only have 1 + CoreSettings s; + if (s.version() != 1) { + qCritical() << "Invalid core settings version, terminating!"; + exit(EXIT_FAILURE); } - } - // MIGRATION end - - // check settings version - // so far, we only have 1 - CoreSettings s; - if(s.version() != 1) { - qCritical() << "Invalid core settings version, terminating!"; - exit(EXIT_FAILURE); - } - registerStorageBackends(); + registerStorageBackends(); - connect(&_storageSyncTimer, SIGNAL(timeout()), this, SLOT(syncStorage())); - _storageSyncTimer.start(10 * 60 * 1000); // 10 minutes + connect(&_storageSyncTimer, SIGNAL(timeout()), this, SLOT(syncStorage())); + _storageSyncTimer.start(10 * 60 * 1000); // 10 minutes } -void Core::init() { - CoreSettings cs; - _configured = initStorage(cs.storageSettings().toMap()); - - if(Quassel::isOptionSet("select-backend")) { - selectBackend(Quassel::optionValue("select-backend")); - exit(0); - } - - if(!_configured) { - if(!_storageBackends.count()) { - qWarning() << qPrintable(tr("Could not initialize any storage backend! Exiting...")); - qWarning() << qPrintable(tr("Currently, Quassel supports SQLite3 and PostgreSQL. You need to build your\n" - "Qt library with the sqlite or postgres plugin enabled in order for quasselcore\n" - "to work.")); - exit(1); // TODO make this less brutal (especially for mono client -> popup) + +void Core::init() +{ + CoreSettings cs; + _configured = initStorage(cs.storageSettings().toMap()); + + if (Quassel::isOptionSet("select-backend")) { + selectBackend(Quassel::optionValue("select-backend")); + exit(0); } - qWarning() << "Core is currently not configured! Please connect with a Quassel Client for basic setup."; - } - if(Quassel::isOptionSet("add-user")) { - createUser(); - exit(0); - } + if (!_configured) { + if (!_storageBackends.count()) { + qWarning() << qPrintable(tr("Could not initialize any storage backend! Exiting...")); + qWarning() << qPrintable(tr("Currently, Quassel supports SQLite3 and PostgreSQL. You need to build your\n" + "Qt library with the sqlite or postgres plugin enabled in order for quasselcore\n" + "to work.")); + exit(1); // TODO make this less brutal (especially for mono client -> popup) + } + qWarning() << "Core is currently not configured! Please connect with a Quassel Client for basic setup."; + } + + if (Quassel::isOptionSet("add-user")) { + createUser(); + exit(0); + } - if(Quassel::isOptionSet("change-userpass")) { - changeUserPass(Quassel::optionValue("change-userpass")); - exit(0); - } + if (Quassel::isOptionSet("change-userpass")) { + changeUserPass(Quassel::optionValue("change-userpass")); + exit(0); + } - connect(&_server, SIGNAL(newConnection()), this, SLOT(incomingConnection())); - connect(&_v6server, SIGNAL(newConnection()), this, SLOT(incomingConnection())); - if(!startListening()) exit(1); // TODO make this less brutal + connect(&_server, SIGNAL(newConnection()), this, SLOT(incomingConnection())); + connect(&_v6server, SIGNAL(newConnection()), this, SLOT(incomingConnection())); + if (!startListening()) exit(1); // TODO make this less brutal - if(Quassel::isOptionSet("oidentd")) - _oidentdConfigGenerator = new OidentdConfigGenerator(this); + if (Quassel::isOptionSet("oidentd")) + _oidentdConfigGenerator = new OidentdConfigGenerator(this); } -Core::~Core() { - foreach(QTcpSocket *socket, blocksizes.keys()) { - socket->disconnectFromHost(); // disconnect non authed clients - } - qDeleteAll(sessions); - qDeleteAll(_storageBackends); + +Core::~Core() +{ + foreach(QTcpSocket *socket, blocksizes.keys()) { + socket->disconnectFromHost(); // disconnect non authed clients + } + qDeleteAll(sessions); + qDeleteAll(_storageBackends); } + /*** Session Restore ***/ -void Core::saveState() { - CoreSettings s; - QVariantMap state; - QVariantList activeSessions; - foreach(UserId user, instance()->sessions.keys()) activeSessions << QVariant::fromValue(user); - state["CoreStateVersion"] = 1; - state["ActiveSessions"] = activeSessions; - s.setCoreState(state); +void Core::saveState() +{ + CoreSettings s; + QVariantMap state; + QVariantList activeSessions; + foreach(UserId user, instance()->sessions.keys()) activeSessions << QVariant::fromValue(user); + state["CoreStateVersion"] = 1; + state["ActiveSessions"] = activeSessions; + s.setCoreState(state); } -void Core::restoreState() { - if(!instance()->_configured) { - // qWarning() << qPrintable(tr("Cannot restore a state for an unconfigured core!")); - return; - } - if(instance()->sessions.count()) { - qWarning() << qPrintable(tr("Calling restoreState() even though active sessions exist!")); - return; - } - CoreSettings s; - /* We don't check, since we are at the first version since switching to Git - uint statever = s.coreState().toMap()["CoreStateVersion"].toUInt(); - if(statever < 1) { - qWarning() << qPrintable(tr("Core state too old, ignoring...")); - return; - } - */ - - QVariantList activeSessions = s.coreState().toMap()["ActiveSessions"].toList(); - if(activeSessions.count() > 0) { - quInfo() << "Restoring previous core state..."; - foreach(QVariant v, activeSessions) { - UserId user = v.value(); - instance()->createSession(user, true); + +void Core::restoreState() +{ + if (!instance()->_configured) { + // qWarning() << qPrintable(tr("Cannot restore a state for an unconfigured core!")); + return; + } + if (instance()->sessions.count()) { + qWarning() << qPrintable(tr("Calling restoreState() even though active sessions exist!")); + return; + } + CoreSettings s; + /* We don't check, since we are at the first version since switching to Git + uint statever = s.coreState().toMap()["CoreStateVersion"].toUInt(); + if(statever < 1) { + qWarning() << qPrintable(tr("Core state too old, ignoring...")); + return; + } + */ + + QVariantList activeSessions = s.coreState().toMap()["ActiveSessions"].toList(); + if (activeSessions.count() > 0) { + quInfo() << "Restoring previous core state..."; + foreach(QVariant v, activeSessions) { + UserId user = v.value(); + instance()->createSession(user, true); + } } - } } + /*** Core Setup ***/ -QString Core::setupCoreForInternalUsage() { - Q_ASSERT(!_storageBackends.isEmpty()); - QVariantMap setupData; - qsrand(QDateTime::currentDateTime().toTime_t()); - int pass = 0; - for(int i = 0; i < 10; i++) { - pass *= 10; - pass += qrand() % 10; - } - setupData["AdminUser"] = "AdminUser"; - setupData["AdminPasswd"] = QString::number(pass); - setupData["Backend"] = QString("SQLite"); // mono client currently needs sqlite - return setupCore(setupData); +QString Core::setupCoreForInternalUsage() +{ + Q_ASSERT(!_storageBackends.isEmpty()); + QVariantMap setupData; + qsrand(QDateTime::currentDateTime().toTime_t()); + int pass = 0; + for (int i = 0; i < 10; i++) { + pass *= 10; + pass += qrand() % 10; + } + setupData["AdminUser"] = "AdminUser"; + setupData["AdminPasswd"] = QString::number(pass); + setupData["Backend"] = QString("SQLite"); // mono client currently needs sqlite + return setupCore(setupData); } -QString Core::setupCore(QVariantMap setupData) { - QString user = setupData.take("AdminUser").toString(); - QString password = setupData.take("AdminPasswd").toString(); - if(user.isEmpty() || password.isEmpty()) { - return tr("Admin user or password not set."); - } - if(_configured || !(_configured = initStorage(setupData, true))) { - return tr("Could not setup storage!"); - } - CoreSettings s; - s.setStorageSettings(setupData); - quInfo() << qPrintable(tr("Creating admin user...")); - _storage->addUser(user, password); - startListening(); // TODO check when we need this - return QString(); + +QString Core::setupCore(QVariantMap setupData) +{ + QString user = setupData.take("AdminUser").toString(); + QString password = setupData.take("AdminPasswd").toString(); + if (user.isEmpty() || password.isEmpty()) { + return tr("Admin user or password not set."); + } + if (_configured || !(_configured = initStorage(setupData, true))) { + return tr("Could not setup storage!"); + } + CoreSettings s; + s.setStorageSettings(setupData); + quInfo() << qPrintable(tr("Creating admin user...")); + _storage->addUser(user, password); + startListening(); // TODO check when we need this + return QString(); } + /*** Storage Handling ***/ -void Core::registerStorageBackends() { - // Register storage backends here! - registerStorageBackend(new SqliteStorage(this)); - registerStorageBackend(new PostgreSqlStorage(this)); +void Core::registerStorageBackends() +{ + // Register storage backends here! + registerStorageBackend(new SqliteStorage(this)); + registerStorageBackend(new PostgreSqlStorage(this)); } -bool Core::registerStorageBackend(Storage *backend) { - if(backend->isAvailable()) { - _storageBackends[backend->displayName()] = backend; - return true; - } else { - backend->deleteLater(); - return false; - } + +bool Core::registerStorageBackend(Storage *backend) +{ + if (backend->isAvailable()) { + _storageBackends[backend->displayName()] = backend; + return true; + } + else { + backend->deleteLater(); + return false; + } } -void Core::unregisterStorageBackends() { - foreach(Storage *s, _storageBackends.values()) { - s->deleteLater(); - } - _storageBackends.clear(); + +void Core::unregisterStorageBackends() +{ + foreach(Storage *s, _storageBackends.values()) { + s->deleteLater(); + } + _storageBackends.clear(); } -void Core::unregisterStorageBackend(Storage *backend) { - _storageBackends.remove(backend->displayName()); - backend->deleteLater(); + +void Core::unregisterStorageBackend(Storage *backend) +{ + _storageBackends.remove(backend->displayName()); + backend->deleteLater(); } + // old db settings: // "Type" => "sqlite" -bool Core::initStorage(const QString &backend, QVariantMap settings, bool setup) { - _storage = 0; - - if(backend.isEmpty()) { - return false; - } - - Storage *storage = 0; - if(_storageBackends.contains(backend)) { - storage = _storageBackends[backend]; - } else { - qCritical() << "Selected storage backend is not available:" << backend; - return false; - } - - Storage::State storageState = storage->init(settings); - switch(storageState) { - case Storage::NeedsSetup: - if(!setup) - return false; // trigger setup process - if(storage->setup(settings)) - return initStorage(backend, settings, false); +bool Core::initStorage(const QString &backend, QVariantMap settings, bool setup) +{ + _storage = 0; + + if (backend.isEmpty()) { + return false; + } + + Storage *storage = 0; + if (_storageBackends.contains(backend)) { + storage = _storageBackends[backend]; + } + else { + qCritical() << "Selected storage backend is not available:" << backend; + return false; + } + + Storage::State storageState = storage->init(settings); + switch (storageState) { + case Storage::NeedsSetup: + if (!setup) + return false; // trigger setup process + if (storage->setup(settings)) + return initStorage(backend, settings, false); // if setup wasn't successfull we mark the backend as unavailable - case Storage::NotAvailable: - qCritical() << "Selected storage backend is not available:" << backend; - storage->deleteLater(); - _storageBackends.remove(backend); - storage = 0; - return false; - case Storage::IsReady: - // delete all other backends - _storageBackends.remove(backend); - unregisterStorageBackends(); - connect(storage, SIGNAL(bufferInfoUpdated(UserId, const BufferInfo &)), this, SIGNAL(bufferInfoUpdated(UserId, const BufferInfo &))); - } - _storage = storage; - return true; + case Storage::NotAvailable: + qCritical() << "Selected storage backend is not available:" << backend; + storage->deleteLater(); + _storageBackends.remove(backend); + storage = 0; + return false; + case Storage::IsReady: + // delete all other backends + _storageBackends.remove(backend); + unregisterStorageBackends(); + connect(storage, SIGNAL(bufferInfoUpdated(UserId, const BufferInfo &)), this, SIGNAL(bufferInfoUpdated(UserId, const BufferInfo &))); + } + _storage = storage; + return true; } -bool Core::initStorage(QVariantMap dbSettings, bool setup) { - return initStorage(dbSettings["Backend"].toString(), dbSettings["ConnectionProperties"].toMap(), setup); + +bool Core::initStorage(QVariantMap dbSettings, bool setup) +{ + return initStorage(dbSettings["Backend"].toString(), dbSettings["ConnectionProperties"].toMap(), setup); } -void Core::syncStorage() { - if(_storage) - _storage->sync(); +void Core::syncStorage() +{ + if (_storage) + _storage->sync(); } + /*** Storage Access ***/ -bool Core::createNetwork(UserId user, NetworkInfo &info) { - NetworkId networkId = instance()->_storage->createNetwork(user, info); - if(!networkId.isValid()) - return false; +bool Core::createNetwork(UserId user, NetworkInfo &info) +{ + NetworkId networkId = instance()->_storage->createNetwork(user, info); + if (!networkId.isValid()) + return false; - info.networkId = networkId; - return true; + info.networkId = networkId; + return true; } -/*** Network Management ***/ -bool Core::startListening() { - // in mono mode we only start a local port if a port is specified in the cli call - if(Quassel::runMode() == Quassel::Monolithic && !Quassel::isOptionSet("port")) - return true; +/*** Network Management ***/ - bool success = false; - uint port = Quassel::optionValue("port").toUInt(); - - const QString listen = Quassel::optionValue("listen"); - const QStringList listen_list = listen.split(",", QString::SkipEmptyParts); - if(listen_list.size() > 0) { - foreach (const QString listen_term, listen_list) { // TODO: handle multiple interfaces for same TCP version gracefully - QHostAddress addr; - if(!addr.setAddress(listen_term)) { - qCritical() << qPrintable( - tr("Invalid listen address %1") - .arg(listen_term) - ); - } else { - switch(addr.protocol()) { - case QAbstractSocket::IPv6Protocol: - if(_v6server.listen(addr, port)) { - quInfo() << qPrintable( - tr("Listening for GUI clients on IPv6 %1 port %2 using protocol version %3") - .arg(addr.toString()) - .arg(_v6server.serverPort()) - .arg(Quassel::buildInfo().protocolVersion) - ); - success = true; - } else - quWarning() << qPrintable( - tr("Could not open IPv6 interface %1:%2: %3") - .arg(addr.toString()) - .arg(port) - .arg(_v6server.errorString())); - break; - case QAbstractSocket::IPv4Protocol: - if(_server.listen(addr, port)) { - quInfo() << qPrintable( - tr("Listening for GUI clients on IPv4 %1 port %2 using protocol version %3") - .arg(addr.toString()) - .arg(_server.serverPort()) - .arg(Quassel::buildInfo().protocolVersion) - ); - success = true; - } else { - // if v6 succeeded on Any, the port will be already in use - don't display the error then - if(!success || _server.serverError() != QAbstractSocket::AddressInUseError) - quWarning() << qPrintable( - tr("Could not open IPv4 interface %1:%2: %3") - .arg(addr.toString()) - .arg(port) - .arg(_server.errorString())); +bool Core::startListening() +{ + // in mono mode we only start a local port if a port is specified in the cli call + if (Quassel::runMode() == Quassel::Monolithic && !Quassel::isOptionSet("port")) + return true; + + bool success = false; + uint port = Quassel::optionValue("port").toUInt(); + + const QString listen = Quassel::optionValue("listen"); + const QStringList listen_list = listen.split(",", QString::SkipEmptyParts); + if (listen_list.size() > 0) { + foreach(const QString listen_term, listen_list) { // TODO: handle multiple interfaces for same TCP version gracefully + QHostAddress addr; + if (!addr.setAddress(listen_term)) { + qCritical() << qPrintable( + tr("Invalid listen address %1") + .arg(listen_term) + ); + } + else { + switch (addr.protocol()) { + case QAbstractSocket::IPv6Protocol: + if (_v6server.listen(addr, port)) { + quInfo() << qPrintable( + tr("Listening for GUI clients on IPv6 %1 port %2 using protocol version %3") + .arg(addr.toString()) + .arg(_v6server.serverPort()) + .arg(Quassel::buildInfo().protocolVersion) + ); + success = true; + } + else + quWarning() << qPrintable( + tr("Could not open IPv6 interface %1:%2: %3") + .arg(addr.toString()) + .arg(port) + .arg(_v6server.errorString())); + break; + case QAbstractSocket::IPv4Protocol: + if (_server.listen(addr, port)) { + quInfo() << qPrintable( + tr("Listening for GUI clients on IPv4 %1 port %2 using protocol version %3") + .arg(addr.toString()) + .arg(_server.serverPort()) + .arg(Quassel::buildInfo().protocolVersion) + ); + success = true; + } + else { + // if v6 succeeded on Any, the port will be already in use - don't display the error then + if (!success || _server.serverError() != QAbstractSocket::AddressInUseError) + quWarning() << qPrintable( + tr("Could not open IPv4 interface %1:%2: %3") + .arg(addr.toString()) + .arg(port) + .arg(_server.errorString())); + } + break; + default: + qCritical() << qPrintable( + tr("Invalid listen address %1, unknown network protocol") + .arg(listen_term) + ); + break; + } } - break; - default: - qCritical() << qPrintable( - tr("Invalid listen address %1, unknown network protocol") - .arg(listen_term) - ); - break; } - } } - } - if(!success) - quError() << qPrintable(tr("Could not open any network interfaces to listen on!")); + if (!success) + quError() << qPrintable(tr("Could not open any network interfaces to listen on!")); - return success; + return success; } -void Core::stopListening(const QString &reason) { - bool wasListening = false; - if(_server.isListening()) { - wasListening = true; - _server.close(); - } - if(_v6server.isListening()) { - wasListening = true; - _v6server.close(); - } - if(wasListening) { - if(reason.isEmpty()) - quInfo() << "No longer listening for GUI clients."; - else - quInfo() << qPrintable(reason); - } + +void Core::stopListening(const QString &reason) +{ + bool wasListening = false; + if (_server.isListening()) { + wasListening = true; + _server.close(); + } + if (_v6server.isListening()) { + wasListening = true; + _v6server.close(); + } + if (wasListening) { + if (reason.isEmpty()) + quInfo() << "No longer listening for GUI clients."; + else + quInfo() << qPrintable(reason); + } } -void Core::incomingConnection() { - QTcpServer *server = qobject_cast(sender()); - Q_ASSERT(server); - while(server->hasPendingConnections()) { - QTcpSocket *socket = server->nextPendingConnection(); - connect(socket, SIGNAL(disconnected()), this, SLOT(clientDisconnected())); - connect(socket, SIGNAL(readyRead()), this, SLOT(clientHasData())); - connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError))); - - QVariantMap clientInfo; - blocksizes.insert(socket, (quint32)0); - quInfo() << qPrintable(tr("Client connected from")) << qPrintable(socket->peerAddress().toString()); - - if(!_configured) { - stopListening(tr("Closing server for basic setup.")); + +void Core::incomingConnection() +{ + QTcpServer *server = qobject_cast(sender()); + Q_ASSERT(server); + while (server->hasPendingConnections()) { + QTcpSocket *socket = server->nextPendingConnection(); + connect(socket, SIGNAL(disconnected()), this, SLOT(clientDisconnected())); + connect(socket, SIGNAL(readyRead()), this, SLOT(clientHasData())); + connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError))); + + QVariantMap clientInfo; + blocksizes.insert(socket, (quint32)0); + quInfo() << qPrintable(tr("Client connected from")) << qPrintable(socket->peerAddress().toString()); + + if (!_configured) { + stopListening(tr("Closing server for basic setup.")); + } } - } } -void Core::clientHasData() { - QTcpSocket *socket = dynamic_cast(sender()); - Q_ASSERT(socket && blocksizes.contains(socket)); - QVariant item; - while(SignalProxy::readDataFromDevice(socket, blocksizes[socket], item)) { - QVariantMap msg = item.toMap(); - processClientMessage(socket, msg); - if(!blocksizes.contains(socket)) break; // this socket is no longer ours to handle! - } + +void Core::clientHasData() +{ + QTcpSocket *socket = dynamic_cast(sender()); + Q_ASSERT(socket && blocksizes.contains(socket)); + QVariant item; + while (SignalProxy::readDataFromDevice(socket, blocksizes[socket], item)) { + QVariantMap msg = item.toMap(); + processClientMessage(socket, msg); + if (!blocksizes.contains(socket)) break; // this socket is no longer ours to handle! + } } -void Core::processClientMessage(QTcpSocket *socket, const QVariantMap &msg) { - if(!msg.contains("MsgType")) { - // Client is way too old, does not even use the current init format - qWarning() << qPrintable(tr("Antique client trying to connect... refusing.")); - socket->close(); - return; - } - // OK, so we have at least an init message format we can understand - if(msg["MsgType"] == "ClientInit") { - QVariantMap reply; - - // Just version information -- check it! - uint ver = msg["ProtocolVersion"].toUInt(); - if(ver < Quassel::buildInfo().coreNeedsProtocol) { - reply["MsgType"] = "ClientInitReject"; - reply["Error"] = tr("Your Quassel Client is too old!
" - "This core needs at least client/core protocol version %1.
" - "Please consider upgrading your client.").arg(Quassel::buildInfo().coreNeedsProtocol); - SignalProxy::writeDataToDevice(socket, reply); - qWarning() << qPrintable(tr("Client")) << qPrintable(socket->peerAddress().toString()) << qPrintable(tr("too old, rejecting.")); - socket->close(); return; + +void Core::processClientMessage(QTcpSocket *socket, const QVariantMap &msg) +{ + if (!msg.contains("MsgType")) { + // Client is way too old, does not even use the current init format + qWarning() << qPrintable(tr("Antique client trying to connect... refusing.")); + socket->close(); + return; } + // OK, so we have at least an init message format we can understand + if (msg["MsgType"] == "ClientInit") { + QVariantMap reply; + + // Just version information -- check it! + uint ver = msg["ProtocolVersion"].toUInt(); + if (ver < Quassel::buildInfo().coreNeedsProtocol) { + reply["MsgType"] = "ClientInitReject"; + reply["Error"] = tr("Your Quassel Client is too old!
" + "This core needs at least client/core protocol version %1.
" + "Please consider upgrading your client.").arg(Quassel::buildInfo().coreNeedsProtocol); + SignalProxy::writeDataToDevice(socket, reply); + qWarning() << qPrintable(tr("Client")) << qPrintable(socket->peerAddress().toString()) << qPrintable(tr("too old, rejecting.")); + socket->close(); return; + } - reply["ProtocolVersion"] = Quassel::buildInfo().protocolVersion; - reply["CoreVersion"] = Quassel::buildInfo().fancyVersionString; - reply["CoreDate"] = Quassel::buildInfo().buildDate; - reply["CoreStartTime"] = startTime(); // v10 clients don't necessarily parse this, see below + reply["ProtocolVersion"] = Quassel::buildInfo().protocolVersion; + reply["CoreVersion"] = Quassel::buildInfo().fancyVersionString; + reply["CoreDate"] = Quassel::buildInfo().buildDate; + reply["CoreStartTime"] = startTime(); // v10 clients don't necessarily parse this, see below - // FIXME: newer clients no longer use the hardcoded CoreInfo (for now), since it gets the - // time zone wrong. With the next protocol bump (10 -> 11), we should remove this - // or make it properly configurable. + // FIXME: newer clients no longer use the hardcoded CoreInfo (for now), since it gets the + // time zone wrong. With the next protocol bump (10 -> 11), we should remove this + // or make it properly configurable. - int uptime = startTime().secsTo(QDateTime::currentDateTime().toUTC()); - int updays = uptime / 86400; uptime %= 86400; - int uphours = uptime / 3600; uptime %= 3600; - int upmins = uptime / 60; - reply["CoreInfo"] = tr("Quassel Core Version %1
" - "Built: %2
" - "Up %3d%4h%5m (since %6)").arg(Quassel::buildInfo().fancyVersionString) - .arg(Quassel::buildInfo().buildDate) - .arg(updays).arg(uphours,2,10,QChar('0')).arg(upmins,2,10,QChar('0')).arg(startTime().toString(Qt::TextDate)); + int uptime = startTime().secsTo(QDateTime::currentDateTime().toUTC()); + int updays = uptime / 86400; uptime %= 86400; + int uphours = uptime / 3600; uptime %= 3600; + int upmins = uptime / 60; + reply["CoreInfo"] = tr("Quassel Core Version %1
" + "Built: %2
" + "Up %3d%4h%5m (since %6)").arg(Quassel::buildInfo().fancyVersionString) + .arg(Quassel::buildInfo().buildDate) + .arg(updays).arg(uphours, 2, 10, QChar('0')).arg(upmins, 2, 10, QChar('0')).arg(startTime().toString(Qt::TextDate)); - reply["CoreFeatures"] = (int)Quassel::features(); + reply["CoreFeatures"] = (int)Quassel::features(); #ifdef HAVE_SSL - SslServer *sslServer = qobject_cast(&_server); - QSslSocket *sslSocket = qobject_cast(socket); - bool supportSsl = (bool)sslServer && (bool)sslSocket && sslServer->isCertValid(); + SslServer *sslServer = qobject_cast(&_server); + QSslSocket *sslSocket = qobject_cast(socket); + bool supportSsl = (bool)sslServer && (bool)sslSocket && sslServer->isCertValid(); #else - bool supportSsl = false; + bool supportSsl = false; #endif #ifndef QT_NO_COMPRESS - bool supportsCompression = true; + bool supportsCompression = true; #else - bool supportsCompression = false; + bool supportsCompression = false; #endif - reply["SupportSsl"] = supportSsl; - reply["SupportsCompression"] = supportsCompression; - // switch to ssl/compression after client has been informed about our capabilities (see below) - - reply["LoginEnabled"] = true; - - // check if we are configured, start wizard otherwise - if(!_configured) { - reply["Configured"] = false; - QList backends; - foreach(Storage *backend, _storageBackends.values()) { - QVariantMap v; - v["DisplayName"] = backend->displayName(); - v["Description"] = backend->description(); - v["SetupKeys"] = backend->setupKeys(); - v["SetupDefaults"] = backend->setupDefaults(); - backends.append(v); - } - reply["StorageBackends"] = backends; - reply["LoginEnabled"] = false; - } else { - reply["Configured"] = true; - } - clientInfo[socket] = msg; // store for future reference - reply["MsgType"] = "ClientInitAck"; - SignalProxy::writeDataToDevice(socket, reply); - socket->flush(); // ensure that the write cache is flushed before we switch to ssl + reply["SupportSsl"] = supportSsl; + reply["SupportsCompression"] = supportsCompression; + // switch to ssl/compression after client has been informed about our capabilities (see below) + + reply["LoginEnabled"] = true; + + // check if we are configured, start wizard otherwise + if (!_configured) { + reply["Configured"] = false; + QList backends; + foreach(Storage *backend, _storageBackends.values()) { + QVariantMap v; + v["DisplayName"] = backend->displayName(); + v["Description"] = backend->description(); + v["SetupKeys"] = backend->setupKeys(); + v["SetupDefaults"] = backend->setupDefaults(); + backends.append(v); + } + reply["StorageBackends"] = backends; + reply["LoginEnabled"] = false; + } + else { + reply["Configured"] = true; + } + clientInfo[socket] = msg; // store for future reference + reply["MsgType"] = "ClientInitAck"; + SignalProxy::writeDataToDevice(socket, reply); + socket->flush(); // ensure that the write cache is flushed before we switch to ssl #ifdef HAVE_SSL - // after we told the client that we are ssl capable we switch to ssl mode - if(supportSsl && msg["UseSsl"].toBool()) { - qDebug() << qPrintable(tr("Starting TLS for Client:")) << qPrintable(socket->peerAddress().toString()); - connect(sslSocket, SIGNAL(sslErrors(const QList &)), this, SLOT(sslErrors(const QList &))); - sslSocket->startServerEncryption(); - } + // after we told the client that we are ssl capable we switch to ssl mode + if (supportSsl && msg["UseSsl"].toBool()) { + qDebug() << qPrintable(tr("Starting TLS for Client:")) << qPrintable(socket->peerAddress().toString()); + connect(sslSocket, SIGNAL(sslErrors(const QList &)), this, SLOT(sslErrors(const QList &))); + sslSocket->startServerEncryption(); + } #endif #ifndef QT_NO_COMPRESS - if(supportsCompression && msg["UseCompression"].toBool()) { - socket->setProperty("UseCompression", true); - qDebug() << "Using compression for Client:" << qPrintable(socket->peerAddress().toString()); - } + if (supportsCompression && msg["UseCompression"].toBool()) { + socket->setProperty("UseCompression", true); + qDebug() << "Using compression for Client:" << qPrintable(socket->peerAddress().toString()); + } #endif - - } else { - // for the rest, we need an initialized connection - if(!clientInfo.contains(socket)) { - QVariantMap reply; - reply["MsgType"] = "ClientLoginReject"; - reply["Error"] = tr("Client not initialized!
You need to send an init message before trying to login."); - SignalProxy::writeDataToDevice(socket, reply); - qWarning() << qPrintable(tr("Client")) << qPrintable(socket->peerAddress().toString()) << qPrintable(tr("did not send an init message before trying to login, rejecting.")); - socket->close(); return; } - if(msg["MsgType"] == "CoreSetupData") { - QVariantMap reply; - QString result = setupCore(msg["SetupData"].toMap()); - if(!result.isEmpty()) { - reply["MsgType"] = "CoreSetupReject"; - reply["Error"] = result; - } else { - reply["MsgType"] = "CoreSetupAck"; - } - SignalProxy::writeDataToDevice(socket, reply); - } else if(msg["MsgType"] == "ClientLogin") { - QVariantMap reply; - UserId uid = _storage->validateUser(msg["User"].toString(), msg["Password"].toString()); - if(uid == 0) { - reply["MsgType"] = "ClientLoginReject"; - reply["Error"] = tr("Invalid username or password!
The username/password combination you supplied could not be found in the database."); - SignalProxy::writeDataToDevice(socket, reply); - return; - } - reply["MsgType"] = "ClientLoginAck"; - SignalProxy::writeDataToDevice(socket, reply); - quInfo() << qPrintable(tr("Client")) << qPrintable(socket->peerAddress().toString()) << qPrintable(tr("initialized and authenticated successfully as \"%1\" (UserId: %2).").arg(msg["User"].toString()).arg(uid.toInt())); - setupClientSession(socket, uid); + else { + // for the rest, we need an initialized connection + if (!clientInfo.contains(socket)) { + QVariantMap reply; + reply["MsgType"] = "ClientLoginReject"; + reply["Error"] = tr("Client not initialized!
You need to send an init message before trying to login."); + SignalProxy::writeDataToDevice(socket, reply); + qWarning() << qPrintable(tr("Client")) << qPrintable(socket->peerAddress().toString()) << qPrintable(tr("did not send an init message before trying to login, rejecting.")); + socket->close(); return; + } + if (msg["MsgType"] == "CoreSetupData") { + QVariantMap reply; + QString result = setupCore(msg["SetupData"].toMap()); + if (!result.isEmpty()) { + reply["MsgType"] = "CoreSetupReject"; + reply["Error"] = result; + } + else { + reply["MsgType"] = "CoreSetupAck"; + } + SignalProxy::writeDataToDevice(socket, reply); + } + else if (msg["MsgType"] == "ClientLogin") { + QVariantMap reply; + UserId uid = _storage->validateUser(msg["User"].toString(), msg["Password"].toString()); + if (uid == 0) { + reply["MsgType"] = "ClientLoginReject"; + reply["Error"] = tr("Invalid username or password!
The username/password combination you supplied could not be found in the database."); + SignalProxy::writeDataToDevice(socket, reply); + return; + } + reply["MsgType"] = "ClientLoginAck"; + SignalProxy::writeDataToDevice(socket, reply); + quInfo() << qPrintable(tr("Client")) << qPrintable(socket->peerAddress().toString()) << qPrintable(tr("initialized and authenticated successfully as \"%1\" (UserId: %2).").arg(msg["User"].toString()).arg(uid.toInt())); + setupClientSession(socket, uid); + } } - } } + // Potentially called during the initialization phase (before handing the connection off to the session) -void Core::clientDisconnected() { - QTcpSocket *socket = qobject_cast(sender()); - if(socket) { - // here it's safe to call methods on socket! - quInfo() << qPrintable(tr("Non-authed client disconnected.")) << qPrintable(socket->peerAddress().toString()); - blocksizes.remove(socket); - clientInfo.remove(socket); - socket->deleteLater(); - } else { - // we have to crawl through the hashes and see if we find a victim to remove - qDebug() << qPrintable(tr("Non-authed client disconnected. (socket allready destroyed)")); - - // DO NOT CALL ANY METHODS ON socket!! - socket = static_cast(sender()); - - QHash::iterator blockSizeIter = blocksizes.begin(); - while(blockSizeIter != blocksizes.end()) { - if(blockSizeIter.key() == socket) { - blockSizeIter = blocksizes.erase(blockSizeIter); - } else { - blockSizeIter++; - } +void Core::clientDisconnected() +{ + QTcpSocket *socket = qobject_cast(sender()); + if (socket) { + // here it's safe to call methods on socket! + quInfo() << qPrintable(tr("Non-authed client disconnected.")) << qPrintable(socket->peerAddress().toString()); + blocksizes.remove(socket); + clientInfo.remove(socket); + socket->deleteLater(); } + else { + // we have to crawl through the hashes and see if we find a victim to remove + qDebug() << qPrintable(tr("Non-authed client disconnected. (socket allready destroyed)")); - QHash::iterator clientInfoIter = clientInfo.begin(); - while(clientInfoIter != clientInfo.end()) { - if(clientInfoIter.key() == socket) { - clientInfoIter = clientInfo.erase(clientInfoIter); - } else { - clientInfoIter++; - } - } - } + // DO NOT CALL ANY METHODS ON socket!! + socket = static_cast(sender()); + QHash::iterator blockSizeIter = blocksizes.begin(); + while (blockSizeIter != blocksizes.end()) { + if (blockSizeIter.key() == socket) { + blockSizeIter = blocksizes.erase(blockSizeIter); + } + else { + blockSizeIter++; + } + } - // make server listen again if still not configured - if (!_configured) { - startListening(); - } + QHash::iterator clientInfoIter = clientInfo.begin(); + while (clientInfoIter != clientInfo.end()) { + if (clientInfoIter.key() == socket) { + clientInfoIter = clientInfo.erase(clientInfoIter); + } + else { + clientInfoIter++; + } + } + } - // TODO remove unneeded sessions - if necessary/possible... - // Suggestion: kill sessions if they are not connected to any network and client. + // make server listen again if still not configured + if (!_configured) { + startListening(); + } + + // TODO remove unneeded sessions - if necessary/possible... + // Suggestion: kill sessions if they are not connected to any network and client. } -void Core::setupClientSession(QTcpSocket *socket, UserId uid) { - // From now on everything is handled by the client session - disconnect(socket, 0, this, 0); - socket->flush(); - blocksizes.remove(socket); - clientInfo.remove(socket); - - // Find or create session for validated user - SessionThread *session; - if(sessions.contains(uid)) { - session = sessions[uid]; - } else { - session = createSession(uid); - if(!session) { - qWarning() << qPrintable(tr("Could not initialize session for client:")) << qPrintable(socket->peerAddress().toString()); - socket->close(); - return; + +void Core::setupClientSession(QTcpSocket *socket, UserId uid) +{ + // From now on everything is handled by the client session + disconnect(socket, 0, this, 0); + socket->flush(); + blocksizes.remove(socket); + clientInfo.remove(socket); + + // Find or create session for validated user + SessionThread *session; + if (sessions.contains(uid)) { + session = sessions[uid]; + } + else { + session = createSession(uid); + if (!session) { + qWarning() << qPrintable(tr("Could not initialize session for client:")) << qPrintable(socket->peerAddress().toString()); + socket->close(); + return; + } } - } - // as we are currently handling an event triggered by incoming data on this socket - // it is unsafe to directly move the socket to the client thread. - QCoreApplication::postEvent(this, new AddClientEvent(socket, uid)); + // as we are currently handling an event triggered by incoming data on this socket + // it is unsafe to directly move the socket to the client thread. + QCoreApplication::postEvent(this, new AddClientEvent(socket, uid)); } -void Core::customEvent(QEvent *event) { - if(event->type() == AddClientEventId) { - AddClientEvent *addClientEvent = static_cast(event); - addClientHelper(addClientEvent->socket, addClientEvent->userId); - return; - } + +void Core::customEvent(QEvent *event) +{ + if (event->type() == AddClientEventId) { + AddClientEvent *addClientEvent = static_cast(event); + addClientHelper(addClientEvent->socket, addClientEvent->userId); + return; + } } -void Core::addClientHelper(QTcpSocket *socket, UserId uid) { - // Find or create session for validated user - if(!sessions.contains(uid)) { - qWarning() << qPrintable(tr("Could not find a session for client:")) << qPrintable(socket->peerAddress().toString()); - socket->close(); - return; - } - SessionThread *session = sessions[uid]; - session->addClient(socket); +void Core::addClientHelper(QTcpSocket *socket, UserId uid) +{ + // Find or create session for validated user + if (!sessions.contains(uid)) { + qWarning() << qPrintable(tr("Could not find a session for client:")) << qPrintable(socket->peerAddress().toString()); + socket->close(); + return; + } + + SessionThread *session = sessions[uid]; + session->addClient(socket); } -void Core::setupInternalClientSession(SignalProxy *proxy) { - if(!_configured) { - stopListening(); - setupCoreForInternalUsage(); - } - - UserId uid; - if(_storage) { - uid = _storage->internalUser(); - } else { - qWarning() << "Core::setupInternalClientSession(): You're trying to run monolithic Quassel with an unusable Backend! Go fix it!"; - return; - } - - // Find or create session for validated user - SessionThread *sess; - if(sessions.contains(uid)) - sess = sessions[uid]; - else - sess = createSession(uid); - sess->addClient(proxy); + +void Core::setupInternalClientSession(SignalProxy *proxy) +{ + if (!_configured) { + stopListening(); + setupCoreForInternalUsage(); + } + + UserId uid; + if (_storage) { + uid = _storage->internalUser(); + } + else { + qWarning() << "Core::setupInternalClientSession(): You're trying to run monolithic Quassel with an unusable Backend! Go fix it!"; + return; + } + + // Find or create session for validated user + SessionThread *sess; + if (sessions.contains(uid)) + sess = sessions[uid]; + else + sess = createSession(uid); + sess->addClient(proxy); } -SessionThread *Core::createSession(UserId uid, bool restore) { - if(sessions.contains(uid)) { - qWarning() << "Calling createSession() when a session for the user already exists!"; - return 0; - } - SessionThread *sess = new SessionThread(uid, restore, this); - sessions[uid] = sess; - sess->start(); - return sess; + +SessionThread *Core::createSession(UserId uid, bool restore) +{ + if (sessions.contains(uid)) { + qWarning() << "Calling createSession() when a session for the user already exists!"; + return 0; + } + SessionThread *sess = new SessionThread(uid, restore, this); + sessions[uid] = sess; + sess->start(); + return sess; } + #ifdef HAVE_SSL -void Core::sslErrors(const QList &errors) { - Q_UNUSED(errors); - QSslSocket *socket = qobject_cast(sender()); - if(socket) - socket->ignoreSslErrors(); +void Core::sslErrors(const QList &errors) +{ + Q_UNUSED(errors); + QSslSocket *socket = qobject_cast(sender()); + if (socket) + socket->ignoreSslErrors(); } + + #endif -void Core::socketError(QAbstractSocket::SocketError err) { - QAbstractSocket *socket = qobject_cast(sender()); - if(socket && err != QAbstractSocket::RemoteHostClosedError) - qWarning() << "Core::socketError()" << socket << err << socket->errorString(); +void Core::socketError(QAbstractSocket::SocketError err) +{ + QAbstractSocket *socket = qobject_cast(sender()); + if (socket && err != QAbstractSocket::RemoteHostClosedError) + qWarning() << "Core::socketError()" << socket << err << socket->errorString(); } + // migration / backend selection -bool Core::selectBackend(const QString &backend) { - // reregister all storage backends - registerStorageBackends(); - if(!_storageBackends.contains(backend)) { - qWarning() << qPrintable(QString("Core::selectBackend(): unsupported backend: %1").arg(backend)); - qWarning() << " supported backends are:" << qPrintable(QStringList(_storageBackends.keys()).join(", ")); - return false; - } - - Storage *storage = _storageBackends[backend]; - QVariantMap settings = promptForSettings(storage); - - Storage::State storageState = storage->init(settings); - switch(storageState) { - case Storage::IsReady: - saveBackendSettings(backend, settings); - qWarning() << "Switched backend to:" << qPrintable(backend); - qWarning() << "Backend already initialized. Skipping Migration"; - return true; - case Storage::NotAvailable: - qCritical() << "Backend is not available:" << qPrintable(backend); - return false; - case Storage::NeedsSetup: - if(!storage->setup(settings)) { - qWarning() << qPrintable(QString("Core::selectBackend(): unable to setup backend: %1").arg(backend)); - return false; +bool Core::selectBackend(const QString &backend) +{ + // reregister all storage backends + registerStorageBackends(); + if (!_storageBackends.contains(backend)) { + qWarning() << qPrintable(QString("Core::selectBackend(): unsupported backend: %1").arg(backend)); + qWarning() << " supported backends are:" << qPrintable(QStringList(_storageBackends.keys()).join(", ")); + return false; } - if(storage->init(settings) != Storage::IsReady) { - qWarning() << qPrintable(QString("Core::migrateBackend(): unable to initialize backend: %1").arg(backend)); - return false; + Storage *storage = _storageBackends[backend]; + QVariantMap settings = promptForSettings(storage); + + Storage::State storageState = storage->init(settings); + switch (storageState) { + case Storage::IsReady: + saveBackendSettings(backend, settings); + qWarning() << "Switched backend to:" << qPrintable(backend); + qWarning() << "Backend already initialized. Skipping Migration"; + return true; + case Storage::NotAvailable: + qCritical() << "Backend is not available:" << qPrintable(backend); + return false; + case Storage::NeedsSetup: + if (!storage->setup(settings)) { + qWarning() << qPrintable(QString("Core::selectBackend(): unable to setup backend: %1").arg(backend)); + return false; + } + + if (storage->init(settings) != Storage::IsReady) { + qWarning() << qPrintable(QString("Core::migrateBackend(): unable to initialize backend: %1").arg(backend)); + return false; + } + + saveBackendSettings(backend, settings); + qWarning() << "Switched backend to:" << qPrintable(backend); + break; } - saveBackendSettings(backend, settings); - qWarning() << "Switched backend to:" << qPrintable(backend); - break; - } - - // let's see if we have a current storage object we can migrate from - AbstractSqlMigrationReader *reader = getMigrationReader(_storage); - AbstractSqlMigrationWriter *writer = getMigrationWriter(storage); - if(reader && writer) { - qDebug() << qPrintable(QString("Migrating Storage backend %1 to %2...").arg(_storage->displayName(), storage->displayName())); - delete _storage; - _storage = 0; - delete storage; - storage = 0; - if(reader->migrateTo(writer)) { - qDebug() << "Migration finished!"; - saveBackendSettings(backend, settings); - return true; + // let's see if we have a current storage object we can migrate from + AbstractSqlMigrationReader *reader = getMigrationReader(_storage); + AbstractSqlMigrationWriter *writer = getMigrationWriter(storage); + if (reader && writer) { + qDebug() << qPrintable(QString("Migrating Storage backend %1 to %2...").arg(_storage->displayName(), storage->displayName())); + delete _storage; + _storage = 0; + delete storage; + storage = 0; + if (reader->migrateTo(writer)) { + qDebug() << "Migration finished!"; + saveBackendSettings(backend, settings); + return true; + } + return false; + qWarning() << qPrintable(QString("Core::migrateDb(): unable to migrate storage backend! (No migration writer for %1)").arg(backend)); } - return false; - qWarning() << qPrintable(QString("Core::migrateDb(): unable to migrate storage backend! (No migration writer for %1)").arg(backend)); - } - - // inform the user why we cannot merge - if(!_storage) { - qWarning() << "No currently active backend. Skipping migration."; - } else if(!reader) { - qWarning() << "Currently active backend does not support migration:" << qPrintable(_storage->displayName()); - } - if(writer) { - qWarning() << "New backend does not support migration:" << qPrintable(backend); - } - - // so we were unable to merge, but let's create a user \o/ - _storage = storage; - createUser(); - return true; -} -void Core::createUser() { - QTextStream out(stdout); - QTextStream in(stdin); - out << "Add a new user:" << endl; - out << "Username: "; - out.flush(); - QString username = in.readLine().trimmed(); - - disableStdInEcho(); - out << "Password: "; - out.flush(); - QString password = in.readLine().trimmed(); - out << endl; - out << "Repeat Password: "; - out.flush(); - QString password2 = in.readLine().trimmed(); - out << endl; - enableStdInEcho(); - - if(password != password2) { - qWarning() << "Passwords don't match!"; - return; - } - if(password.isEmpty()) { - qWarning() << "Password is empty!"; - return; - } - - if(_configured && _storage->addUser(username, password).isValid()) { - out << "Added user " << username << " successfully!" << endl; - } else { - qWarning() << "Unable to add user:" << qPrintable(username); - } -} + // inform the user why we cannot merge + if (!_storage) { + qWarning() << "No currently active backend. Skipping migration."; + } + else if (!reader) { + qWarning() << "Currently active backend does not support migration:" << qPrintable(_storage->displayName()); + } + if (writer) { + qWarning() << "New backend does not support migration:" << qPrintable(backend); + } -void Core::changeUserPass(const QString &username) { - QTextStream out(stdout); - QTextStream in(stdin); - UserId userId = _storage->getUserId(username); - if(!userId.isValid()) { - out << "User " << username << " does not exist." << endl; - return; - } - - out << "Change password for user: " << username << endl; - - disableStdInEcho(); - out << "New Password: "; - out.flush(); - QString password = in.readLine().trimmed(); - out << endl; - out << "Repeat Password: "; - out.flush(); - QString password2 = in.readLine().trimmed(); - out << endl; - enableStdInEcho(); - - if(password != password2) { - qWarning() << "Passwords don't match!"; - return; - } - if(password.isEmpty()) { - qWarning() << "Password is empty!"; - return; - } - - if(_configured && _storage->updateUser(userId, password)) { - out << "Password changed successfully!" << endl; - } else { - qWarning() << "Failed to change password!"; - } + // so we were unable to merge, but let's create a user \o/ + _storage = storage; + createUser(); + return true; } -AbstractSqlMigrationReader *Core::getMigrationReader(Storage *storage) { - if(!storage) - return 0; - - AbstractSqlStorage *sqlStorage = qobject_cast(storage); - if(!sqlStorage) { - qDebug() << "Core::migrateDb(): only SQL based backends can be migrated!"; - return 0; - } - return sqlStorage->createMigrationReader(); -} +void Core::createUser() +{ + QTextStream out(stdout); + QTextStream in(stdin); + out << "Add a new user:" << endl; + out << "Username: "; + out.flush(); + QString username = in.readLine().trimmed(); -AbstractSqlMigrationWriter *Core::getMigrationWriter(Storage *storage) { - if(!storage) - return 0; + disableStdInEcho(); + out << "Password: "; + out.flush(); + QString password = in.readLine().trimmed(); + out << endl; + out << "Repeat Password: "; + out.flush(); + QString password2 = in.readLine().trimmed(); + out << endl; + enableStdInEcho(); - AbstractSqlStorage *sqlStorage = qobject_cast(storage); - if(!sqlStorage) { - qDebug() << "Core::migrateDb(): only SQL based backends can be migrated!"; - return 0; - } + if (password != password2) { + qWarning() << "Passwords don't match!"; + return; + } + if (password.isEmpty()) { + qWarning() << "Password is empty!"; + return; + } - return sqlStorage->createMigrationWriter(); + if (_configured && _storage->addUser(username, password).isValid()) { + out << "Added user " << username << " successfully!" << endl; + } + else { + qWarning() << "Unable to add user:" << qPrintable(username); + } } -void Core::saveBackendSettings(const QString &backend, const QVariantMap &settings) { - QVariantMap dbsettings; - dbsettings["Backend"] = backend; - dbsettings["ConnectionProperties"] = settings; - CoreSettings().setStorageSettings(dbsettings); -} -QVariantMap Core::promptForSettings(const Storage *storage) { - QVariantMap settings; +void Core::changeUserPass(const QString &username) +{ + QTextStream out(stdout); + QTextStream in(stdin); + UserId userId = _storage->getUserId(username); + if (!userId.isValid()) { + out << "User " << username << " does not exist." << endl; + return; + } - QStringList keys = storage->setupKeys(); - if(keys.isEmpty()) - return settings; + out << "Change password for user: " << username << endl; - QTextStream out(stdout); - QTextStream in(stdin); - out << "Default values are in brackets" << endl; + disableStdInEcho(); + out << "New Password: "; + out.flush(); + QString password = in.readLine().trimmed(); + out << endl; + out << "Repeat Password: "; + out.flush(); + QString password2 = in.readLine().trimmed(); + out << endl; + enableStdInEcho(); - QVariantMap defaults = storage->setupDefaults(); - QString value; - foreach(QString key, keys) { - QVariant val; - if(defaults.contains(key)) { - val = defaults[key]; + if (password != password2) { + qWarning() << "Passwords don't match!"; + return; } - out << key; - if(!val.toString().isEmpty()) { - out << " (" << val.toString() << ")"; + if (password.isEmpty()) { + qWarning() << "Password is empty!"; + return; } - out << ": "; - out.flush(); - bool noEcho = QString("password").toLower().startsWith(key.toLower()); - if(noEcho) { - disableStdInEcho(); + if (_configured && _storage->updateUser(userId, password)) { + out << "Password changed successfully!" << endl; } - value = in.readLine().trimmed(); - if(noEcho) { - out << endl; - enableStdInEcho(); + else { + qWarning() << "Failed to change password!"; } +} + - if(!value.isEmpty()) { - switch(defaults[key].type()) { - case QVariant::Int: - val = QVariant(value.toInt()); - break; - default: - val = QVariant(value); - } +AbstractSqlMigrationReader *Core::getMigrationReader(Storage *storage) +{ + if (!storage) + return 0; + + AbstractSqlStorage *sqlStorage = qobject_cast(storage); + if (!sqlStorage) { + qDebug() << "Core::migrateDb(): only SQL based backends can be migrated!"; + return 0; } - settings[key] = val; - } - return settings; + + return sqlStorage->createMigrationReader(); +} + + +AbstractSqlMigrationWriter *Core::getMigrationWriter(Storage *storage) +{ + if (!storage) + return 0; + + AbstractSqlStorage *sqlStorage = qobject_cast(storage); + if (!sqlStorage) { + qDebug() << "Core::migrateDb(): only SQL based backends can be migrated!"; + return 0; + } + + return sqlStorage->createMigrationWriter(); +} + + +void Core::saveBackendSettings(const QString &backend, const QVariantMap &settings) +{ + QVariantMap dbsettings; + dbsettings["Backend"] = backend; + dbsettings["ConnectionProperties"] = settings; + CoreSettings().setStorageSettings(dbsettings); +} + + +QVariantMap Core::promptForSettings(const Storage *storage) +{ + QVariantMap settings; + + QStringList keys = storage->setupKeys(); + if (keys.isEmpty()) + return settings; + + QTextStream out(stdout); + QTextStream in(stdin); + out << "Default values are in brackets" << endl; + + QVariantMap defaults = storage->setupDefaults(); + QString value; + foreach(QString key, keys) { + QVariant val; + if (defaults.contains(key)) { + val = defaults[key]; + } + out << key; + if (!val.toString().isEmpty()) { + out << " (" << val.toString() << ")"; + } + out << ": "; + out.flush(); + + bool noEcho = QString("password").toLower().startsWith(key.toLower()); + if (noEcho) { + disableStdInEcho(); + } + value = in.readLine().trimmed(); + if (noEcho) { + out << endl; + enableStdInEcho(); + } + + if (!value.isEmpty()) { + switch (defaults[key].type()) { + case QVariant::Int: + val = QVariant(value.toInt()); + break; + default: + val = QVariant(value); + } + } + settings[key] = val; + } + return settings; } #ifdef Q_OS_WIN32 -void Core::stdInEcho(bool on) { - HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); - DWORD mode = 0; - GetConsoleMode(hStdin, &mode); - if(on) - mode |= ENABLE_ECHO_INPUT; - else - mode &= ~ENABLE_ECHO_INPUT; - SetConsoleMode(hStdin, mode); +void Core::stdInEcho(bool on) +{ + HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); + DWORD mode = 0; + GetConsoleMode(hStdin, &mode); + if (on) + mode |= ENABLE_ECHO_INPUT; + else + mode &= ~ENABLE_ECHO_INPUT; + SetConsoleMode(hStdin, mode); } + + #else -void Core::stdInEcho(bool on) { - termios t; - tcgetattr(STDIN_FILENO, &t); - if(on) - t.c_lflag |= ECHO; - else - t.c_lflag &= ~ECHO; - tcsetattr(STDIN_FILENO, TCSANOW, &t); +void Core::stdInEcho(bool on) +{ + termios t; + tcgetattr(STDIN_FILENO, &t); + if (on) + t.c_lflag |= ECHO; + else + t.c_lflag &= ~ECHO; + tcsetattr(STDIN_FILENO, TCSANOW, &t); } + + #endif /* Q_OS_WIN32 */ diff --git a/src/core/core.h b/src/core/core.h index 6ee511a4..045b8f3c 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -49,449 +49,519 @@ struct NetworkInfo; class AbstractSqlMigrationReader; class AbstractSqlMigrationWriter; -class Core : public QObject { - Q_OBJECT +class Core : public QObject +{ + Q_OBJECT public: - static Core *instance(); - static void destroy(); - - static void saveState(); - static void restoreState(); - - /*** Storage access ***/ - // These methods are threadsafe. - - //! Store a user setting persistently - /** - * \param userId The users Id - * \param settingName The Name of the Setting - * \param data The Value - */ - static inline void setUserSetting(UserId userId, const QString &settingName, const QVariant &data) { - instance()->_storage->setUserSetting(userId, settingName, data); - } - - //! Retrieve a persistent user setting - /** - * \param userId The users Id - * \param settingName The Name of the Setting - * \param defaultValue Value to return in case it's unset. - * \return the Value of the Setting or the default value if it is unset. - */ - static inline QVariant getUserSetting(UserId userId, const QString &settingName, const QVariant &defaultValue = QVariant()) { - return instance()->_storage->getUserSetting(userId, settingName, defaultValue); - } - - /* Identity handling */ - static inline IdentityId createIdentity(UserId user, CoreIdentity &identity) { - return instance()->_storage->createIdentity(user, identity); - } - static bool updateIdentity(UserId user, const CoreIdentity &identity) { - return instance()->_storage->updateIdentity(user, identity); - } - static void removeIdentity(UserId user, IdentityId identityId) { - instance()->_storage->removeIdentity(user, identityId); - } - static QList identities(UserId user) { - return instance()->_storage->identities(user); - } - - //! Create a Network in the Storage and store it's Id in the given NetworkInfo - /** \note This method is thredsafe. - * - * \param user The core user - * \param networkInfo a NetworkInfo definition to store the newly created ID in - * \return true if successfull. - */ - static bool createNetwork(UserId user, NetworkInfo &info); - - //! Apply the changes to NetworkInfo info to the storage engine - /** \note This method is thredsafe. - * - * \param user The core user - * \param networkInfo The Updated NetworkInfo - * \return true if successfull. - */ - static inline bool updateNetwork(UserId user, const NetworkInfo &info) { - return instance()->_storage->updateNetwork(user, info); - } - - //! Permanently remove a Network and all the data associated with it. - /** \note This method is thredsafe. - * - * \param user The core user - * \param networkId The network to delete - * \return true if successfull. - */ - static inline bool removeNetwork(UserId user, const NetworkId &networkId) { - return instance()->_storage->removeNetwork(user, networkId); - } - - //! Returns a list of all NetworkInfos for the given UserId user - /** \note This method is thredsafe. - * - * \param user The core user - * \return QList. - */ - static inline QList networks(UserId user) { - return instance()->_storage->networks(user); - } - - //! Get a list of Networks to restore - /** Return a list of networks the user was connected at the time of core shutdown - * \note This method is threadsafe. - * - * \param user The User Id in question - */ - static inline QList connectedNetworks(UserId user) { - return instance()->_storage->connectedNetworks(user); - } - - //! Update the connected state of a network - /** \note This method is threadsafe - * - * \param user The Id of the networks owner - * \param networkId The Id of the network - * \param isConnected whether the network is connected or not - */ - static inline void setNetworkConnected(UserId user, const NetworkId &networkId, bool isConnected) { - return instance()->_storage->setNetworkConnected(user, networkId, isConnected); - } - - //! Get a hash of channels with their channel keys for a given network - /** The keys are channel names and values are passwords (possibly empty) - * \note This method is threadsafe - * - * \param user The id of the networks owner - * \param networkId The Id of the network - */ - static inline QHash persistentChannels(UserId user, const NetworkId &networkId) { - return instance()->_storage->persistentChannels(user, networkId); - } - - //! Update the connected state of a channel - /** \note This method is threadsafe - * - * \param user The Id of the networks owner - * \param networkId The Id of the network - * \param channel The name of the channel - * \param isJoined whether the channel is connected or not - */ - static inline void setChannelPersistent(UserId user, const NetworkId &networkId, const QString &channel, bool isJoined) { - return instance()->_storage->setChannelPersistent(user, networkId, channel, isJoined); - } - - //! Update the key of a channel - /** \note This method is threadsafe - * - * \param user The Id of the networks owner - * \param networkId The Id of the network - * \param channel The name of the channel - * \param key The key of the channel (possibly empty) - */ - static inline void setPersistentChannelKey(UserId user, const NetworkId &networkId, const QString &channel, const QString &key) { - return instance()->_storage->setPersistentChannelKey(user, networkId, channel, key); - } - - //! retrieve last known away message for session restore - /** \note This method is threadsafe - * - * \param user The Id of the networks owner - * \param networkId The Id of the network - */ - static inline QString awayMessage(UserId user, NetworkId networkId) { - return instance()->_storage->awayMessage(user, networkId); - } - - //! Make away message persistent for session restore - /** \note This method is threadsafe - * - * \param user The Id of the networks owner - * \param networkId The Id of the network - * \param awayMsg The current away message of own user - */ - static inline void setAwayMessage(UserId user, NetworkId networkId, const QString &awayMsg) { - return instance()->_storage->setAwayMessage(user, networkId, awayMsg); - } - - //! retrieve last known user mode for session restore - /** \note This method is threadsafe - * - * \param user The Id of the networks owner - * \param networkId The Id of the network - */ - static inline QString userModes(UserId user, NetworkId networkId) { - return instance()->_storage->userModes(user, networkId); - } - - //! Make our user modes persistent for session restore - /** \note This method is threadsafe - * - * \param user The Id of the networks owner - * \param networkId The Id of the network - * \param userModes The current user modes of own user - */ - static inline void setUserModes(UserId user, NetworkId networkId, const QString &userModes) { - return instance()->_storage->setUserModes(user, networkId, userModes); - } - - //! Get the unique BufferInfo for the given combination of network and buffername for a user. - /** \note This method is threadsafe. - * - * \param user The core user who owns this buffername - * \param networkId The network id - * \param type The type of the buffer (StatusBuffer, Channel, etc.) - * \param buffer The buffer name (if empty, the net's status buffer is returned) - * \param create Whether or not the buffer should be created if it doesnt exist - * \return The BufferInfo corresponding to the given network and buffer name, or 0 if not found - */ - static inline BufferInfo bufferInfo(UserId user, const NetworkId &networkId, BufferInfo::Type type, const QString &buffer = "", bool create = true) { - return instance()->_storage->bufferInfo(user, networkId, type, buffer, create); - } - - //! Get the unique BufferInfo for a bufferId - /** \note This method is threadsafe - * \param user The core user who owns this buffername - * \param bufferId The id of the buffer - * \return The BufferInfo corresponding to the given buffer id, or an invalid BufferInfo if not found. - */ - static inline BufferInfo getBufferInfo(UserId user, const BufferId &bufferId) { - return instance()->_storage->getBufferInfo(user, bufferId); - } - - //! Store a Message in the storage backend and set it's unique Id. - /** \note This method is threadsafe. - * - * \param message The message object to be stored - * \return true on success - */ - static inline bool storeMessage(Message &message) { - return instance()->_storage->logMessage(message); - } - - //! Store a list of Messages in the storage backend and set their unique Id. - /** \note This method is threadsafe. - * - * \param messages The list message objects to be stored - * \return true on success - */ - static inline bool storeMessages(MessageList &messages) { - return instance()->_storage->logMessages(messages); - } - - //! Request a certain number messages stored in a given buffer. - /** \param buffer The buffer we request messages from - * \param first if != -1 return only messages with a MsgId >= first - * \param last if != -1 return only messages with a MsgId < last - * \param limit if != -1 limit the returned list to a max of \limit entries - * \return The requested list of messages - */ - static inline QList requestMsgs(UserId user, BufferId bufferId, MsgId first = -1, MsgId last = -1, int limit = -1) { - return instance()->_storage->requestMsgs(user, bufferId, first, last, limit); - } - - //! Request a certain number of messages across all buffers - /** \param first if != -1 return only messages with a MsgId >= first - * \param last if != -1 return only messages with a MsgId < last - * \param limit Max amount of messages - * \return The requested list of messages - */ - static inline QList requestAllMsgs(UserId user, MsgId first = -1, MsgId last = -1, int limit = -1) { - return instance()->_storage->requestAllMsgs(user, first, last, limit); - } - - //! Request a list of all buffers known to a user. - /** This method is used to get a list of all buffers we have stored a backlog from. - * \note This method is threadsafe. - * - * \param user The user whose buffers we request - * \return A list of the BufferInfos for all buffers as requested - */ - static inline QList requestBuffers(UserId user) { - return instance()->_storage->requestBuffers(user); - } - - //! Request a list of BufferIds for a given NetworkId - /** \note This method is threadsafe. - * - * \param user The user whose buffers we request - * \param networkId The NetworkId of the network in question - * \return List of BufferIds belonging to the Network - */ - static inline QList requestBufferIdsForNetwork(UserId user, NetworkId networkId) { - return instance()->_storage->requestBufferIdsForNetwork(user, networkId); - } - - //! Remove permanently a buffer and it's content from the storage backend - /** This call cannot be reverted! - * \note This method is threadsafe. - * - * \param user The user who is the owner of the buffer - * \param bufferId The bufferId - * \return true if successfull - */ - static inline bool removeBuffer(const UserId &user, const BufferId &bufferId) { - return instance()->_storage->removeBuffer(user, bufferId); - } - - //! Rename a Buffer - /** \note This method is threadsafe. - * \param user The id of the buffer owner - * \param bufferId The bufferId - * \param newName The new name of the buffer - * \return true if successfull - */ - static inline bool renameBuffer(const UserId &user, const BufferId &bufferId, const QString &newName) { - return instance()->_storage->renameBuffer(user, bufferId, newName); - } - - //! Merge the content of two Buffers permanently. This cannot be reversed! - /** \note This method is threadsafe. - * \param user The id of the buffer owner - * \param bufferId1 The bufferId of the remaining buffer - * \param bufferId2 The buffer that is about to be removed - * \return true if successfulln - */ - static inline bool mergeBuffersPermanently(const UserId &user, const BufferId &bufferId1, const BufferId &bufferId2) { - return instance()->_storage->mergeBuffersPermanently(user, bufferId1, bufferId2); - } - - //! Update the LastSeenDate for a Buffer - /** This Method is used to make the LastSeenDate of a Buffer persistent - * \note This method is threadsafe. - * - * \param user The Owner of that Buffer - * \param bufferId The buffer id - * \param MsgId The Message id of the message that has been just seen - */ - static inline void setBufferLastSeenMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) { - return instance()->_storage->setBufferLastSeenMsg(user, bufferId, msgId); - } - - //! Get a Hash of all last seen message ids - /** This Method is called when the Quassel Core is started to restore the lastSeenMsgIds - * \note This method is threadsafe. - * - * \param user The Owner of the buffers - */ - static inline QHash bufferLastSeenMsgIds(UserId user) { - return instance()->_storage->bufferLastSeenMsgIds(user); - } - - //! Update the MarkerLineMsgId for a Buffer - /** This Method is used to make the marker line position of a Buffer persistent - * \note This method is threadsafe. - * - * \param user The Owner of that Buffer - * \param bufferId The buffer id - * \param MsgId The Message id where the marker line should be placed - */ - static inline void setBufferMarkerLineMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) { - return instance()->_storage->setBufferMarkerLineMsg(user, bufferId, msgId); - } - - //! Get a Hash of all marker line message ids - /** This Method is called when the Quassel Core is started to restore the MarkerLineMsgIds - * \note This method is threadsafe. - * - * \param user The Owner of the buffers - */ - static inline QHash bufferMarkerLineMsgIds(UserId user) { - return instance()->_storage->bufferMarkerLineMsgIds(user); - } - - const QDateTime &startTime() const { return _startTime; } - - static inline QTimer &syncTimer() { return instance()->_storageSyncTimer; } - - inline OidentdConfigGenerator *oidentdConfigGenerator() const { return _oidentdConfigGenerator; } - - static const int AddClientEventId; + static Core *instance(); + static void destroy(); + + static void saveState(); + static void restoreState(); + + /*** Storage access ***/ + // These methods are threadsafe. + + //! Store a user setting persistently + /** + * \param userId The users Id + * \param settingName The Name of the Setting + * \param data The Value + */ + static inline void setUserSetting(UserId userId, const QString &settingName, const QVariant &data) + { + instance()->_storage->setUserSetting(userId, settingName, data); + } + + + //! Retrieve a persistent user setting + /** + * \param userId The users Id + * \param settingName The Name of the Setting + * \param defaultValue Value to return in case it's unset. + * \return the Value of the Setting or the default value if it is unset. + */ + static inline QVariant getUserSetting(UserId userId, const QString &settingName, const QVariant &defaultValue = QVariant()) + { + return instance()->_storage->getUserSetting(userId, settingName, defaultValue); + } + + + /* Identity handling */ + static inline IdentityId createIdentity(UserId user, CoreIdentity &identity) + { + return instance()->_storage->createIdentity(user, identity); + } + + + static bool updateIdentity(UserId user, const CoreIdentity &identity) + { + return instance()->_storage->updateIdentity(user, identity); + } + + + static void removeIdentity(UserId user, IdentityId identityId) + { + instance()->_storage->removeIdentity(user, identityId); + } + + + static QList identities(UserId user) + { + return instance()->_storage->identities(user); + } + + + //! Create a Network in the Storage and store it's Id in the given NetworkInfo + /** \note This method is thredsafe. + * + * \param user The core user + * \param networkInfo a NetworkInfo definition to store the newly created ID in + * \return true if successfull. + */ + static bool createNetwork(UserId user, NetworkInfo &info); + + //! Apply the changes to NetworkInfo info to the storage engine + /** \note This method is thredsafe. + * + * \param user The core user + * \param networkInfo The Updated NetworkInfo + * \return true if successfull. + */ + static inline bool updateNetwork(UserId user, const NetworkInfo &info) + { + return instance()->_storage->updateNetwork(user, info); + } + + + //! Permanently remove a Network and all the data associated with it. + /** \note This method is thredsafe. + * + * \param user The core user + * \param networkId The network to delete + * \return true if successfull. + */ + static inline bool removeNetwork(UserId user, const NetworkId &networkId) + { + return instance()->_storage->removeNetwork(user, networkId); + } + + + //! Returns a list of all NetworkInfos for the given UserId user + /** \note This method is thredsafe. + * + * \param user The core user + * \return QList. + */ + static inline QList networks(UserId user) + { + return instance()->_storage->networks(user); + } + + + //! Get a list of Networks to restore + /** Return a list of networks the user was connected at the time of core shutdown + * \note This method is threadsafe. + * + * \param user The User Id in question + */ + static inline QList connectedNetworks(UserId user) + { + return instance()->_storage->connectedNetworks(user); + } + + + //! Update the connected state of a network + /** \note This method is threadsafe + * + * \param user The Id of the networks owner + * \param networkId The Id of the network + * \param isConnected whether the network is connected or not + */ + static inline void setNetworkConnected(UserId user, const NetworkId &networkId, bool isConnected) + { + return instance()->_storage->setNetworkConnected(user, networkId, isConnected); + } + + + //! Get a hash of channels with their channel keys for a given network + /** The keys are channel names and values are passwords (possibly empty) + * \note This method is threadsafe + * + * \param user The id of the networks owner + * \param networkId The Id of the network + */ + static inline QHash persistentChannels(UserId user, const NetworkId &networkId) + { + return instance()->_storage->persistentChannels(user, networkId); + } + + + //! Update the connected state of a channel + /** \note This method is threadsafe + * + * \param user The Id of the networks owner + * \param networkId The Id of the network + * \param channel The name of the channel + * \param isJoined whether the channel is connected or not + */ + static inline void setChannelPersistent(UserId user, const NetworkId &networkId, const QString &channel, bool isJoined) + { + return instance()->_storage->setChannelPersistent(user, networkId, channel, isJoined); + } + + + //! Update the key of a channel + /** \note This method is threadsafe + * + * \param user The Id of the networks owner + * \param networkId The Id of the network + * \param channel The name of the channel + * \param key The key of the channel (possibly empty) + */ + static inline void setPersistentChannelKey(UserId user, const NetworkId &networkId, const QString &channel, const QString &key) + { + return instance()->_storage->setPersistentChannelKey(user, networkId, channel, key); + } + + + //! retrieve last known away message for session restore + /** \note This method is threadsafe + * + * \param user The Id of the networks owner + * \param networkId The Id of the network + */ + static inline QString awayMessage(UserId user, NetworkId networkId) + { + return instance()->_storage->awayMessage(user, networkId); + } + + + //! Make away message persistent for session restore + /** \note This method is threadsafe + * + * \param user The Id of the networks owner + * \param networkId The Id of the network + * \param awayMsg The current away message of own user + */ + static inline void setAwayMessage(UserId user, NetworkId networkId, const QString &awayMsg) + { + return instance()->_storage->setAwayMessage(user, networkId, awayMsg); + } + + + //! retrieve last known user mode for session restore + /** \note This method is threadsafe + * + * \param user The Id of the networks owner + * \param networkId The Id of the network + */ + static inline QString userModes(UserId user, NetworkId networkId) + { + return instance()->_storage->userModes(user, networkId); + } + + + //! Make our user modes persistent for session restore + /** \note This method is threadsafe + * + * \param user The Id of the networks owner + * \param networkId The Id of the network + * \param userModes The current user modes of own user + */ + static inline void setUserModes(UserId user, NetworkId networkId, const QString &userModes) + { + return instance()->_storage->setUserModes(user, networkId, userModes); + } + + + //! Get the unique BufferInfo for the given combination of network and buffername for a user. + /** \note This method is threadsafe. + * + * \param user The core user who owns this buffername + * \param networkId The network id + * \param type The type of the buffer (StatusBuffer, Channel, etc.) + * \param buffer The buffer name (if empty, the net's status buffer is returned) + * \param create Whether or not the buffer should be created if it doesnt exist + * \return The BufferInfo corresponding to the given network and buffer name, or 0 if not found + */ + static inline BufferInfo bufferInfo(UserId user, const NetworkId &networkId, BufferInfo::Type type, const QString &buffer = "", bool create = true) + { + return instance()->_storage->bufferInfo(user, networkId, type, buffer, create); + } + + + //! Get the unique BufferInfo for a bufferId + /** \note This method is threadsafe + * \param user The core user who owns this buffername + * \param bufferId The id of the buffer + * \return The BufferInfo corresponding to the given buffer id, or an invalid BufferInfo if not found. + */ + static inline BufferInfo getBufferInfo(UserId user, const BufferId &bufferId) + { + return instance()->_storage->getBufferInfo(user, bufferId); + } + + + //! Store a Message in the storage backend and set it's unique Id. + /** \note This method is threadsafe. + * + * \param message The message object to be stored + * \return true on success + */ + static inline bool storeMessage(Message &message) + { + return instance()->_storage->logMessage(message); + } + + + //! Store a list of Messages in the storage backend and set their unique Id. + /** \note This method is threadsafe. + * + * \param messages The list message objects to be stored + * \return true on success + */ + static inline bool storeMessages(MessageList &messages) + { + return instance()->_storage->logMessages(messages); + } + + + //! Request a certain number messages stored in a given buffer. + /** \param buffer The buffer we request messages from + * \param first if != -1 return only messages with a MsgId >= first + * \param last if != -1 return only messages with a MsgId < last + * \param limit if != -1 limit the returned list to a max of \limit entries + * \return The requested list of messages + */ + static inline QList requestMsgs(UserId user, BufferId bufferId, MsgId first = -1, MsgId last = -1, int limit = -1) + { + return instance()->_storage->requestMsgs(user, bufferId, first, last, limit); + } + + + //! Request a certain number of messages across all buffers + /** \param first if != -1 return only messages with a MsgId >= first + * \param last if != -1 return only messages with a MsgId < last + * \param limit Max amount of messages + * \return The requested list of messages + */ + static inline QList requestAllMsgs(UserId user, MsgId first = -1, MsgId last = -1, int limit = -1) + { + return instance()->_storage->requestAllMsgs(user, first, last, limit); + } + + + //! Request a list of all buffers known to a user. + /** This method is used to get a list of all buffers we have stored a backlog from. + * \note This method is threadsafe. + * + * \param user The user whose buffers we request + * \return A list of the BufferInfos for all buffers as requested + */ + static inline QList requestBuffers(UserId user) + { + return instance()->_storage->requestBuffers(user); + } + + + //! Request a list of BufferIds for a given NetworkId + /** \note This method is threadsafe. + * + * \param user The user whose buffers we request + * \param networkId The NetworkId of the network in question + * \return List of BufferIds belonging to the Network + */ + static inline QList requestBufferIdsForNetwork(UserId user, NetworkId networkId) + { + return instance()->_storage->requestBufferIdsForNetwork(user, networkId); + } + + + //! Remove permanently a buffer and it's content from the storage backend + /** This call cannot be reverted! + * \note This method is threadsafe. + * + * \param user The user who is the owner of the buffer + * \param bufferId The bufferId + * \return true if successfull + */ + static inline bool removeBuffer(const UserId &user, const BufferId &bufferId) + { + return instance()->_storage->removeBuffer(user, bufferId); + } + + + //! Rename a Buffer + /** \note This method is threadsafe. + * \param user The id of the buffer owner + * \param bufferId The bufferId + * \param newName The new name of the buffer + * \return true if successfull + */ + static inline bool renameBuffer(const UserId &user, const BufferId &bufferId, const QString &newName) + { + return instance()->_storage->renameBuffer(user, bufferId, newName); + } + + + //! Merge the content of two Buffers permanently. This cannot be reversed! + /** \note This method is threadsafe. + * \param user The id of the buffer owner + * \param bufferId1 The bufferId of the remaining buffer + * \param bufferId2 The buffer that is about to be removed + * \return true if successfulln + */ + static inline bool mergeBuffersPermanently(const UserId &user, const BufferId &bufferId1, const BufferId &bufferId2) + { + return instance()->_storage->mergeBuffersPermanently(user, bufferId1, bufferId2); + } + + + //! Update the LastSeenDate for a Buffer + /** This Method is used to make the LastSeenDate of a Buffer persistent + * \note This method is threadsafe. + * + * \param user The Owner of that Buffer + * \param bufferId The buffer id + * \param MsgId The Message id of the message that has been just seen + */ + static inline void setBufferLastSeenMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) + { + return instance()->_storage->setBufferLastSeenMsg(user, bufferId, msgId); + } + + + //! Get a Hash of all last seen message ids + /** This Method is called when the Quassel Core is started to restore the lastSeenMsgIds + * \note This method is threadsafe. + * + * \param user The Owner of the buffers + */ + static inline QHash bufferLastSeenMsgIds(UserId user) + { + return instance()->_storage->bufferLastSeenMsgIds(user); + } + + + //! Update the MarkerLineMsgId for a Buffer + /** This Method is used to make the marker line position of a Buffer persistent + * \note This method is threadsafe. + * + * \param user The Owner of that Buffer + * \param bufferId The buffer id + * \param MsgId The Message id where the marker line should be placed + */ + static inline void setBufferMarkerLineMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) + { + return instance()->_storage->setBufferMarkerLineMsg(user, bufferId, msgId); + } + + + //! Get a Hash of all marker line message ids + /** This Method is called when the Quassel Core is started to restore the MarkerLineMsgIds + * \note This method is threadsafe. + * + * \param user The Owner of the buffers + */ + static inline QHash bufferMarkerLineMsgIds(UserId user) + { + return instance()->_storage->bufferMarkerLineMsgIds(user); + } + + + const QDateTime &startTime() const { return _startTime; } + + static inline QTimer &syncTimer() { return instance()->_storageSyncTimer; } + + inline OidentdConfigGenerator *oidentdConfigGenerator() const { return _oidentdConfigGenerator; } + + static const int AddClientEventId; public slots: - //! Make storage data persistent - /** \note This method is threadsafe. - */ - void syncStorage(); - void setupInternalClientSession(SignalProxy *proxy); + //! Make storage data persistent + /** \note This method is threadsafe. + */ + void syncStorage(); + void setupInternalClientSession(SignalProxy *proxy); signals: - //! Sent when a BufferInfo is updated in storage. - void bufferInfoUpdated(UserId user, const BufferInfo &info); + //! Sent when a BufferInfo is updated in storage. + void bufferInfoUpdated(UserId user, const BufferInfo &info); - //! Relay From CoreSession::sessionState(const QVariant &). Used for internal connection only - void sessionState(const QVariant &); + //! Relay From CoreSession::sessionState(const QVariant &). Used for internal connection only + void sessionState(const QVariant &); protected: - virtual void customEvent(QEvent *event); + virtual void customEvent(QEvent *event); private slots: - bool startListening(); - void stopListening(const QString &msg = QString()); - void incomingConnection(); - void clientHasData(); - void clientDisconnected(); + bool startListening(); + void stopListening(const QString &msg = QString()); + void incomingConnection(); + void clientHasData(); + void clientDisconnected(); - bool initStorage(const QString &backend, QVariantMap settings, bool setup = false); - bool initStorage(QVariantMap dbSettings, bool setup = false); + bool initStorage(const QString &backend, QVariantMap settings, bool setup = false); + bool initStorage(QVariantMap dbSettings, bool setup = false); #ifdef HAVE_SSL - void sslErrors(const QList &errors); + void sslErrors(const QList &errors); #endif - void socketError(QAbstractSocket::SocketError); + void socketError(QAbstractSocket::SocketError); private: - Core(); - ~Core(); - void init(); - static Core *instanceptr; - - SessionThread *createSession(UserId userId, bool restoreState = false); - void setupClientSession(QTcpSocket *socket, UserId uid); - void addClientHelper(QTcpSocket *socket, UserId uid); - void processClientMessage(QTcpSocket *socket, const QVariantMap &msg); - //void processCoreSetup(QTcpSocket *socket, QVariantMap &msg); - QString setupCoreForInternalUsage(); - QString setupCore(QVariantMap setupData); - - void registerStorageBackends(); - bool registerStorageBackend(Storage *); - void unregisterStorageBackends(); - void unregisterStorageBackend(Storage *); - bool selectBackend(const QString &backend); - void createUser(); - void changeUserPass(const QString &username); - void saveBackendSettings(const QString &backend, const QVariantMap &settings); - QVariantMap promptForSettings(const Storage *storage); - - QHash sessions; - Storage *_storage; - QTimer _storageSyncTimer; + Core(); + ~Core(); + void init(); + static Core *instanceptr; + + SessionThread *createSession(UserId userId, bool restoreState = false); + void setupClientSession(QTcpSocket *socket, UserId uid); + void addClientHelper(QTcpSocket *socket, UserId uid); + void processClientMessage(QTcpSocket *socket, const QVariantMap &msg); + //void processCoreSetup(QTcpSocket *socket, QVariantMap &msg); + QString setupCoreForInternalUsage(); + QString setupCore(QVariantMap setupData); + + void registerStorageBackends(); + bool registerStorageBackend(Storage *); + void unregisterStorageBackends(); + void unregisterStorageBackend(Storage *); + bool selectBackend(const QString &backend); + void createUser(); + void changeUserPass(const QString &username); + void saveBackendSettings(const QString &backend, const QVariantMap &settings); + QVariantMap promptForSettings(const Storage *storage); + + QHash sessions; + Storage *_storage; + QTimer _storageSyncTimer; #ifdef HAVE_SSL - SslServer _server, _v6server; + SslServer _server, _v6server; #else - QTcpServer _server, _v6server; + QTcpServer _server, _v6server; #endif - OidentdConfigGenerator *_oidentdConfigGenerator; + OidentdConfigGenerator *_oidentdConfigGenerator; - QHash blocksizes; - QHash clientInfo; + QHash blocksizes; + QHash clientInfo; - QHash _storageBackends; + QHash _storageBackends; - QDateTime _startTime; + QDateTime _startTime; - bool _configured; + bool _configured; - - static AbstractSqlMigrationReader *getMigrationReader(Storage *storage); - static AbstractSqlMigrationWriter *getMigrationWriter(Storage *storage); - static void stdInEcho(bool on); - static inline void enableStdInEcho() { stdInEcho(true); } - static inline void disableStdInEcho() { stdInEcho(false); } + static AbstractSqlMigrationReader *getMigrationReader(Storage *storage); + static AbstractSqlMigrationWriter *getMigrationWriter(Storage *storage); + static void stdInEcho(bool on); + static inline void enableStdInEcho() { stdInEcho(true); } + static inline void disableStdInEcho() { stdInEcho(false); } }; + #endif diff --git a/src/core/corealiasmanager.cpp b/src/core/corealiasmanager.cpp index 03027ca8..1e8d89f7 100644 --- a/src/core/corealiasmanager.cpp +++ b/src/core/corealiasmanager.cpp @@ -26,39 +26,45 @@ INIT_SYNCABLE_OBJECT(CoreAliasManager) CoreAliasManager::CoreAliasManager(CoreSession *parent) - : AliasManager(parent) + : AliasManager(parent) { - CoreSession *session = qobject_cast(parent); - if(!session) { - qWarning() << "CoreAliasManager: unable to load Aliases. Parent is not a Coresession!"; - loadDefaults(); - return; - } + CoreSession *session = qobject_cast(parent); + if (!session) { + qWarning() << "CoreAliasManager: unable to load Aliases. Parent is not a Coresession!"; + loadDefaults(); + return; + } - initSetAliases(Core::getUserSetting(session->user(), "Aliases").toMap()); - if(isEmpty()) - loadDefaults(); + initSetAliases(Core::getUserSetting(session->user(), "Aliases").toMap()); + if (isEmpty()) + loadDefaults(); - // we store our settings whenever they change - connect(this, SIGNAL(updatedRemotely()), SLOT(save())); + // we store our settings whenever they change + connect(this, SIGNAL(updatedRemotely()), SLOT(save())); } -void CoreAliasManager::save() const { - CoreSession *session = qobject_cast(parent()); - if(!session) { - qWarning() << "CoreAliasManager: unable to save Aliases. Parent is not a Coresession!"; - return; - } - Core::setUserSetting(session->user(), "Aliases", initAliases()); +void CoreAliasManager::save() const +{ + CoreSession *session = qobject_cast(parent()); + if (!session) { + qWarning() << "CoreAliasManager: unable to save Aliases. Parent is not a Coresession!"; + return; + } + + Core::setUserSetting(session->user(), "Aliases", initAliases()); } -const Network *CoreAliasManager::network(NetworkId id) const { - return qobject_cast(parent())->network(id); + +const Network *CoreAliasManager::network(NetworkId id) const +{ + return qobject_cast(parent())->network(id); } -void CoreAliasManager::loadDefaults() { - foreach(Alias alias, AliasManager::defaults()) { - addAlias(alias.name, alias.expansion); - } + +void CoreAliasManager::loadDefaults() +{ + foreach(Alias alias, AliasManager::defaults()) { + addAlias(alias.name, alias.expansion); + } } diff --git a/src/core/corealiasmanager.h b/src/core/corealiasmanager.h index ee22c5ab..52121311 100644 --- a/src/core/corealiasmanager.h +++ b/src/core/corealiasmanager.h @@ -25,24 +25,25 @@ class CoreSession; -class CoreAliasManager : public AliasManager { - SYNCABLE_OBJECT - Q_OBJECT +class CoreAliasManager : public AliasManager +{ + SYNCABLE_OBJECT + Q_OBJECT public: - explicit CoreAliasManager(CoreSession *parent); + explicit CoreAliasManager(CoreSession *parent); - inline virtual const QMetaObject *syncMetaObject() const { return &AliasManager::staticMetaObject; } + inline virtual const QMetaObject *syncMetaObject() const { return &AliasManager::staticMetaObject; } protected: - const Network *network(NetworkId) const; + const Network *network(NetworkId) const; private slots: - void save() const; + void save() const; private: - void loadDefaults(); - + void loadDefaults(); }; + #endif //COREALIASMANAGER_H diff --git a/src/core/coreapplication.cpp b/src/core/coreapplication.cpp index f7f36c54..f6212d74 100644 --- a/src/core/coreapplication.cpp +++ b/src/core/coreapplication.cpp @@ -24,61 +24,69 @@ #include "logger.h" CoreApplicationInternal::CoreApplicationInternal() - : _coreCreated(false) + : _coreCreated(false) { - } -CoreApplicationInternal::~CoreApplicationInternal() { - if(_coreCreated) { - Core::saveState(); - Core::destroy(); - } + +CoreApplicationInternal::~CoreApplicationInternal() +{ + if (_coreCreated) { + Core::saveState(); + Core::destroy(); + } } -bool CoreApplicationInternal::init() { - /* FIXME - This is an initial check if logfile is writable since the warning would spam stdout if done - in current Logger implementation. Can be dropped whenever the logfile is only opened once. - */ - QFile logFile; - if(!Quassel::optionValue("logfile").isEmpty()) { - logFile.setFileName(Quassel::optionValue("logfile")); - if(!logFile.open(QIODevice::Append | QIODevice::Text)) - qWarning("Warning: Couldn't open logfile '%s' - will log to stdout instead",qPrintable(logFile.fileName())); - else logFile.close(); - } - - Core::instance(); // create and init the core - _coreCreated = true; - - if(!Quassel::isOptionSet("norestore")) - Core::restoreState(); - - return true; + +bool CoreApplicationInternal::init() +{ + /* FIXME + This is an initial check if logfile is writable since the warning would spam stdout if done + in current Logger implementation. Can be dropped whenever the logfile is only opened once. + */ + QFile logFile; + if (!Quassel::optionValue("logfile").isEmpty()) { + logFile.setFileName(Quassel::optionValue("logfile")); + if (!logFile.open(QIODevice::Append | QIODevice::Text)) + qWarning("Warning: Couldn't open logfile '%s' - will log to stdout instead", qPrintable(logFile.fileName())); + else logFile.close(); + } + + Core::instance(); // create and init the core + _coreCreated = true; + + if (!Quassel::isOptionSet("norestore")) + Core::restoreState(); + + return true; } + /*****************************************************************************/ CoreApplication::CoreApplication(int &argc, char **argv) - : QCoreApplication(argc, argv), Quassel() + : QCoreApplication(argc, argv), Quassel() { #ifdef Q_OS_MAC - disableCrashhandler(); + disableCrashhandler(); #endif /* Q_OS_MAC */ - setRunMode(Quassel::CoreOnly); - _internal = new CoreApplicationInternal(); + setRunMode(Quassel::CoreOnly); + _internal = new CoreApplicationInternal(); } -CoreApplication::~CoreApplication() { - delete _internal; + +CoreApplication::~CoreApplication() +{ + delete _internal; } -bool CoreApplication::init() { - if(Quassel::init() && _internal->init()) { - qInstallMsgHandler(Logger::logMessage); - return true; - } - return false; + +bool CoreApplication::init() +{ + if (Quassel::init() && _internal->init()) { + qInstallMsgHandler(Logger::logMessage); + return true; + } + return false; } diff --git a/src/core/coreapplication.h b/src/core/coreapplication.h index 517fd254..59e58642 100644 --- a/src/core/coreapplication.h +++ b/src/core/coreapplication.h @@ -32,30 +32,33 @@ /// Encapsulates CoreApplication's logic. /** This allows it to be reused within MonolithicApplication as well. */ -class CoreApplicationInternal { - Q_DECLARE_TR_FUNCTIONS(CoreApplicationInternal) +class CoreApplicationInternal +{ + Q_DECLARE_TR_FUNCTIONS(CoreApplicationInternal) - public: +public: CoreApplicationInternal(); ~CoreApplicationInternal(); bool init(); - private: +private: bool _coreCreated; }; -class CoreApplication : public QCoreApplication, public Quassel { - Q_OBJECT - public: +class CoreApplication : public QCoreApplication, public Quassel +{ + Q_OBJECT +public: CoreApplication(int &argc, char **argv); ~CoreApplication(); bool init(); - private: +private: CoreApplicationInternal *_internal; }; + #endif diff --git a/src/core/corebacklogmanager.cpp b/src/core/corebacklogmanager.cpp index 9ef4b899..9df40cbe 100644 --- a/src/core/corebacklogmanager.cpp +++ b/src/core/corebacklogmanager.cpp @@ -26,86 +26,92 @@ INIT_SYNCABLE_OBJECT(CoreBacklogManager) CoreBacklogManager::CoreBacklogManager(CoreSession *coreSession) - : BacklogManager(coreSession), + : BacklogManager(coreSession), _coreSession(coreSession) { } -QVariantList CoreBacklogManager::requestBacklog(BufferId bufferId, MsgId first, MsgId last, int limit, int additional) { - QVariantList backlog; - QList msgList; - msgList = Core::requestMsgs(coreSession()->user(), bufferId, first, last, limit); - QList::const_iterator msgIter = msgList.constBegin(); - QList::const_iterator msgListEnd = msgList.constEnd(); - while(msgIter != msgListEnd) { - backlog << qVariantFromValue(*msgIter); - msgIter++; - } +QVariantList CoreBacklogManager::requestBacklog(BufferId bufferId, MsgId first, MsgId last, int limit, int additional) +{ + QVariantList backlog; + QList msgList; + msgList = Core::requestMsgs(coreSession()->user(), bufferId, first, last, limit); - if(additional && limit != 0) { - MsgId oldestMessage = first; - if(!msgList.isEmpty()) { - if(msgList.first().msgId() < msgList.last().msgId()) - oldestMessage = msgList.first().msgId(); - else - oldestMessage = msgList.last().msgId(); + QList::const_iterator msgIter = msgList.constBegin(); + QList::const_iterator msgListEnd = msgList.constEnd(); + while (msgIter != msgListEnd) { + backlog << qVariantFromValue(*msgIter); + msgIter++; } - if(first != -1) { - last = first; - } else { - last = oldestMessage; - } + if (additional && limit != 0) { + MsgId oldestMessage = first; + if (!msgList.isEmpty()) { + if (msgList.first().msgId() < msgList.last().msgId()) + oldestMessage = msgList.first().msgId(); + else + oldestMessage = msgList.last().msgId(); + } - // only fetch additional messages if they continue seemlessly - // that is, if the list of messages is not truncated by the limit - if(last == oldestMessage) { - msgList = Core::requestMsgs(coreSession()->user(), bufferId, -1, last, additional); - msgIter = msgList.constBegin(); - msgListEnd = msgList.constEnd(); - while(msgIter != msgListEnd) { - backlog << qVariantFromValue(*msgIter); - msgIter++; - } + if (first != -1) { + last = first; + } + else { + last = oldestMessage; + } + + // only fetch additional messages if they continue seemlessly + // that is, if the list of messages is not truncated by the limit + if (last == oldestMessage) { + msgList = Core::requestMsgs(coreSession()->user(), bufferId, -1, last, additional); + msgIter = msgList.constBegin(); + msgListEnd = msgList.constEnd(); + while (msgIter != msgListEnd) { + backlog << qVariantFromValue(*msgIter); + msgIter++; + } + } } - } - return backlog; + return backlog; } -QVariantList CoreBacklogManager::requestBacklogAll(MsgId first, MsgId last, int limit, int additional) { - QVariantList backlog; - QList msgList; - msgList = Core::requestAllMsgs(coreSession()->user(), first, last, limit); - QList::const_iterator msgIter = msgList.constBegin(); - QList::const_iterator msgListEnd = msgList.constEnd(); - while(msgIter != msgListEnd) { - backlog << qVariantFromValue(*msgIter); - msgIter++; - } +QVariantList CoreBacklogManager::requestBacklogAll(MsgId first, MsgId last, int limit, int additional) +{ + QVariantList backlog; + QList msgList; + msgList = Core::requestAllMsgs(coreSession()->user(), first, last, limit); - if(additional) { - if(first != -1) { - last = first; - } else { - last = -1; - if(!msgList.isEmpty()) { - if(msgList.first().msgId() < msgList.last().msgId()) - last = msgList.first().msgId(); - else - last = msgList.last().msgId(); - } + QList::const_iterator msgIter = msgList.constBegin(); + QList::const_iterator msgListEnd = msgList.constEnd(); + while (msgIter != msgListEnd) { + backlog << qVariantFromValue(*msgIter); + msgIter++; } - msgList = Core::requestAllMsgs(coreSession()->user(), -1, last, additional); - msgIter = msgList.constBegin(); - msgListEnd = msgList.constEnd(); - while(msgIter != msgListEnd) { - backlog << qVariantFromValue(*msgIter); - msgIter++; + + if (additional) { + if (first != -1) { + last = first; + } + else { + last = -1; + if (!msgList.isEmpty()) { + if (msgList.first().msgId() < msgList.last().msgId()) + last = msgList.first().msgId(); + else + last = msgList.last().msgId(); + } + } + msgList = Core::requestAllMsgs(coreSession()->user(), -1, last, additional); + msgIter = msgList.constBegin(); + msgListEnd = msgList.constEnd(); + while (msgIter != msgListEnd) { + backlog << qVariantFromValue(*msgIter); + msgIter++; + } } - } - return backlog; + return backlog; } diff --git a/src/core/corebacklogmanager.h b/src/core/corebacklogmanager.h index 9d1a8128..85378f3b 100644 --- a/src/core/corebacklogmanager.h +++ b/src/core/corebacklogmanager.h @@ -25,21 +25,23 @@ class CoreSession; -class CoreBacklogManager : public BacklogManager { - SYNCABLE_OBJECT - Q_OBJECT +class CoreBacklogManager : public BacklogManager +{ + SYNCABLE_OBJECT + Q_OBJECT public: - CoreBacklogManager(CoreSession *coreSession = 0); + CoreBacklogManager(CoreSession *coreSession = 0); - CoreSession *coreSession() { return _coreSession; } + CoreSession *coreSession() { return _coreSession; } public slots: - virtual QVariantList requestBacklog(BufferId bufferId, MsgId first = -1, MsgId last = -1, int limit = -1, int additional = 0); - virtual QVariantList requestBacklogAll(MsgId first = -1, MsgId last = -1, int limit = -1, int additional = 0); + virtual QVariantList requestBacklog(BufferId bufferId, MsgId first = -1, MsgId last = -1, int limit = -1, int additional = 0); + virtual QVariantList requestBacklogAll(MsgId first = -1, MsgId last = -1, int limit = -1, int additional = 0); private: - CoreSession *_coreSession; + CoreSession *_coreSession; }; + #endif // COREBACKLOGMANAGER_H diff --git a/src/core/corebasichandler.cpp b/src/core/corebasichandler.cpp index 44fdc7b4..6bcc8def 100644 --- a/src/core/corebasichandler.cpp +++ b/src/core/corebasichandler.cpp @@ -23,109 +23,139 @@ #include "logger.h" CoreBasicHandler::CoreBasicHandler(CoreNetwork *parent) - : BasicHandler(parent), + : BasicHandler(parent), _network(parent) { - connect(this, SIGNAL(displayMsg(Message::Type, BufferInfo::Type, const QString &, const QString &, const QString &, Message::Flags)), - network(), SLOT(displayMsg(Message::Type, BufferInfo::Type, const QString &, const QString &, const QString &, Message::Flags))); + connect(this, SIGNAL(displayMsg(Message::Type, BufferInfo::Type, const QString &, const QString &, const QString &, Message::Flags)), + network(), SLOT(displayMsg(Message::Type, BufferInfo::Type, const QString &, const QString &, const QString &, Message::Flags))); - connect(this, SIGNAL(putCmd(QString, const QList &, const QByteArray &)), - network(), SLOT(putCmd(QString, const QList &, const QByteArray &))); + connect(this, SIGNAL(putCmd(QString, const QList &, const QByteArray &)), + network(), SLOT(putCmd(QString, const QList &, const QByteArray &))); - connect(this, SIGNAL(putRawLine(const QByteArray &)), - network(), SLOT(putRawLine(const QByteArray &))); + connect(this, SIGNAL(putRawLine(const QByteArray &)), + network(), SLOT(putRawLine(const QByteArray &))); } -QString CoreBasicHandler::serverDecode(const QByteArray &string) { - return network()->serverDecode(string); + +QString CoreBasicHandler::serverDecode(const QByteArray &string) +{ + return network()->serverDecode(string); } -QStringList CoreBasicHandler::serverDecode(const QList &stringlist) { - QStringList list; - foreach(QByteArray s, stringlist) list << network()->serverDecode(s); - return list; + +QStringList CoreBasicHandler::serverDecode(const QList &stringlist) +{ + QStringList list; + foreach(QByteArray s, stringlist) list << network()->serverDecode(s); + return list; } -QString CoreBasicHandler::channelDecode(const QString &bufferName, const QByteArray &string) { - return network()->channelDecode(bufferName, string); + +QString CoreBasicHandler::channelDecode(const QString &bufferName, const QByteArray &string) +{ + return network()->channelDecode(bufferName, string); } -QStringList CoreBasicHandler::channelDecode(const QString &bufferName, const QList &stringlist) { - QStringList list; - foreach(QByteArray s, stringlist) list << network()->channelDecode(bufferName, s); - return list; + +QStringList CoreBasicHandler::channelDecode(const QString &bufferName, const QList &stringlist) +{ + QStringList list; + foreach(QByteArray s, stringlist) list << network()->channelDecode(bufferName, s); + return list; } -QString CoreBasicHandler::userDecode(const QString &userNick, const QByteArray &string) { - return network()->userDecode(userNick, string); + +QString CoreBasicHandler::userDecode(const QString &userNick, const QByteArray &string) +{ + return network()->userDecode(userNick, string); } -QStringList CoreBasicHandler::userDecode(const QString &userNick, const QList &stringlist) { - QStringList list; - foreach(QByteArray s, stringlist) list << network()->userDecode(userNick, s); - return list; + +QStringList CoreBasicHandler::userDecode(const QString &userNick, const QList &stringlist) +{ + QStringList list; + foreach(QByteArray s, stringlist) list << network()->userDecode(userNick, s); + return list; } + /*** ***/ -QByteArray CoreBasicHandler::serverEncode(const QString &string) { - return network()->serverEncode(string); +QByteArray CoreBasicHandler::serverEncode(const QString &string) +{ + return network()->serverEncode(string); } -QList CoreBasicHandler::serverEncode(const QStringList &stringlist) { - QList list; - foreach(QString s, stringlist) list << network()->serverEncode(s); - return list; + +QList CoreBasicHandler::serverEncode(const QStringList &stringlist) +{ + QList list; + foreach(QString s, stringlist) list << network()->serverEncode(s); + return list; } -QByteArray CoreBasicHandler::channelEncode(const QString &bufferName, const QString &string) { - return network()->channelEncode(bufferName, string); + +QByteArray CoreBasicHandler::channelEncode(const QString &bufferName, const QString &string) +{ + return network()->channelEncode(bufferName, string); } -QList CoreBasicHandler::channelEncode(const QString &bufferName, const QStringList &stringlist) { - QList list; - foreach(QString s, stringlist) list << network()->channelEncode(bufferName, s); - return list; + +QList CoreBasicHandler::channelEncode(const QString &bufferName, const QStringList &stringlist) +{ + QList list; + foreach(QString s, stringlist) list << network()->channelEncode(bufferName, s); + return list; } -QByteArray CoreBasicHandler::userEncode(const QString &userNick, const QString &string) { - return network()->userEncode(userNick, string); + +QByteArray CoreBasicHandler::userEncode(const QString &userNick, const QString &string) +{ + return network()->userEncode(userNick, string); } -QList CoreBasicHandler::userEncode(const QString &userNick, const QStringList &stringlist) { - QList list; - foreach(QString s, stringlist) list << network()->userEncode(userNick, s); - return list; + +QList CoreBasicHandler::userEncode(const QString &userNick, const QStringList &stringlist) +{ + QList list; + foreach(QString s, stringlist) list << network()->userEncode(userNick, s); + return list; } + // ==================== // protected: // ==================== -BufferInfo::Type CoreBasicHandler::typeByTarget(const QString &target) const { - if(target.isEmpty()) - return BufferInfo::StatusBuffer; +BufferInfo::Type CoreBasicHandler::typeByTarget(const QString &target) const +{ + if (target.isEmpty()) + return BufferInfo::StatusBuffer; - if(network()->isChannelName(target)) - return BufferInfo::ChannelBuffer; + if (network()->isChannelName(target)) + return BufferInfo::ChannelBuffer; - return BufferInfo::QueryBuffer; + return BufferInfo::QueryBuffer; } -void CoreBasicHandler::putCmd(const QString &cmd, const QByteArray ¶m, const QByteArray &prefix) { - QList list; - list << param; - emit putCmd(cmd, list, prefix); + +void CoreBasicHandler::putCmd(const QString &cmd, const QByteArray ¶m, const QByteArray &prefix) +{ + QList list; + list << param; + emit putCmd(cmd, list, prefix); } -void CoreBasicHandler::displayMsg(Message::Type msgType, QString target, const QString &text, const QString &sender, Message::Flags flags) { - IrcChannel *channel = network()->ircChannel(target); - if(!channel) { - if(!target.isEmpty() && network()->prefixes().contains(target[0])) - target = target.mid(1); - if(target.startsWith('$') || target.startsWith('#')) - target = nickFromMask(sender); - } +void CoreBasicHandler::displayMsg(Message::Type msgType, QString target, const QString &text, const QString &sender, Message::Flags flags) +{ + IrcChannel *channel = network()->ircChannel(target); + if (!channel) { + if (!target.isEmpty() && network()->prefixes().contains(target[0])) + target = target.mid(1); + + if (target.startsWith('$') || target.startsWith('#')) + target = nickFromMask(sender); + } - emit displayMsg(msgType, typeByTarget(target), target, text, sender, flags); + emit displayMsg(msgType, typeByTarget(target), target, text, sender, flags); } diff --git a/src/core/corebasichandler.h b/src/core/corebasichandler.h index d04beed2..cec31ee8 100644 --- a/src/core/corebasichandler.h +++ b/src/core/corebasichandler.h @@ -31,41 +31,44 @@ class CoreSession; -class CoreBasicHandler : public BasicHandler { - Q_OBJECT +class CoreBasicHandler : public BasicHandler +{ + Q_OBJECT public: - CoreBasicHandler(CoreNetwork *parent = 0); - - QString serverDecode(const QByteArray &string); - QStringList serverDecode(const QList &stringlist); - QString channelDecode(const QString &bufferName, const QByteArray &string); - QStringList channelDecode(const QString &bufferName, const QList &stringlist); - QString userDecode(const QString &userNick, const QByteArray &string); - QStringList userDecode(const QString &userNick, const QList &stringlist); - - QByteArray serverEncode(const QString &string); - QList serverEncode(const QStringList &stringlist); - QByteArray channelEncode(const QString &bufferName, const QString &string); - QList channelEncode(const QString &bufferName, const QStringList &stringlist); - QByteArray userEncode(const QString &userNick, const QString &string); - QList userEncode(const QString &userNick, const QStringList &stringlist); + CoreBasicHandler(CoreNetwork *parent = 0); + + QString serverDecode(const QByteArray &string); + QStringList serverDecode(const QList &stringlist); + QString channelDecode(const QString &bufferName, const QByteArray &string); + QStringList channelDecode(const QString &bufferName, const QList &stringlist); + QString userDecode(const QString &userNick, const QByteArray &string); + QStringList userDecode(const QString &userNick, const QList &stringlist); + + QByteArray serverEncode(const QString &string); + QList serverEncode(const QStringList &stringlist); + QByteArray channelEncode(const QString &bufferName, const QString &string); + QList channelEncode(const QString &bufferName, const QStringList &stringlist); + QByteArray userEncode(const QString &userNick, const QString &string); + QList userEncode(const QString &userNick, const QStringList &stringlist); signals: - void displayMsg(Message::Type, BufferInfo::Type, const QString &target, const QString &text, const QString &sender = "", Message::Flags flags = Message::None); - void putCmd(const QString &cmd, const QList ¶ms, const QByteArray &prefix = QByteArray()); - void putRawLine(const QByteArray &msg); + void displayMsg(Message::Type, BufferInfo::Type, const QString &target, const QString &text, const QString &sender = "", Message::Flags flags = Message::None); + void putCmd(const QString &cmd, const QList ¶ms, const QByteArray &prefix = QByteArray()); + void putRawLine(const QByteArray &msg); protected: - void displayMsg(Message::Type, QString target, const QString &text, const QString &sender = "", Message::Flags flags = Message::None); - void putCmd(const QString &cmd, const QByteArray ¶m, const QByteArray &prefix = QByteArray()); + void displayMsg(Message::Type, QString target, const QString &text, const QString &sender = "", Message::Flags flags = Message::None); + void putCmd(const QString &cmd, const QByteArray ¶m, const QByteArray &prefix = QByteArray()); - inline CoreNetwork *network() const { return _network; } - inline CoreSession *coreSession() const { return _network->coreSession(); } + inline CoreNetwork *network() const { return _network; } + inline CoreSession *coreSession() const { return _network->coreSession(); } - BufferInfo::Type typeByTarget(const QString &target) const; + BufferInfo::Type typeByTarget(const QString &target) const; private: - CoreNetwork *_network; + CoreNetwork *_network; }; + + #endif diff --git a/src/core/corebuffersyncer.cpp b/src/core/corebuffersyncer.cpp index 55c28b26..27e7ead2 100644 --- a/src/core/corebuffersyncer.cpp +++ b/src/core/corebuffersyncer.cpp @@ -25,138 +25,158 @@ #include "corenetwork.h" #include "ircchannel.h" -class PurgeEvent : public QEvent { +class PurgeEvent : public QEvent +{ public: - PurgeEvent() : QEvent(QEvent::User) {} + PurgeEvent() : QEvent(QEvent::User) {} }; + INIT_SYNCABLE_OBJECT(CoreBufferSyncer) CoreBufferSyncer::CoreBufferSyncer(CoreSession *parent) - : BufferSyncer(Core::bufferLastSeenMsgIds(parent->user()), Core::bufferMarkerLineMsgIds(parent->user()), parent), + : BufferSyncer(Core::bufferLastSeenMsgIds(parent->user()), Core::bufferMarkerLineMsgIds(parent->user()), parent), _coreSession(parent), _purgeBuffers(false) { } -void CoreBufferSyncer::requestSetLastSeenMsg(BufferId buffer, const MsgId &msgId) { - if(setLastSeenMsg(buffer, msgId)) - dirtyLastSeenBuffers << buffer; + +void CoreBufferSyncer::requestSetLastSeenMsg(BufferId buffer, const MsgId &msgId) +{ + if (setLastSeenMsg(buffer, msgId)) + dirtyLastSeenBuffers << buffer; } -void CoreBufferSyncer::requestSetMarkerLine(BufferId buffer, const MsgId &msgId) { - if(setMarkerLine(buffer, msgId)) - dirtyMarkerLineBuffers << buffer; + +void CoreBufferSyncer::requestSetMarkerLine(BufferId buffer, const MsgId &msgId) +{ + if (setMarkerLine(buffer, msgId)) + dirtyMarkerLineBuffers << buffer; } -void CoreBufferSyncer::storeDirtyIds() { - UserId userId = _coreSession->user(); - MsgId msgId; - foreach(BufferId bufferId, dirtyLastSeenBuffers) { - msgId = lastSeenMsg(bufferId); - if(msgId.isValid()) - Core::setBufferLastSeenMsg(userId, bufferId, msgId); - } - - foreach(BufferId bufferId, dirtyMarkerLineBuffers) { - msgId = markerLine(bufferId); - if(msgId.isValid()) - Core::setBufferMarkerLineMsg(userId, bufferId, msgId); - } - - dirtyLastSeenBuffers.clear(); - dirtyMarkerLineBuffers.clear(); + +void CoreBufferSyncer::storeDirtyIds() +{ + UserId userId = _coreSession->user(); + MsgId msgId; + foreach(BufferId bufferId, dirtyLastSeenBuffers) { + msgId = lastSeenMsg(bufferId); + if (msgId.isValid()) + Core::setBufferLastSeenMsg(userId, bufferId, msgId); + } + + foreach(BufferId bufferId, dirtyMarkerLineBuffers) { + msgId = markerLine(bufferId); + if (msgId.isValid()) + Core::setBufferMarkerLineMsg(userId, bufferId, msgId); + } + + dirtyLastSeenBuffers.clear(); + dirtyMarkerLineBuffers.clear(); } -void CoreBufferSyncer::removeBuffer(BufferId bufferId) { - BufferInfo bufferInfo = Core::getBufferInfo(_coreSession->user(), bufferId); - if(!bufferInfo.isValid()) { - qWarning() << "CoreBufferSyncer::removeBuffer(): invalid BufferId:" << bufferId << "for User:" << _coreSession->user(); - return; - } - - if(bufferInfo.type() == BufferInfo::StatusBuffer) { - qWarning() << "CoreBufferSyncer::removeBuffer(): Status Buffers cannot be removed!"; - return; - } - - if(bufferInfo.type() == BufferInfo::ChannelBuffer) { - CoreNetwork *net = _coreSession->network(bufferInfo.networkId()); - if(!net) { - qWarning() << "CoreBufferSyncer::removeBuffer(): Received BufferInfo with unknown networkId!"; - return; + +void CoreBufferSyncer::removeBuffer(BufferId bufferId) +{ + BufferInfo bufferInfo = Core::getBufferInfo(_coreSession->user(), bufferId); + if (!bufferInfo.isValid()) { + qWarning() << "CoreBufferSyncer::removeBuffer(): invalid BufferId:" << bufferId << "for User:" << _coreSession->user(); + return; } - IrcChannel *chan = net->ircChannel(bufferInfo.bufferName()); - if(chan) { - qWarning() << "CoreBufferSyncer::removeBuffer(): Unable to remove Buffer for joined Channel:" << bufferInfo.bufferName(); - return; + + if (bufferInfo.type() == BufferInfo::StatusBuffer) { + qWarning() << "CoreBufferSyncer::removeBuffer(): Status Buffers cannot be removed!"; + return; + } + + if (bufferInfo.type() == BufferInfo::ChannelBuffer) { + CoreNetwork *net = _coreSession->network(bufferInfo.networkId()); + if (!net) { + qWarning() << "CoreBufferSyncer::removeBuffer(): Received BufferInfo with unknown networkId!"; + return; + } + IrcChannel *chan = net->ircChannel(bufferInfo.bufferName()); + if (chan) { + qWarning() << "CoreBufferSyncer::removeBuffer(): Unable to remove Buffer for joined Channel:" << bufferInfo.bufferName(); + return; + } } - } - if(Core::removeBuffer(_coreSession->user(), bufferId)) - BufferSyncer::removeBuffer(bufferId); + if (Core::removeBuffer(_coreSession->user(), bufferId)) + BufferSyncer::removeBuffer(bufferId); } -void CoreBufferSyncer::renameBuffer(BufferId bufferId, QString newName) { - BufferInfo bufferInfo = Core::getBufferInfo(_coreSession->user(), bufferId); - if(!bufferInfo.isValid()) { - qWarning() << "CoreBufferSyncer::renameBuffer(): invalid BufferId:" << bufferId << "for User:" << _coreSession->user(); - return; - } - if(bufferInfo.type() != BufferInfo::QueryBuffer) { - qWarning() << "CoreBufferSyncer::renameBuffer(): only QueryBuffers can be renamed" << bufferId; - return; - } +void CoreBufferSyncer::renameBuffer(BufferId bufferId, QString newName) +{ + BufferInfo bufferInfo = Core::getBufferInfo(_coreSession->user(), bufferId); + if (!bufferInfo.isValid()) { + qWarning() << "CoreBufferSyncer::renameBuffer(): invalid BufferId:" << bufferId << "for User:" << _coreSession->user(); + return; + } + + if (bufferInfo.type() != BufferInfo::QueryBuffer) { + qWarning() << "CoreBufferSyncer::renameBuffer(): only QueryBuffers can be renamed" << bufferId; + return; + } - if(Core::renameBuffer(_coreSession->user(), bufferId, newName)) - BufferSyncer::renameBuffer(bufferId, newName); + if (Core::renameBuffer(_coreSession->user(), bufferId, newName)) + BufferSyncer::renameBuffer(bufferId, newName); } -void CoreBufferSyncer::mergeBuffersPermanently(BufferId bufferId1, BufferId bufferId2) { - BufferInfo bufferInfo1 = Core::getBufferInfo(_coreSession->user(), bufferId1); - BufferInfo bufferInfo2 = Core::getBufferInfo(_coreSession->user(), bufferId2); - if(!bufferInfo1.isValid() || !bufferInfo2.isValid()) { - qWarning() << "CoreBufferSyncer::mergeBufferPermanently(): invalid BufferIds:" << bufferId1 << bufferId2 << "for User:" << _coreSession->user(); - return; - } - - if(bufferInfo1.type() != BufferInfo::QueryBuffer || bufferInfo2.type() != BufferInfo::QueryBuffer) { - qWarning() << "CoreBufferSyncer::mergeBufferPermanently(): only QueryBuffers can be merged!" << bufferId1 << bufferId2; - return; - } - - if(Core::mergeBuffersPermanently(_coreSession->user(), bufferId1, bufferId2)) { - BufferSyncer::mergeBuffersPermanently(bufferId1, bufferId2); - } + +void CoreBufferSyncer::mergeBuffersPermanently(BufferId bufferId1, BufferId bufferId2) +{ + BufferInfo bufferInfo1 = Core::getBufferInfo(_coreSession->user(), bufferId1); + BufferInfo bufferInfo2 = Core::getBufferInfo(_coreSession->user(), bufferId2); + if (!bufferInfo1.isValid() || !bufferInfo2.isValid()) { + qWarning() << "CoreBufferSyncer::mergeBufferPermanently(): invalid BufferIds:" << bufferId1 << bufferId2 << "for User:" << _coreSession->user(); + return; + } + + if (bufferInfo1.type() != BufferInfo::QueryBuffer || bufferInfo2.type() != BufferInfo::QueryBuffer) { + qWarning() << "CoreBufferSyncer::mergeBufferPermanently(): only QueryBuffers can be merged!" << bufferId1 << bufferId2; + return; + } + + if (Core::mergeBuffersPermanently(_coreSession->user(), bufferId1, bufferId2)) { + BufferSyncer::mergeBuffersPermanently(bufferId1, bufferId2); + } } -void CoreBufferSyncer::customEvent(QEvent *event) { - if(event->type() != QEvent::User) - return; - purgeBufferIds(); - event->accept(); +void CoreBufferSyncer::customEvent(QEvent *event) +{ + if (event->type() != QEvent::User) + return; + + purgeBufferIds(); + event->accept(); } -void CoreBufferSyncer::requestPurgeBufferIds() { - if(_purgeBuffers) - return; - _purgeBuffers = true; - QCoreApplication::postEvent(this, new PurgeEvent()); +void CoreBufferSyncer::requestPurgeBufferIds() +{ + if (_purgeBuffers) + return; + + _purgeBuffers = true; + QCoreApplication::postEvent(this, new PurgeEvent()); } -void CoreBufferSyncer::purgeBufferIds() { - _purgeBuffers = false; - QList bufferInfos = Core::requestBuffers(_coreSession->user()); - QSet actualBuffers; - foreach(BufferInfo bufferInfo, bufferInfos) { - actualBuffers << bufferInfo.bufferId(); - } - - QSet storedIds = lastSeenBufferIds().toSet() + markerLineBufferIds().toSet(); - foreach(BufferId bufferId, storedIds) { - if(!actualBuffers.contains(bufferId)) { - BufferSyncer::removeBuffer(bufferId); + +void CoreBufferSyncer::purgeBufferIds() +{ + _purgeBuffers = false; + QList bufferInfos = Core::requestBuffers(_coreSession->user()); + QSet actualBuffers; + foreach(BufferInfo bufferInfo, bufferInfos) { + actualBuffers << bufferInfo.bufferId(); + } + + QSet storedIds = lastSeenBufferIds().toSet() + markerLineBufferIds().toSet(); + foreach(BufferId bufferId, storedIds) { + if (!actualBuffers.contains(bufferId)) { + BufferSyncer::removeBuffer(bufferId); + } } - } } diff --git a/src/core/corebuffersyncer.h b/src/core/corebuffersyncer.h index cb58b0ac..1160a5fc 100644 --- a/src/core/corebuffersyncer.h +++ b/src/core/corebuffersyncer.h @@ -25,43 +25,45 @@ class CoreSession; -class CoreBufferSyncer : public BufferSyncer { - SYNCABLE_OBJECT - Q_OBJECT +class CoreBufferSyncer : public BufferSyncer +{ + SYNCABLE_OBJECT + Q_OBJECT public: - CoreBufferSyncer(CoreSession *parent); + CoreBufferSyncer(CoreSession *parent); public slots: - virtual void requestSetLastSeenMsg(BufferId buffer, const MsgId &msgId); - virtual void requestSetMarkerLine(BufferId buffer, const MsgId &msgId); + virtual void requestSetLastSeenMsg(BufferId buffer, const MsgId &msgId); + virtual void requestSetMarkerLine(BufferId buffer, const MsgId &msgId); - virtual inline void requestRemoveBuffer(BufferId buffer) { removeBuffer(buffer); } - virtual void removeBuffer(BufferId bufferId); + virtual inline void requestRemoveBuffer(BufferId buffer) { removeBuffer(buffer); } + virtual void removeBuffer(BufferId bufferId); - virtual inline void requestRenameBuffer(BufferId buffer, QString newName) { renameBuffer(buffer, newName); } - virtual void renameBuffer(BufferId buffer, QString newName); + virtual inline void requestRenameBuffer(BufferId buffer, QString newName) { renameBuffer(buffer, newName); } + virtual void renameBuffer(BufferId buffer, QString newName); - virtual inline void requestMergeBuffersPermanently(BufferId buffer1, BufferId buffer2) { mergeBuffersPermanently(buffer1, buffer2); } - virtual void mergeBuffersPermanently(BufferId buffer1, BufferId buffer2); + virtual inline void requestMergeBuffersPermanently(BufferId buffer1, BufferId buffer2) { mergeBuffersPermanently(buffer1, buffer2); } + virtual void mergeBuffersPermanently(BufferId buffer1, BufferId buffer2); - virtual void requestPurgeBufferIds(); + virtual void requestPurgeBufferIds(); - virtual inline void requestMarkBufferAsRead(BufferId buffer) { markBufferAsRead(buffer); } + virtual inline void requestMarkBufferAsRead(BufferId buffer) { markBufferAsRead(buffer); } - void storeDirtyIds(); + void storeDirtyIds(); protected: - virtual void customEvent(QEvent *event); + virtual void customEvent(QEvent *event); private: - CoreSession *_coreSession; - bool _purgeBuffers; + CoreSession *_coreSession; + bool _purgeBuffers; - QSet dirtyLastSeenBuffers; - QSet dirtyMarkerLineBuffers; + QSet dirtyLastSeenBuffers; + QSet dirtyMarkerLineBuffers; - void purgeBufferIds(); + void purgeBufferIds(); }; + #endif //COREBUFFERSYNCER_H diff --git a/src/core/corebufferviewconfig.cpp b/src/core/corebufferviewconfig.cpp index ab0f3089..80576bb2 100644 --- a/src/core/corebufferviewconfig.cpp +++ b/src/core/corebufferviewconfig.cpp @@ -22,13 +22,14 @@ INIT_SYNCABLE_OBJECT(CoreBufferViewConfig) CoreBufferViewConfig::CoreBufferViewConfig(int bufferViewId, QObject *parent) - : BufferViewConfig(bufferViewId, parent) + : BufferViewConfig(bufferViewId, parent) { - setAllowClientUpdates(true); + setAllowClientUpdates(true); } + CoreBufferViewConfig::CoreBufferViewConfig(int bufferViewId, const QVariantMap &properties, QObject *parent) - : BufferViewConfig(bufferViewId, properties, parent) + : BufferViewConfig(bufferViewId, properties, parent) { - setAllowClientUpdates(true); + setAllowClientUpdates(true); } diff --git a/src/core/corebufferviewconfig.h b/src/core/corebufferviewconfig.h index 5334b946..d77698d4 100644 --- a/src/core/corebufferviewconfig.h +++ b/src/core/corebufferviewconfig.h @@ -23,22 +23,24 @@ #ifndef COREBUFFERVIEWCONFIG_H #define COREBUFFERVIEWCONFIG_H -class CoreBufferViewConfig : public BufferViewConfig { - SYNCABLE_OBJECT - Q_OBJECT +class CoreBufferViewConfig : public BufferViewConfig +{ + SYNCABLE_OBJECT + Q_OBJECT public: - CoreBufferViewConfig(int bufferViewId, QObject *parent = 0); - CoreBufferViewConfig(int bufferViewId, const QVariantMap &properties, QObject *parent = 0); - - inline virtual const QMetaObject *syncMetaObject() const { return &BufferViewConfig::staticMetaObject; } + CoreBufferViewConfig(int bufferViewId, QObject *parent = 0); + CoreBufferViewConfig(int bufferViewId, const QVariantMap &properties, QObject *parent = 0); + + inline virtual const QMetaObject *syncMetaObject() const { return &BufferViewConfig::staticMetaObject; } public slots: - virtual inline void requestSetBufferViewName(const QString &bufferViewName) { setBufferViewName(bufferViewName); } - virtual inline void requestRemoveBuffer(const BufferId &bufferId) { removeBuffer(bufferId); } - virtual inline void requestRemoveBufferPermanently(const BufferId &bufferId) { removeBufferPermanently(bufferId); } - virtual inline void requestAddBuffer(const BufferId &bufferId, int pos) { addBuffer(bufferId, pos); } - virtual inline void requestMoveBuffer(const BufferId &bufferId, int pos) { moveBuffer(bufferId, pos); } + virtual inline void requestSetBufferViewName(const QString &bufferViewName) { setBufferViewName(bufferViewName); } + virtual inline void requestRemoveBuffer(const BufferId &bufferId) { removeBuffer(bufferId); } + virtual inline void requestRemoveBufferPermanently(const BufferId &bufferId) { removeBufferPermanently(bufferId); } + virtual inline void requestAddBuffer(const BufferId &bufferId, int pos) { addBuffer(bufferId, pos); } + virtual inline void requestMoveBuffer(const BufferId &bufferId, int pos) { moveBuffer(bufferId, pos); } }; + #endif // COREBUFFERVIEWCONFIG_H diff --git a/src/core/corebufferviewmanager.cpp b/src/core/corebufferviewmanager.cpp index 4560a521..58a1dd48 100644 --- a/src/core/corebufferviewmanager.cpp +++ b/src/core/corebufferviewmanager.cpp @@ -27,68 +27,78 @@ INIT_SYNCABLE_OBJECT(CoreBufferViewManager) CoreBufferViewManager::CoreBufferViewManager(SignalProxy *proxy, CoreSession *parent) - : BufferViewManager(proxy, parent), + : BufferViewManager(proxy, parent), _coreSession(parent) { - QVariantMap views = Core::getUserSetting(_coreSession->user(), "BufferViews").toMap(); - QVariantMap::iterator iter = views.begin(); - QVariantMap::iterator iterEnd = views.end(); - CoreBufferViewConfig *config = 0; - while(iter != iterEnd) { - config = new CoreBufferViewConfig(iter.key().toInt(), iter.value().toMap(), this); - addBufferViewConfig(config); - iter++; - } + QVariantMap views = Core::getUserSetting(_coreSession->user(), "BufferViews").toMap(); + QVariantMap::iterator iter = views.begin(); + QVariantMap::iterator iterEnd = views.end(); + CoreBufferViewConfig *config = 0; + while (iter != iterEnd) { + config = new CoreBufferViewConfig(iter.key().toInt(), iter.value().toMap(), this); + addBufferViewConfig(config); + iter++; + } } -void CoreBufferViewManager::saveBufferViews() { - QVariantMap views; - BufferViewConfigHash::const_iterator iter = bufferViewConfigHash().constBegin(); - BufferViewConfigHash::const_iterator iterEnd = bufferViewConfigHash().constEnd(); - while(iter != iterEnd) { - views[QString::number((*iter)->bufferViewId())] = (*iter)->toVariantMap(); - iter++; - } +void CoreBufferViewManager::saveBufferViews() +{ + QVariantMap views; + + BufferViewConfigHash::const_iterator iter = bufferViewConfigHash().constBegin(); + BufferViewConfigHash::const_iterator iterEnd = bufferViewConfigHash().constEnd(); + while (iter != iterEnd) { + views[QString::number((*iter)->bufferViewId())] = (*iter)->toVariantMap(); + iter++; + } - Core::setUserSetting(_coreSession->user(), "BufferViews", views); + Core::setUserSetting(_coreSession->user(), "BufferViews", views); } -void CoreBufferViewManager::requestCreateBufferView(const QVariantMap &properties) { - QString bufferViewName = properties["bufferViewName"].toString(); - int maxId = -1; - BufferViewConfigHash::const_iterator iter = bufferViewConfigHash().constBegin(); - BufferViewConfigHash::const_iterator iterEnd = bufferViewConfigHash().constEnd(); - while(iter != iterEnd) { - if((*iter)->bufferViewName() == bufferViewName) - return; - - if((*iter)->bufferViewId() > maxId) - maxId = (*iter)->bufferViewId(); - - iter++; - } - maxId++; - - CoreBufferViewConfig *config = new CoreBufferViewConfig(maxId, properties); - addBufferViewConfig(config); + +void CoreBufferViewManager::requestCreateBufferView(const QVariantMap &properties) +{ + QString bufferViewName = properties["bufferViewName"].toString(); + int maxId = -1; + BufferViewConfigHash::const_iterator iter = bufferViewConfigHash().constBegin(); + BufferViewConfigHash::const_iterator iterEnd = bufferViewConfigHash().constEnd(); + while (iter != iterEnd) { + if ((*iter)->bufferViewName() == bufferViewName) + return; + + if ((*iter)->bufferViewId() > maxId) + maxId = (*iter)->bufferViewId(); + + iter++; + } + maxId++; + + CoreBufferViewConfig *config = new CoreBufferViewConfig(maxId, properties); + addBufferViewConfig(config); } -void CoreBufferViewManager::requestCreateBufferViews(const QVariantList &properties) { - QVariantList::const_iterator iter = properties.constBegin(); - QVariantList::const_iterator iterEnd = properties.constEnd(); - while(iter != iterEnd) { - requestCreateBufferView((*iter).toMap()); - iter++; - } + +void CoreBufferViewManager::requestCreateBufferViews(const QVariantList &properties) +{ + QVariantList::const_iterator iter = properties.constBegin(); + QVariantList::const_iterator iterEnd = properties.constEnd(); + while (iter != iterEnd) { + requestCreateBufferView((*iter).toMap()); + iter++; + } } -void CoreBufferViewManager::requestDeleteBufferView(int bufferViewId) { - deleteBufferViewConfig(bufferViewId); + +void CoreBufferViewManager::requestDeleteBufferView(int bufferViewId) +{ + deleteBufferViewConfig(bufferViewId); } -void CoreBufferViewManager::requestDeleteBufferViews(const QVariantList &bufferViews) { - foreach(QVariant bufferView, bufferViews) { - deleteBufferViewConfig(bufferView.toInt()); - } + +void CoreBufferViewManager::requestDeleteBufferViews(const QVariantList &bufferViews) +{ + foreach(QVariant bufferView, bufferViews) { + deleteBufferViewConfig(bufferView.toInt()); + } } diff --git a/src/core/corebufferviewmanager.h b/src/core/corebufferviewmanager.h index 4bedb281..fd28c1d9 100644 --- a/src/core/corebufferviewmanager.h +++ b/src/core/corebufferviewmanager.h @@ -25,26 +25,27 @@ class CoreSession; -class CoreBufferViewManager : public BufferViewManager { - SYNCABLE_OBJECT - Q_OBJECT +class CoreBufferViewManager : public BufferViewManager +{ + SYNCABLE_OBJECT + Q_OBJECT public: - CoreBufferViewManager(SignalProxy *proxy, CoreSession *parent); - - inline virtual const QMetaObject *syncMetaObject() const { return &BufferViewManager::staticMetaObject; } + CoreBufferViewManager(SignalProxy *proxy, CoreSession *parent); + + inline virtual const QMetaObject *syncMetaObject() const { return &BufferViewManager::staticMetaObject; } public slots: - virtual void requestCreateBufferView(const QVariantMap &properties); - virtual void requestCreateBufferViews(const QVariantList &properties); - virtual void requestDeleteBufferView(int bufferViewId); - virtual void requestDeleteBufferViews(const QVariantList &bufferViews); + virtual void requestCreateBufferView(const QVariantMap &properties); + virtual void requestCreateBufferViews(const QVariantList &properties); + virtual void requestDeleteBufferView(int bufferViewId); + virtual void requestDeleteBufferViews(const QVariantList &bufferViews); - void saveBufferViews(); + void saveBufferViews(); private: - CoreSession *_coreSession; + CoreSession *_coreSession; }; -#endif // COREBUFFERVIEWMANAGER_H +#endif // COREBUFFERVIEWMANAGER_H diff --git a/src/core/corecoreinfo.cpp b/src/core/corecoreinfo.cpp index 195026a7..d8f72408 100644 --- a/src/core/corecoreinfo.cpp +++ b/src/core/corecoreinfo.cpp @@ -27,16 +27,18 @@ INIT_SYNCABLE_OBJECT(CoreCoreInfo) CoreCoreInfo::CoreCoreInfo(CoreSession *parent) - : CoreInfo(parent), + : CoreInfo(parent), _coreSession(parent) { } -QVariantMap CoreCoreInfo::coreData() const { - QVariantMap data; - data["quasselVersion"] = Quassel::buildInfo().fancyVersionString; - data["quasselBuildDate"] = Quassel::buildInfo().buildDate; - data["startTime"] = Core::instance()->startTime(); - data["sessionConnectedClients"] = _coreSession->signalProxy()->peerCount(); - return data; + +QVariantMap CoreCoreInfo::coreData() const +{ + QVariantMap data; + data["quasselVersion"] = Quassel::buildInfo().fancyVersionString; + data["quasselBuildDate"] = Quassel::buildInfo().buildDate; + data["startTime"] = Core::instance()->startTime(); + data["sessionConnectedClients"] = _coreSession->signalProxy()->peerCount(); + return data; } diff --git a/src/core/corecoreinfo.h b/src/core/corecoreinfo.h index 7bda4f04..0e77f962 100644 --- a/src/core/corecoreinfo.h +++ b/src/core/corecoreinfo.h @@ -28,21 +28,23 @@ class CoreSession; /* * Yes this name is somewhat stupid... but it fits the general naming scheme * which is prefixing core specific sync objects with "Core"... ;) - */ -class CoreCoreInfo : public CoreInfo { - SYNCABLE_OBJECT - Q_OBJECT + */ +class CoreCoreInfo : public CoreInfo +{ + SYNCABLE_OBJECT + Q_OBJECT public: - CoreCoreInfo(CoreSession *parent); + CoreCoreInfo(CoreSession *parent); - inline virtual const QMetaObject *syncMetaObject() const { return &CoreInfo::staticMetaObject; } + inline virtual const QMetaObject *syncMetaObject() const { return &CoreInfo::staticMetaObject; } public slots: - virtual QVariantMap coreData() const; + virtual QVariantMap coreData() const; private: - CoreSession *_coreSession; + CoreSession *_coreSession; }; + #endif //CORECOREINFO_H diff --git a/src/core/coreeventmanager.h b/src/core/coreeventmanager.h index 41e5f1c9..01e0c2b7 100644 --- a/src/core/coreeventmanager.h +++ b/src/core/coreeventmanager.h @@ -29,19 +29,20 @@ class CoreSession; class CoreEventManager : public EventManager { - Q_OBJECT + Q_OBJECT public: - CoreEventManager(CoreSession *session) - : EventManager(session) - , _coreSession(session) - { } + CoreEventManager(CoreSession *session) + : EventManager(session) + , _coreSession(session) + {} protected: - inline Network *networkById(NetworkId id) const { return _coreSession->network(id); } + inline Network *networkById(NetworkId id) const { return _coreSession->network(id); } private: - CoreSession *_coreSession; + CoreSession *_coreSession; }; + #endif diff --git a/src/core/coreidentity.cpp b/src/core/coreidentity.cpp index fef75222..2ea428d8 100644 --- a/src/core/coreidentity.cpp +++ b/src/core/coreidentity.cpp @@ -24,95 +24,115 @@ INIT_SYNCABLE_OBJECT(CoreIdentity) CoreIdentity::CoreIdentity(IdentityId id, QObject *parent) - : Identity(id, parent) + : Identity(id, parent) #ifdef HAVE_SSL - , _certManager(*this) + , _certManager(*this) #endif { #ifdef HAVE_SSL - connect(this, SIGNAL(idSet(IdentityId)), &_certManager, SLOT(setId(IdentityId))); - connect(&_certManager, SIGNAL(updated()), this, SIGNAL(updated())); + connect(this, SIGNAL(idSet(IdentityId)), &_certManager, SLOT(setId(IdentityId))); + connect(&_certManager, SIGNAL(updated()), this, SIGNAL(updated())); #endif } + CoreIdentity::CoreIdentity(const Identity &other, QObject *parent) - : Identity(other, parent) + : Identity(other, parent) #ifdef HAVE_SSL - , _certManager(*this) + , _certManager(*this) #endif { #ifdef HAVE_SSL - connect(this, SIGNAL(idSet(IdentityId)), &_certManager, SLOT(setId(IdentityId))); - connect(&_certManager, SIGNAL(updated()), this, SIGNAL(updated())); + connect(this, SIGNAL(idSet(IdentityId)), &_certManager, SLOT(setId(IdentityId))); + connect(&_certManager, SIGNAL(updated()), this, SIGNAL(updated())); #endif } + CoreIdentity::CoreIdentity(const CoreIdentity &other, QObject *parent) - : Identity(other, parent) + : Identity(other, parent) #ifdef HAVE_SSL - , _sslKey(other._sslKey), + , _sslKey(other._sslKey), _sslCert(other._sslCert), _certManager(*this) #endif { #ifdef HAVE_SSL - connect(this, SIGNAL(idSet(IdentityId)), &_certManager, SLOT(setId(IdentityId))); - connect(&_certManager, SIGNAL(updated()), this, SIGNAL(updated())); + connect(this, SIGNAL(idSet(IdentityId)), &_certManager, SLOT(setId(IdentityId))); + connect(&_certManager, SIGNAL(updated()), this, SIGNAL(updated())); #endif } -void CoreIdentity::synchronize(SignalProxy *proxy) { - proxy->synchronize(this); + +void CoreIdentity::synchronize(SignalProxy *proxy) +{ + proxy->synchronize(this); #ifdef HAVE_SSL - proxy->synchronize(&_certManager); + proxy->synchronize(&_certManager); #endif } + #ifdef HAVE_SSL -void CoreIdentity::setSslKey(const QByteArray &encoded) { - QSslKey key(encoded, QSsl::Rsa); - if(key.isNull()) - key = QSslKey(encoded, QSsl::Dsa); - setSslKey(key); +void CoreIdentity::setSslKey(const QByteArray &encoded) +{ + QSslKey key(encoded, QSsl::Rsa); + if (key.isNull()) + key = QSslKey(encoded, QSsl::Dsa); + setSslKey(key); } -void CoreIdentity::setSslCert(const QByteArray &encoded) { - setSslCert(QSslCertificate(encoded)); + +void CoreIdentity::setSslCert(const QByteArray &encoded) +{ + setSslCert(QSslCertificate(encoded)); } + + #endif -CoreIdentity &CoreIdentity::operator=(const CoreIdentity &identity) { - Identity::operator=(identity); +CoreIdentity &CoreIdentity::operator=(const CoreIdentity &identity) +{ + Identity::operator=(identity); #ifdef HAVE_SSL - _sslKey = identity._sslKey; - _sslCert = identity._sslCert; + _sslKey = identity._sslKey; + _sslCert = identity._sslCert; #endif - return *this; + return *this; } + #ifdef HAVE_SSL // ======================================== // CoreCertManager // ======================================== INIT_SYNCABLE_OBJECT(CoreCertManager) CoreCertManager::CoreCertManager(CoreIdentity &identity) - : CertManager(identity.id()), + : CertManager(identity.id()), identity(identity) { - setAllowClientUpdates(true); + setAllowClientUpdates(true); } -void CoreCertManager::setId(IdentityId id) { - renameObject(QString::number(id.toInt())); + +void CoreCertManager::setId(IdentityId id) +{ + renameObject(QString::number(id.toInt())); } -void CoreCertManager::setSslKey(const QByteArray &encoded) { - identity.setSslKey(encoded); - CertManager::setSslKey(encoded); + +void CoreCertManager::setSslKey(const QByteArray &encoded) +{ + identity.setSslKey(encoded); + CertManager::setSslKey(encoded); } -void CoreCertManager::setSslCert(const QByteArray &encoded) { - identity.setSslCert(encoded); - CertManager::setSslCert(encoded); + +void CoreCertManager::setSslCert(const QByteArray &encoded) +{ + identity.setSslCert(encoded); + CertManager::setSslCert(encoded); } + + #endif //HAVE_SSL diff --git a/src/core/coreidentity.h b/src/core/coreidentity.h index 6cb6cd11..0c35c5bb 100644 --- a/src/core/coreidentity.h +++ b/src/core/coreidentity.h @@ -35,70 +35,81 @@ class SignalProxy; // ======================================== #ifdef HAVE_SSL class CoreIdentity; -class CoreCertManager : public CertManager { - SYNCABLE_OBJECT - Q_OBJECT +class CoreCertManager : public CertManager +{ + SYNCABLE_OBJECT + Q_OBJECT public: - CoreCertManager(CoreIdentity &identity); + CoreCertManager(CoreIdentity &identity); #ifdef HAVE_SSL - virtual const QSslKey &sslKey() const; - virtual const QSslCertificate &sslCert() const; + virtual const QSslKey &sslKey() const; + virtual const QSslCertificate &sslCert() const; public slots: - virtual void setSslKey(const QByteArray &encoded); - virtual void setSslCert(const QByteArray &encoded); + virtual void setSslKey(const QByteArray &encoded); + virtual void setSslCert(const QByteArray &encoded); #endif - void setId(IdentityId id); + void setId(IdentityId id); private: - CoreIdentity &identity; + CoreIdentity &identity; }; + + #endif //HAVE_SSL // ========================================= // CoreIdentity // ========================================= -class CoreIdentity : public Identity { - SYNCABLE_OBJECT - Q_OBJECT +class CoreIdentity : public Identity +{ + SYNCABLE_OBJECT + Q_OBJECT public: - CoreIdentity(IdentityId id, QObject *parent = 0); - CoreIdentity(const Identity &other, QObject *parent = 0); - CoreIdentity(const CoreIdentity &other, QObject *parent = 0); + CoreIdentity(IdentityId id, QObject *parent = 0); + CoreIdentity(const Identity &other, QObject *parent = 0); + CoreIdentity(const CoreIdentity &other, QObject *parent = 0); - void synchronize(SignalProxy *proxy); + void synchronize(SignalProxy *proxy); #ifdef HAVE_SSL - inline const QSslKey &sslKey() const { return _sslKey; } - inline void setSslKey(const QSslKey &key) { _sslKey = key; } - void setSslKey(const QByteArray &encoded); - inline const QSslCertificate &sslCert() const { return _sslCert; } - inline void setSslCert(const QSslCertificate &cert) { _sslCert = cert; } - void setSslCert(const QByteArray &encoded); + inline const QSslKey &sslKey() const { return _sslKey; } + inline void setSslKey(const QSslKey &key) { _sslKey = key; } + void setSslKey(const QByteArray &encoded); + inline const QSslCertificate &sslCert() const { return _sslCert; } + inline void setSslCert(const QSslCertificate &cert) { _sslCert = cert; } + void setSslCert(const QByteArray &encoded); #endif /* HAVE_SSL */ - CoreIdentity& operator=(const CoreIdentity &identity); + CoreIdentity &operator=(const CoreIdentity &identity); private: #ifdef HAVE_SSL - QSslKey _sslKey; - QSslCertificate _sslCert; + QSslKey _sslKey; + QSslCertificate _sslCert; - CoreCertManager _certManager; + CoreCertManager _certManager; #endif }; + #ifdef HAVE_SSL -inline const QSslKey &CoreCertManager::sslKey() const { - return identity.sslKey(); +inline const QSslKey &CoreCertManager::sslKey() const +{ + return identity.sslKey(); } -inline const QSslCertificate &CoreCertManager::sslCert() const { - return identity.sslCert(); + + +inline const QSslCertificate &CoreCertManager::sslCert() const +{ + return identity.sslCert(); } + + #endif #endif //COREIDENTITY_H diff --git a/src/core/coreignorelistmanager.cpp b/src/core/coreignorelistmanager.cpp index e3cc70b4..36c70360 100644 --- a/src/core/coreignorelistmanager.cpp +++ b/src/core/coreignorelistmanager.cpp @@ -25,39 +25,44 @@ INIT_SYNCABLE_OBJECT(CoreIgnoreListManager) CoreIgnoreListManager::CoreIgnoreListManager(CoreSession *parent) - : IgnoreListManager(parent) + : IgnoreListManager(parent) { - CoreSession *session = qobject_cast(parent); - if(!session) { - qWarning() << "CoreIgnoreListManager: unable to load IgnoreList. Parent is not a Coresession!"; - //loadDefaults(); - return; - } + CoreSession *session = qobject_cast(parent); + if (!session) { + qWarning() << "CoreIgnoreListManager: unable to load IgnoreList. Parent is not a Coresession!"; + //loadDefaults(); + return; + } - initSetIgnoreList(Core::getUserSetting(session->user(), "IgnoreList").toMap()); + initSetIgnoreList(Core::getUserSetting(session->user(), "IgnoreList").toMap()); - // we store our settings whenever they change - connect(this, SIGNAL(updatedRemotely()), SLOT(save())); + // we store our settings whenever they change + connect(this, SIGNAL(updatedRemotely()), SLOT(save())); - //if(isEmpty()) + //if(isEmpty()) //loadDefaults(); } -IgnoreListManager::StrictnessType CoreIgnoreListManager::match(const RawMessage &rawMsg, const QString &networkName) { - //StrictnessType _match(const QString &msgContents, const QString &msgSender, Message::Type msgType, const QString &network, const QString &bufferName); - return _match(rawMsg.text, rawMsg.sender, rawMsg.type, networkName, rawMsg.target); + +IgnoreListManager::StrictnessType CoreIgnoreListManager::match(const RawMessage &rawMsg, const QString &networkName) +{ + //StrictnessType _match(const QString &msgContents, const QString &msgSender, Message::Type msgType, const QString &network, const QString &bufferName); + return _match(rawMsg.text, rawMsg.sender, rawMsg.type, networkName, rawMsg.target); } -void CoreIgnoreListManager::save() const { - CoreSession *session = qobject_cast(parent()); - if(!session) { - qWarning() << "CoreIgnoreListManager: unable to save IgnoreList. Parent is not a Coresession!"; - return; - } - Core::setUserSetting(session->user(), "IgnoreList", initIgnoreList()); +void CoreIgnoreListManager::save() const +{ + CoreSession *session = qobject_cast(parent()); + if (!session) { + qWarning() << "CoreIgnoreListManager: unable to save IgnoreList. Parent is not a Coresession!"; + return; + } + + Core::setUserSetting(session->user(), "IgnoreList", initIgnoreList()); } + //void CoreIgnoreListManager::loadDefaults() { // foreach(IgnoreListItem item, IgnoreListManager::defaults()) { // addIgnoreListItem(item.ignoreRule, item.isRegEx, item.strictness, item.scope, item.scopeRule); diff --git a/src/core/coreignorelistmanager.h b/src/core/coreignorelistmanager.h index d7d5c9cf..051b44ca 100644 --- a/src/core/coreignorelistmanager.h +++ b/src/core/coreignorelistmanager.h @@ -26,31 +26,34 @@ class CoreSession; struct RawMessage; -class CoreIgnoreListManager : public IgnoreListManager { - SYNCABLE_OBJECT - Q_OBJECT +class CoreIgnoreListManager : public IgnoreListManager +{ + SYNCABLE_OBJECT + Q_OBJECT public: - explicit CoreIgnoreListManager(CoreSession *parent); + explicit CoreIgnoreListManager(CoreSession *parent); - inline virtual const QMetaObject *syncMetaObject() const { return &IgnoreListManager::staticMetaObject; } + inline virtual const QMetaObject *syncMetaObject() const { return &IgnoreListManager::staticMetaObject; } - StrictnessType match(const RawMessage &rawMsg, const QString &networkName); + StrictnessType match(const RawMessage &rawMsg, const QString &networkName); public slots: - virtual inline void requestToggleIgnoreRule(const QString &ignoreRule) { toggleIgnoreRule(ignoreRule); } - virtual inline void requestRemoveIgnoreListItem(const QString &ignoreRule) { removeIgnoreListItem(ignoreRule); } - virtual inline void requestAddIgnoreListItem(int type, const QString &ignoreRule, bool isRegEx, int strictness, - int scope, const QString &scopeRule, bool isActive) { - addIgnoreListItem(type, ignoreRule, isRegEx, strictness, scope, scopeRule, isActive); - } + virtual inline void requestToggleIgnoreRule(const QString &ignoreRule) { toggleIgnoreRule(ignoreRule); } + virtual inline void requestRemoveIgnoreListItem(const QString &ignoreRule) { removeIgnoreListItem(ignoreRule); } + virtual inline void requestAddIgnoreListItem(int type, const QString &ignoreRule, bool isRegEx, int strictness, + int scope, const QString &scopeRule, bool isActive) + { + addIgnoreListItem(type, ignoreRule, isRegEx, strictness, scope, scopeRule, isActive); + } + private slots: - void save() const; + void save() const; //private: // void loadDefaults(); - }; + #endif //COREIGNORELISTMANAGER_H diff --git a/src/core/coreircchannel.cpp b/src/core/coreircchannel.cpp index 20855104..2dd1d9d9 100644 --- a/src/core/coreircchannel.cpp +++ b/src/core/coreircchannel.cpp @@ -23,46 +23,53 @@ INIT_SYNCABLE_OBJECT(CoreIrcChannel) CoreIrcChannel::CoreIrcChannel(const QString &channelname, Network *network) - : IrcChannel(channelname, network), + : IrcChannel(channelname, network), _receivedWelcomeMsg(false) { #ifdef HAVE_QCA2 - _cipher = 0; + _cipher = 0; #endif } -CoreIrcChannel::~CoreIrcChannel() { + +CoreIrcChannel::~CoreIrcChannel() +{ #ifdef HAVE_QCA2 - delete _cipher; + delete _cipher; #endif } + #ifdef HAVE_QCA2 -Cipher *CoreIrcChannel::cipher() const { - if(!_cipher) - _cipher = new Cipher(); +Cipher *CoreIrcChannel::cipher() const +{ + if (!_cipher) + _cipher = new Cipher(); - return _cipher; + return _cipher; } -void CoreIrcChannel::setEncrypted(bool e) { - if(!Cipher::neededFeaturesAvailable()) - return; - if(e) { - if(topic().isEmpty()) - return; +void CoreIrcChannel::setEncrypted(bool e) +{ + if (!Cipher::neededFeaturesAvailable()) + return; + + if (e) { + if (topic().isEmpty()) + return; - QByteArray key = qobject_cast(network())->cipherKey(name()); - if(key.isEmpty()) - return; + QByteArray key = qobject_cast(network())->cipherKey(name()); + if (key.isEmpty()) + return; - if(!cipher()->setKey(key)) - return; + if (!cipher()->setKey(key)) + return; - QByteArray decrypted = cipher()->decryptTopic(topic().toAscii()); - setTopic(decodeString(decrypted)); - } + QByteArray decrypted = cipher()->decryptTopic(topic().toAscii()); + setTopic(decodeString(decrypted)); + } } + #endif diff --git a/src/core/coreircchannel.h b/src/core/coreircchannel.h index 16c96ebd..3ae7a214 100644 --- a/src/core/coreircchannel.h +++ b/src/core/coreircchannel.h @@ -27,30 +27,32 @@ # include "cipher.h" #endif -class CoreIrcChannel : public IrcChannel { - SYNCABLE_OBJECT - Q_OBJECT +class CoreIrcChannel : public IrcChannel +{ + SYNCABLE_OBJECT + Q_OBJECT public: - CoreIrcChannel(const QString &channelname, Network *network); - virtual ~CoreIrcChannel(); + CoreIrcChannel(const QString &channelname, Network *network); + virtual ~CoreIrcChannel(); - inline virtual const QMetaObject *syncMetaObject() const { return &IrcChannel::staticMetaObject; } + inline virtual const QMetaObject *syncMetaObject() const { return &IrcChannel::staticMetaObject; } #ifdef HAVE_QCA2 - Cipher *cipher() const; - void setEncrypted(bool); + Cipher *cipher() const; + void setEncrypted(bool); #endif - inline bool receivedWelcomeMsg() const { return _receivedWelcomeMsg; } - inline void setReceivedWelcomeMsg() { _receivedWelcomeMsg = true; } + inline bool receivedWelcomeMsg() const { return _receivedWelcomeMsg; } + inline void setReceivedWelcomeMsg() { _receivedWelcomeMsg = true; } private: - bool _receivedWelcomeMsg; + bool _receivedWelcomeMsg; #ifdef HAVE_QCA2 - mutable Cipher *_cipher; + mutable Cipher *_cipher; #endif }; + #endif //COREIRCCHANNEL_H diff --git a/src/core/coreirclisthelper.cpp b/src/core/coreirclisthelper.cpp index 05454713..5b0ef239 100644 --- a/src/core/coreirclisthelper.cpp +++ b/src/core/coreirclisthelper.cpp @@ -24,63 +24,76 @@ #include "coreuserinputhandler.h" INIT_SYNCABLE_OBJECT(CoreIrcListHelper) -QVariantList CoreIrcListHelper::requestChannelList(const NetworkId &netId, const QStringList &channelFilters) { - if(_finishedChannelLists.contains(netId)) - return _finishedChannelLists.take(netId); - - if(_channelLists.contains(netId)) { - _queuedQuery[netId] = channelFilters.join(","); - } else { - dispatchQuery(netId, channelFilters.join(",")); - } - return QVariantList(); +QVariantList CoreIrcListHelper::requestChannelList(const NetworkId &netId, const QStringList &channelFilters) +{ + if (_finishedChannelLists.contains(netId)) + return _finishedChannelLists.take(netId); + + if (_channelLists.contains(netId)) { + _queuedQuery[netId] = channelFilters.join(","); + } + else { + dispatchQuery(netId, channelFilters.join(",")); + } + return QVariantList(); } -bool CoreIrcListHelper::addChannel(const NetworkId &netId, const QString &channelName, quint32 userCount, const QString &topic) { - if(!_channelLists.contains(netId)) - return false; - _channelLists[netId] << ChannelDescription(channelName, userCount, topic); - return true; -} +bool CoreIrcListHelper::addChannel(const NetworkId &netId, const QString &channelName, quint32 userCount, const QString &topic) +{ + if (!_channelLists.contains(netId)) + return false; -bool CoreIrcListHelper::dispatchQuery(const NetworkId &netId, const QString &query) { - CoreNetwork *network = coreSession()->network(netId); - if(network) { - _channelLists[netId] = QList(); - network->userInputHandler()->handleList(BufferInfo(), query); - _queryTimeout[startTimer(10000)] = netId; + _channelLists[netId] << ChannelDescription(channelName, userCount, topic); return true; - } else { - return false; - } } -bool CoreIrcListHelper::endOfChannelList(const NetworkId &netId) { - if(_queuedQuery.contains(netId)) { - // we're no longer interessted in the current data. drop it and issue a new request. - return dispatchQuery(netId, _queuedQuery.take(netId)); - } else if(_channelLists.contains(netId)) { - QVariantList channelList; - foreach(ChannelDescription channel, _channelLists[netId]) { - QVariantList channelVariant; - channelVariant << channel.channelName - << channel.userCount - << channel.topic; - channelList << qVariantFromValue(channelVariant); + +bool CoreIrcListHelper::dispatchQuery(const NetworkId &netId, const QString &query) +{ + CoreNetwork *network = coreSession()->network(netId); + if (network) { + _channelLists[netId] = QList(); + network->userInputHandler()->handleList(BufferInfo(), query); + _queryTimeout[startTimer(10000)] = netId; + return true; + } + else { + return false; } - _finishedChannelLists[netId] = channelList; - _channelLists.remove(netId); - reportFinishedList(netId); - return true; - } else { - return false; - } } -void CoreIrcListHelper::timerEvent(QTimerEvent *event) { - int timerId = event->timerId(); - killTimer(timerId); - NetworkId netId = _queryTimeout.take(timerId); - endOfChannelList(netId); + +bool CoreIrcListHelper::endOfChannelList(const NetworkId &netId) +{ + if (_queuedQuery.contains(netId)) { + // we're no longer interessted in the current data. drop it and issue a new request. + return dispatchQuery(netId, _queuedQuery.take(netId)); + } + else if (_channelLists.contains(netId)) { + QVariantList channelList; + foreach(ChannelDescription channel, _channelLists[netId]) { + QVariantList channelVariant; + channelVariant << channel.channelName + << channel.userCount + << channel.topic; + channelList << qVariantFromValue(channelVariant); + } + _finishedChannelLists[netId] = channelList; + _channelLists.remove(netId); + reportFinishedList(netId); + return true; + } + else { + return false; + } +} + + +void CoreIrcListHelper::timerEvent(QTimerEvent *event) +{ + int timerId = event->timerId(); + killTimer(timerId); + NetworkId netId = _queryTimeout.take(timerId); + endOfChannelList(netId); } diff --git a/src/core/coreirclisthelper.h b/src/core/coreirclisthelper.h index 688344a1..2660c281 100644 --- a/src/core/coreirclisthelper.h +++ b/src/core/coreirclisthelper.h @@ -27,37 +27,39 @@ class QTimerEvent; -class CoreIrcListHelper : public IrcListHelper { - SYNCABLE_OBJECT - Q_OBJECT +class CoreIrcListHelper : public IrcListHelper +{ + SYNCABLE_OBJECT + Q_OBJECT public: - inline CoreIrcListHelper(CoreSession *coreSession) : IrcListHelper(coreSession), _coreSession(coreSession) {}; + inline CoreIrcListHelper(CoreSession *coreSession) : IrcListHelper(coreSession), _coreSession(coreSession) {}; - inline virtual const QMetaObject *syncMetaObject() const { return &IrcListHelper::staticMetaObject; } + inline virtual const QMetaObject *syncMetaObject() const { return &IrcListHelper::staticMetaObject; } - inline CoreSession *coreSession() const { return _coreSession; } + inline CoreSession *coreSession() const { return _coreSession; } - inline bool requestInProgress(const NetworkId &netId) const { return _channelLists.contains(netId); } + inline bool requestInProgress(const NetworkId &netId) const { return _channelLists.contains(netId); } public slots: - virtual QVariantList requestChannelList(const NetworkId &netId, const QStringList &channelFilters); - bool addChannel(const NetworkId &netId, const QString &channelName, quint32 userCount, const QString &topic); - bool endOfChannelList(const NetworkId &netId); + virtual QVariantList requestChannelList(const NetworkId &netId, const QStringList &channelFilters); + bool addChannel(const NetworkId &netId, const QString &channelName, quint32 userCount, const QString &topic); + bool endOfChannelList(const NetworkId &netId); protected: - void timerEvent(QTimerEvent *event); + void timerEvent(QTimerEvent *event); private: - bool dispatchQuery(const NetworkId &netId, const QString &query); + bool dispatchQuery(const NetworkId &netId, const QString &query); private: - CoreSession *_coreSession; + CoreSession *_coreSession; - QHash _queuedQuery; - QHash > _channelLists; - QHash _finishedChannelLists; - QHash _queryTimeout; + QHash _queuedQuery; + QHash > _channelLists; + QHash _finishedChannelLists; + QHash _queryTimeout; }; + #endif //COREIRCLISTHELPER_H diff --git a/src/core/coreircuser.cpp b/src/core/coreircuser.cpp index 367474b5..17b12d59 100644 --- a/src/core/coreircuser.cpp +++ b/src/core/coreircuser.cpp @@ -20,29 +20,37 @@ #include "coreircuser.h" -CoreIrcUser::CoreIrcUser(const QString &hostmask, Network *network) : IrcUser(hostmask, network) { +CoreIrcUser::CoreIrcUser(const QString &hostmask, Network *network) : IrcUser(hostmask, network) +{ #ifdef HAVE_QCA2 - _cipher = 0; + _cipher = 0; #endif } -CoreIrcUser::~CoreIrcUser() { + +CoreIrcUser::~CoreIrcUser() +{ #ifdef HAVE_QCA2 - delete _cipher; + delete _cipher; #endif } + #ifdef HAVE_QCA2 -Cipher *CoreIrcUser::cipher() const { - if(!_cipher) - _cipher = new Cipher(); +Cipher *CoreIrcUser::cipher() const +{ + if (!_cipher) + _cipher = new Cipher(); - return _cipher; + return _cipher; } -void CoreIrcUser::setEncrypted(bool e) { - Q_UNUSED(e); - // TODO + +void CoreIrcUser::setEncrypted(bool e) +{ + Q_UNUSED(e); + // TODO } + #endif diff --git a/src/core/coreircuser.h b/src/core/coreircuser.h index f8430e3a..47b8911d 100644 --- a/src/core/coreircuser.h +++ b/src/core/coreircuser.h @@ -27,25 +27,27 @@ # include "cipher.h" #endif -class CoreIrcUser : public IrcUser { - SYNCABLE_OBJECT - Q_OBJECT +class CoreIrcUser : public IrcUser +{ + SYNCABLE_OBJECT + Q_OBJECT public: - CoreIrcUser(const QString &hostmask, Network *network); - virtual ~CoreIrcUser(); + CoreIrcUser(const QString &hostmask, Network *network); + virtual ~CoreIrcUser(); - inline virtual const QMetaObject *syncMetaObject() const { return &IrcUser::staticMetaObject; } + inline virtual const QMetaObject *syncMetaObject() const { return &IrcUser::staticMetaObject; } #ifdef HAVE_QCA2 - Cipher *cipher() const; - void setEncrypted(bool); + Cipher *cipher() const; + void setEncrypted(bool); #endif #ifdef HAVE_QCA2 private: - mutable Cipher *_cipher; + mutable Cipher *_cipher; #endif }; + #endif diff --git a/src/core/corenetwork.cpp b/src/core/corenetwork.cpp index 02f38422..35e6a8c4 100644 --- a/src/core/corenetwork.cpp +++ b/src/core/corenetwork.cpp @@ -29,7 +29,7 @@ INIT_SYNCABLE_OBJECT(CoreNetwork) CoreNetwork::CoreNetwork(const NetworkId &networkid, CoreSession *session) - : Network(networkid, session), + : Network(networkid, session), _coreSession(session), _userInputHandler(new CoreUserInputHandler(this)), _autoReconnectCount(0), @@ -40,788 +40,901 @@ CoreNetwork::CoreNetwork(const NetworkId &networkid, CoreSession *session) _lastPingTime(0), _pingCount(0), - _requestedUserModes('-') -{ - _autoReconnectTimer.setSingleShot(true); - _socketCloseTimer.setSingleShot(true); - connect(&_socketCloseTimer, SIGNAL(timeout()), this, SLOT(socketCloseTimeout())); - - setPingInterval(networkConfig()->pingInterval()); - connect(&_pingTimer, SIGNAL(timeout()), this, SLOT(sendPing())); - - setAutoWhoDelay(networkConfig()->autoWhoDelay()); - setAutoWhoInterval(networkConfig()->autoWhoInterval()); - - QHash channels = coreSession()->persistentChannels(networkId()); - foreach(QString chan, channels.keys()) { - _channelKeys[chan.toLower()] = channels[chan]; - } - - connect(networkConfig(), SIGNAL(pingTimeoutEnabledSet(bool)), SLOT(enablePingTimeout(bool))); - connect(networkConfig(), SIGNAL(pingIntervalSet(int)), SLOT(setPingInterval(int))); - connect(networkConfig(), SIGNAL(autoWhoEnabledSet(bool)), SLOT(setAutoWhoEnabled(bool))); - connect(networkConfig(), SIGNAL(autoWhoIntervalSet(int)), SLOT(setAutoWhoInterval(int))); - connect(networkConfig(), SIGNAL(autoWhoDelaySet(int)), SLOT(setAutoWhoDelay(int))); - - connect(&_autoReconnectTimer, SIGNAL(timeout()), this, SLOT(doAutoReconnect())); - connect(&_autoWhoTimer, SIGNAL(timeout()), this, SLOT(sendAutoWho())); - connect(&_autoWhoCycleTimer, SIGNAL(timeout()), this, SLOT(startAutoWhoCycle())); - connect(&_tokenBucketTimer, SIGNAL(timeout()), this, SLOT(fillBucketAndProcessQueue())); - - connect(&socket, SIGNAL(connected()), this, SLOT(socketInitialized())); - connect(&socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected())); - connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError))); - connect(&socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(socketStateChanged(QAbstractSocket::SocketState))); - connect(&socket, SIGNAL(readyRead()), this, SLOT(socketHasData())); + _requestedUserModes('-') +{ + _autoReconnectTimer.setSingleShot(true); + _socketCloseTimer.setSingleShot(true); + connect(&_socketCloseTimer, SIGNAL(timeout()), this, SLOT(socketCloseTimeout())); + + setPingInterval(networkConfig()->pingInterval()); + connect(&_pingTimer, SIGNAL(timeout()), this, SLOT(sendPing())); + + setAutoWhoDelay(networkConfig()->autoWhoDelay()); + setAutoWhoInterval(networkConfig()->autoWhoInterval()); + + QHash channels = coreSession()->persistentChannels(networkId()); + foreach(QString chan, channels.keys()) { + _channelKeys[chan.toLower()] = channels[chan]; + } + + connect(networkConfig(), SIGNAL(pingTimeoutEnabledSet(bool)), SLOT(enablePingTimeout(bool))); + connect(networkConfig(), SIGNAL(pingIntervalSet(int)), SLOT(setPingInterval(int))); + connect(networkConfig(), SIGNAL(autoWhoEnabledSet(bool)), SLOT(setAutoWhoEnabled(bool))); + connect(networkConfig(), SIGNAL(autoWhoIntervalSet(int)), SLOT(setAutoWhoInterval(int))); + connect(networkConfig(), SIGNAL(autoWhoDelaySet(int)), SLOT(setAutoWhoDelay(int))); + + connect(&_autoReconnectTimer, SIGNAL(timeout()), this, SLOT(doAutoReconnect())); + connect(&_autoWhoTimer, SIGNAL(timeout()), this, SLOT(sendAutoWho())); + connect(&_autoWhoCycleTimer, SIGNAL(timeout()), this, SLOT(startAutoWhoCycle())); + connect(&_tokenBucketTimer, SIGNAL(timeout()), this, SLOT(fillBucketAndProcessQueue())); + + connect(&socket, SIGNAL(connected()), this, SLOT(socketInitialized())); + connect(&socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected())); + connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError))); + connect(&socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(socketStateChanged(QAbstractSocket::SocketState))); + connect(&socket, SIGNAL(readyRead()), this, SLOT(socketHasData())); #ifdef HAVE_SSL - connect(&socket, SIGNAL(encrypted()), this, SLOT(socketInitialized())); - connect(&socket, SIGNAL(sslErrors(const QList &)), this, SLOT(sslErrors(const QList &))); + connect(&socket, SIGNAL(encrypted()), this, SLOT(socketInitialized())); + connect(&socket, SIGNAL(sslErrors(const QList &)), this, SLOT(sslErrors(const QList &))); #endif - connect(this, SIGNAL(newEvent(Event *)), coreSession()->eventManager(), SLOT(postEvent(Event *))); + connect(this, SIGNAL(newEvent(Event *)), coreSession()->eventManager(), SLOT(postEvent(Event *))); - if(Quassel::isOptionSet("oidentd")) { - connect(this, SIGNAL(socketInitialized(const CoreIdentity*,QHostAddress,quint16,QHostAddress,quint16)), Core::instance()->oidentdConfigGenerator(), SLOT(addSocket(const CoreIdentity*,QHostAddress,quint16,QHostAddress,quint16)), Qt::BlockingQueuedConnection); - connect(this, SIGNAL(socketDisconnected(const CoreIdentity*,QHostAddress,quint16,QHostAddress,quint16)), Core::instance()->oidentdConfigGenerator(), SLOT(removeSocket(const CoreIdentity*,QHostAddress,quint16,QHostAddress,quint16))); - } + if (Quassel::isOptionSet("oidentd")) { + connect(this, SIGNAL(socketInitialized(const CoreIdentity*, QHostAddress, quint16, QHostAddress, quint16)), Core::instance()->oidentdConfigGenerator(), SLOT(addSocket(const CoreIdentity*, QHostAddress, quint16, QHostAddress, quint16)), Qt::BlockingQueuedConnection); + connect(this, SIGNAL(socketDisconnected(const CoreIdentity*, QHostAddress, quint16, QHostAddress, quint16)), Core::instance()->oidentdConfigGenerator(), SLOT(removeSocket(const CoreIdentity*, QHostAddress, quint16, QHostAddress, quint16))); + } } -CoreNetwork::~CoreNetwork() { - if(connectionState() != Disconnected && connectionState() != Network::Reconnecting) - disconnectFromIrc(false); // clean up, but this does not count as requested disconnect! - disconnect(&socket, 0, this, 0); // this keeps the socket from triggering events during clean up - delete _userInputHandler; + +CoreNetwork::~CoreNetwork() +{ + if (connectionState() != Disconnected && connectionState() != Network::Reconnecting) + disconnectFromIrc(false); // clean up, but this does not count as requested disconnect! + disconnect(&socket, 0, this, 0); // this keeps the socket from triggering events during clean up + delete _userInputHandler; } -QString CoreNetwork::channelDecode(const QString &bufferName, const QByteArray &string) const { - if(!bufferName.isEmpty()) { - IrcChannel *channel = ircChannel(bufferName); - if(channel) - return channel->decodeString(string); - } - return decodeString(string); + +QString CoreNetwork::channelDecode(const QString &bufferName, const QByteArray &string) const +{ + if (!bufferName.isEmpty()) { + IrcChannel *channel = ircChannel(bufferName); + if (channel) + return channel->decodeString(string); + } + return decodeString(string); } -QString CoreNetwork::userDecode(const QString &userNick, const QByteArray &string) const { - IrcUser *user = ircUser(userNick); - if(user) - return user->decodeString(string); - return decodeString(string); + +QString CoreNetwork::userDecode(const QString &userNick, const QByteArray &string) const +{ + IrcUser *user = ircUser(userNick); + if (user) + return user->decodeString(string); + return decodeString(string); } -QByteArray CoreNetwork::channelEncode(const QString &bufferName, const QString &string) const { - if(!bufferName.isEmpty()) { - IrcChannel *channel = ircChannel(bufferName); - if(channel) - return channel->encodeString(string); - } - return encodeString(string); + +QByteArray CoreNetwork::channelEncode(const QString &bufferName, const QString &string) const +{ + if (!bufferName.isEmpty()) { + IrcChannel *channel = ircChannel(bufferName); + if (channel) + return channel->encodeString(string); + } + return encodeString(string); } -QByteArray CoreNetwork::userEncode(const QString &userNick, const QString &string) const { - IrcUser *user = ircUser(userNick); - if(user) - return user->encodeString(string); - return encodeString(string); + +QByteArray CoreNetwork::userEncode(const QString &userNick, const QString &string) const +{ + IrcUser *user = ircUser(userNick); + if (user) + return user->encodeString(string); + return encodeString(string); } -void CoreNetwork::connectToIrc(bool reconnecting) { - if(!reconnecting && useAutoReconnect() && _autoReconnectCount == 0) { - _autoReconnectTimer.setInterval(autoReconnectInterval() * 1000); - if(unlimitedReconnectRetries()) - _autoReconnectCount = -1; - else - _autoReconnectCount = autoReconnectRetries(); - } - if(serverList().isEmpty()) { - qWarning() << "Server list empty, ignoring connect request!"; - return; - } - CoreIdentity *identity = identityPtr(); - if(!identity) { - qWarning() << "Invalid identity configures, ignoring connect request!"; - return; - } - - // cleaning up old quit reason - _quitReason.clear(); - - // use a random server? - if(useRandomServer()) { - _lastUsedServerIndex = qrand() % serverList().size(); - } else if(_previousConnectionAttemptFailed) { - // cycle to next server if previous connection attempt failed - displayMsg(Message::Server, BufferInfo::StatusBuffer, "", tr("Connection failed. Cycling to next Server")); - if(++_lastUsedServerIndex >= serverList().size()) { - _lastUsedServerIndex = 0; - } - } - _previousConnectionAttemptFailed = false; - - Server server = usedServer(); - displayStatusMsg(tr("Connecting to %1:%2...").arg(server.host).arg(server.port)); - displayMsg(Message::Server, BufferInfo::StatusBuffer, "", tr("Connecting to %1:%2...").arg(server.host).arg(server.port)); - - if(server.useProxy) { - QNetworkProxy proxy((QNetworkProxy::ProxyType)server.proxyType, server.proxyHost, server.proxyPort, server.proxyUser, server.proxyPass); - socket.setProxy(proxy); - } else { - socket.setProxy(QNetworkProxy::NoProxy); - } -#ifdef HAVE_SSL - socket.setProtocol((QSsl::SslProtocol)server.sslVersion); - if(server.useSsl) { +void CoreNetwork::connectToIrc(bool reconnecting) +{ + if (!reconnecting && useAutoReconnect() && _autoReconnectCount == 0) { + _autoReconnectTimer.setInterval(autoReconnectInterval() * 1000); + if (unlimitedReconnectRetries()) + _autoReconnectCount = -1; + else + _autoReconnectCount = autoReconnectRetries(); + } + if (serverList().isEmpty()) { + qWarning() << "Server list empty, ignoring connect request!"; + return; + } CoreIdentity *identity = identityPtr(); - if(identity) { - socket.setLocalCertificate(identity->sslCert()); - socket.setPrivateKey(identity->sslKey()); + if (!identity) { + qWarning() << "Invalid identity configures, ignoring connect request!"; + return; + } + + // cleaning up old quit reason + _quitReason.clear(); + + // use a random server? + if (useRandomServer()) { + _lastUsedServerIndex = qrand() % serverList().size(); + } + else if (_previousConnectionAttemptFailed) { + // cycle to next server if previous connection attempt failed + displayMsg(Message::Server, BufferInfo::StatusBuffer, "", tr("Connection failed. Cycling to next Server")); + if (++_lastUsedServerIndex >= serverList().size()) { + _lastUsedServerIndex = 0; + } + } + _previousConnectionAttemptFailed = false; + + Server server = usedServer(); + displayStatusMsg(tr("Connecting to %1:%2...").arg(server.host).arg(server.port)); + displayMsg(Message::Server, BufferInfo::StatusBuffer, "", tr("Connecting to %1:%2...").arg(server.host).arg(server.port)); + + if (server.useProxy) { + QNetworkProxy proxy((QNetworkProxy::ProxyType)server.proxyType, server.proxyHost, server.proxyPort, server.proxyUser, server.proxyPass); + socket.setProxy(proxy); + } + else { + socket.setProxy(QNetworkProxy::NoProxy); + } + +#ifdef HAVE_SSL + socket.setProtocol((QSsl::SslProtocol)server.sslVersion); + if (server.useSsl) { + CoreIdentity *identity = identityPtr(); + if (identity) { + socket.setLocalCertificate(identity->sslCert()); + socket.setPrivateKey(identity->sslKey()); + } + socket.connectToHostEncrypted(server.host, server.port); + } + else { + socket.connectToHost(server.host, server.port); } - socket.connectToHostEncrypted(server.host, server.port); - } else { - socket.connectToHost(server.host, server.port); - } #else - socket.connectToHost(server.host, server.port); + socket.connectToHost(server.host, server.port); #endif } -void CoreNetwork::disconnectFromIrc(bool requested, const QString &reason, bool withReconnect) { - _quitRequested = requested; // see socketDisconnected(); - if(!withReconnect) { - _autoReconnectTimer.stop(); - _autoReconnectCount = 0; // prohibiting auto reconnect - } - disablePingTimeout(); - _msgQueue.clear(); - IrcUser *me_ = me(); - if(me_) { - QString awayMsg; - if(me_->isAway()) - awayMsg = me_->awayMessage(); - Core::setAwayMessage(userId(), networkId(), awayMsg); - } +void CoreNetwork::disconnectFromIrc(bool requested, const QString &reason, bool withReconnect) +{ + _quitRequested = requested; // see socketDisconnected(); + if (!withReconnect) { + _autoReconnectTimer.stop(); + _autoReconnectCount = 0; // prohibiting auto reconnect + } + disablePingTimeout(); + _msgQueue.clear(); + + IrcUser *me_ = me(); + if (me_) { + QString awayMsg; + if (me_->isAway()) + awayMsg = me_->awayMessage(); + Core::setAwayMessage(userId(), networkId(), awayMsg); + } - if(reason.isEmpty() && identityPtr()) - _quitReason = identityPtr()->quitReason(); - else - _quitReason = reason; + if (reason.isEmpty() && identityPtr()) + _quitReason = identityPtr()->quitReason(); + else + _quitReason = reason; - displayMsg(Message::Server, BufferInfo::StatusBuffer, "", tr("Disconnecting. (%1)").arg((!requested && !withReconnect) ? tr("Core Shutdown") : _quitReason)); - switch(socket.state()) { - case QAbstractSocket::ConnectedState: - userInputHandler()->issueQuit(_quitReason); - if(requested || withReconnect) { - // the irc server has 10 seconds to close the socket - _socketCloseTimer.start(10000); - break; + displayMsg(Message::Server, BufferInfo::StatusBuffer, "", tr("Disconnecting. (%1)").arg((!requested && !withReconnect) ? tr("Core Shutdown") : _quitReason)); + switch (socket.state()) { + case QAbstractSocket::ConnectedState: + userInputHandler()->issueQuit(_quitReason); + if (requested || withReconnect) { + // the irc server has 10 seconds to close the socket + _socketCloseTimer.start(10000); + break; + } + default: + socket.close(); + socketDisconnected(); } - default: - socket.close(); - socketDisconnected(); - } } -void CoreNetwork::userInput(BufferInfo buf, QString msg) { - userInputHandler()->handleUserInput(buf, msg); + +void CoreNetwork::userInput(BufferInfo buf, QString msg) +{ + userInputHandler()->handleUserInput(buf, msg); } -void CoreNetwork::putRawLine(QByteArray s) { - if(_tokenBucket > 0) - writeToSocket(s); - else - _msgQueue.append(s); + +void CoreNetwork::putRawLine(QByteArray s) +{ + if (_tokenBucket > 0) + writeToSocket(s); + else + _msgQueue.append(s); } -void CoreNetwork::putCmd(const QString &cmd, const QList ¶ms, const QByteArray &prefix) { - QByteArray msg; - if(!prefix.isEmpty()) - msg += ":" + prefix + " "; - msg += cmd.toUpper().toAscii(); +void CoreNetwork::putCmd(const QString &cmd, const QList ¶ms, const QByteArray &prefix) +{ + QByteArray msg; + + if (!prefix.isEmpty()) + msg += ":" + prefix + " "; + msg += cmd.toUpper().toAscii(); - for(int i = 0; i < params.size() - 1; i++) { - msg += " " + params[i]; - } - if(!params.isEmpty()) - msg += " :" + params.last(); + for (int i = 0; i < params.size() - 1; i++) { + msg += " " + params[i]; + } + if (!params.isEmpty()) + msg += " :" + params.last(); - putRawLine(msg); + putRawLine(msg); } -void CoreNetwork::setChannelJoined(const QString &channel) { - _autoWhoQueue.prepend(channel.toLower()); // prepend so this new chan is the first to be checked - Core::setChannelPersistent(userId(), networkId(), channel, true); - Core::setPersistentChannelKey(userId(), networkId(), channel, _channelKeys[channel.toLower()]); +void CoreNetwork::setChannelJoined(const QString &channel) +{ + _autoWhoQueue.prepend(channel.toLower()); // prepend so this new chan is the first to be checked + + Core::setChannelPersistent(userId(), networkId(), channel, true); + Core::setPersistentChannelKey(userId(), networkId(), channel, _channelKeys[channel.toLower()]); } -void CoreNetwork::setChannelParted(const QString &channel) { - removeChannelKey(channel); - _autoWhoQueue.removeAll(channel.toLower()); - _autoWhoPending.remove(channel.toLower()); - Core::setChannelPersistent(userId(), networkId(), channel, false); +void CoreNetwork::setChannelParted(const QString &channel) +{ + removeChannelKey(channel); + _autoWhoQueue.removeAll(channel.toLower()); + _autoWhoPending.remove(channel.toLower()); + + Core::setChannelPersistent(userId(), networkId(), channel, false); } -void CoreNetwork::addChannelKey(const QString &channel, const QString &key) { - if(key.isEmpty()) { - removeChannelKey(channel); - } else { - _channelKeys[channel.toLower()] = key; - } + +void CoreNetwork::addChannelKey(const QString &channel, const QString &key) +{ + if (key.isEmpty()) { + removeChannelKey(channel); + } + else { + _channelKeys[channel.toLower()] = key; + } } -void CoreNetwork::removeChannelKey(const QString &channel) { - _channelKeys.remove(channel.toLower()); + +void CoreNetwork::removeChannelKey(const QString &channel) +{ + _channelKeys.remove(channel.toLower()); } + #ifdef HAVE_QCA2 -Cipher *CoreNetwork::cipher(const QString &target) const { - if(target.isEmpty()) - return 0; +Cipher *CoreNetwork::cipher(const QString &target) const +{ + if (target.isEmpty()) + return 0; - if(!Cipher::neededFeaturesAvailable()) - return 0; + if (!Cipher::neededFeaturesAvailable()) + return 0; - QByteArray key = cipherKey(target); - if(key.isEmpty()) - return 0; + QByteArray key = cipherKey(target); + if (key.isEmpty()) + return 0; - CoreIrcChannel *channel = qobject_cast(ircChannel(target)); - if(channel) { - if(channel->cipher()->setKey(key)) - return channel->cipher(); - } else { - CoreIrcUser *user = qobject_cast(ircUser(target)); - if(user && user->cipher()->setKey(key)) - return user->cipher(); - } - return 0; + CoreIrcChannel *channel = qobject_cast(ircChannel(target)); + if (channel) { + if (channel->cipher()->setKey(key)) + return channel->cipher(); + } + else { + CoreIrcUser *user = qobject_cast(ircUser(target)); + if (user && user->cipher()->setKey(key)) + return user->cipher(); + } + return 0; } -QByteArray CoreNetwork::cipherKey(const QString &recipient) const { - return _cipherKeys.value(recipient.toLower(), QByteArray()); + +QByteArray CoreNetwork::cipherKey(const QString &recipient) const +{ + return _cipherKeys.value(recipient.toLower(), QByteArray()); } -void CoreNetwork::setCipherKey(const QString &recipient, const QByteArray &key) { - if(!key.isEmpty()) - _cipherKeys[recipient.toLower()] = key; - else - _cipherKeys.remove(recipient.toLower()); + +void CoreNetwork::setCipherKey(const QString &recipient, const QByteArray &key) +{ + if (!key.isEmpty()) + _cipherKeys[recipient.toLower()] = key; + else + _cipherKeys.remove(recipient.toLower()); } + + #endif /* HAVE_QCA2 */ -bool CoreNetwork::setAutoWhoDone(const QString &channel) { - QString chan = channel.toLower(); - if(_autoWhoPending.value(chan, 0) <= 0) - return false; - if(--_autoWhoPending[chan] <= 0) - _autoWhoPending.remove(chan); - return true; +bool CoreNetwork::setAutoWhoDone(const QString &channel) +{ + QString chan = channel.toLower(); + if (_autoWhoPending.value(chan, 0) <= 0) + return false; + if (--_autoWhoPending[chan] <= 0) + _autoWhoPending.remove(chan); + return true; } -void CoreNetwork::setMyNick(const QString &mynick) { - Network::setMyNick(mynick); - if(connectionState() == Network::Initializing) - networkInitialized(); + +void CoreNetwork::setMyNick(const QString &mynick) +{ + Network::setMyNick(mynick); + if (connectionState() == Network::Initializing) + networkInitialized(); } -void CoreNetwork::socketHasData() { - while(socket.canReadLine()) { - QByteArray s = socket.readLine().trimmed(); - NetworkDataEvent *event = new NetworkDataEvent(EventManager::NetworkIncoming, this, s); + +void CoreNetwork::socketHasData() +{ + while (socket.canReadLine()) { + QByteArray s = socket.readLine().trimmed(); + NetworkDataEvent *event = new NetworkDataEvent(EventManager::NetworkIncoming, this, s); #if QT_VERSION >= 0x040700 - event->setTimestamp(QDateTime::currentDateTimeUtc()); + event->setTimestamp(QDateTime::currentDateTimeUtc()); #else - event->setTimestamp(QDateTime::currentDateTime().toUTC()); + event->setTimestamp(QDateTime::currentDateTime().toUTC()); #endif - emit newEvent(event); - } + emit newEvent(event); + } } -void CoreNetwork::socketError(QAbstractSocket::SocketError error) { - if(_quitRequested && error == QAbstractSocket::RemoteHostClosedError) - return; - _previousConnectionAttemptFailed = true; - qWarning() << qPrintable(tr("Could not connect to %1 (%2)").arg(networkName(), socket.errorString())); - emit connectionError(socket.errorString()); - displayMsg(Message::Error, BufferInfo::StatusBuffer, "", tr("Connection failure: %1").arg(socket.errorString())); - emitConnectionError(socket.errorString()); - if(socket.state() < QAbstractSocket::ConnectedState) { - socketDisconnected(); - } +void CoreNetwork::socketError(QAbstractSocket::SocketError error) +{ + if (_quitRequested && error == QAbstractSocket::RemoteHostClosedError) + return; + + _previousConnectionAttemptFailed = true; + qWarning() << qPrintable(tr("Could not connect to %1 (%2)").arg(networkName(), socket.errorString())); + emit connectionError(socket.errorString()); + displayMsg(Message::Error, BufferInfo::StatusBuffer, "", tr("Connection failure: %1").arg(socket.errorString())); + emitConnectionError(socket.errorString()); + if (socket.state() < QAbstractSocket::ConnectedState) { + socketDisconnected(); + } } -void CoreNetwork::socketInitialized() { - Server server = usedServer(); + +void CoreNetwork::socketInitialized() +{ + Server server = usedServer(); #ifdef HAVE_SSL - if(server.useSsl && !socket.isEncrypted()) - return; + if (server.useSsl && !socket.isEncrypted()) + return; #endif - CoreIdentity *identity = identityPtr(); - if(!identity) { - qCritical() << "Identity invalid!"; - disconnectFromIrc(); - return; - } - - emit socketInitialized(identity, localAddress(), localPort(), peerAddress(), peerPort()); - - // TokenBucket to avoid sending too much at once - _messageDelay = 2200; // this seems to be a safe value (2.2 seconds delay) - _burstSize = 5; - _tokenBucket = _burstSize; // init with a full bucket - _tokenBucketTimer.start(_messageDelay); - - if(networkInfo().useSasl) { - putRawLine(serverEncode(QString("CAP REQ :sasl"))); - } - if(!server.password.isEmpty()) { - putRawLine(serverEncode(QString("PASS %1").arg(server.password))); - } - QString nick; - if(identity->nicks().isEmpty()) { - nick = "quassel"; - qWarning() << "CoreNetwork::socketInitialized(): no nicks supplied for identity Id" << identity->id(); - } else { - nick = identity->nicks()[0]; - } - putRawLine(serverEncode(QString("NICK :%1").arg(nick))); - putRawLine(serverEncode(QString("USER %1 8 * :%2").arg(identity->ident(), identity->realName()))); -} - -void CoreNetwork::socketDisconnected() { - disablePingTimeout(); - _msgQueue.clear(); - - _autoWhoCycleTimer.stop(); - _autoWhoTimer.stop(); - _autoWhoQueue.clear(); - _autoWhoPending.clear(); - - _socketCloseTimer.stop(); - - _tokenBucketTimer.stop(); - - IrcUser *me_ = me(); - if(me_) { - foreach(QString channel, me_->channels()) - displayMsg(Message::Quit, BufferInfo::ChannelBuffer, channel, _quitReason, me_->hostmask()); - } - - setConnected(false); - emit disconnected(networkId()); - emit socketDisconnected(identityPtr(), localAddress(), localPort(), peerAddress(), peerPort()); - if(_quitRequested) { - _quitRequested = false; - setConnectionState(Network::Disconnected); - Core::setNetworkConnected(userId(), networkId(), false); - } else if(_autoReconnectCount != 0) { - setConnectionState(Network::Reconnecting); - if(_autoReconnectCount == -1 || _autoReconnectCount == autoReconnectRetries()) - doAutoReconnect(); // first try is immediate - else - _autoReconnectTimer.start(); - } + CoreIdentity *identity = identityPtr(); + if (!identity) { + qCritical() << "Identity invalid!"; + disconnectFromIrc(); + return; + } + + emit socketInitialized(identity, localAddress(), localPort(), peerAddress(), peerPort()); + + // TokenBucket to avoid sending too much at once + _messageDelay = 2200; // this seems to be a safe value (2.2 seconds delay) + _burstSize = 5; + _tokenBucket = _burstSize; // init with a full bucket + _tokenBucketTimer.start(_messageDelay); + + if (networkInfo().useSasl) { + putRawLine(serverEncode(QString("CAP REQ :sasl"))); + } + if (!server.password.isEmpty()) { + putRawLine(serverEncode(QString("PASS %1").arg(server.password))); + } + QString nick; + if (identity->nicks().isEmpty()) { + nick = "quassel"; + qWarning() << "CoreNetwork::socketInitialized(): no nicks supplied for identity Id" << identity->id(); + } + else { + nick = identity->nicks()[0]; + } + putRawLine(serverEncode(QString("NICK :%1").arg(nick))); + putRawLine(serverEncode(QString("USER %1 8 * :%2").arg(identity->ident(), identity->realName()))); } -void CoreNetwork::socketStateChanged(QAbstractSocket::SocketState socketState) { - Network::ConnectionState state; - switch(socketState) { + +void CoreNetwork::socketDisconnected() +{ + disablePingTimeout(); + _msgQueue.clear(); + + _autoWhoCycleTimer.stop(); + _autoWhoTimer.stop(); + _autoWhoQueue.clear(); + _autoWhoPending.clear(); + + _socketCloseTimer.stop(); + + _tokenBucketTimer.stop(); + + IrcUser *me_ = me(); + if (me_) { + foreach(QString channel, me_->channels()) + displayMsg(Message::Quit, BufferInfo::ChannelBuffer, channel, _quitReason, me_->hostmask()); + } + + setConnected(false); + emit disconnected(networkId()); + emit socketDisconnected(identityPtr(), localAddress(), localPort(), peerAddress(), peerPort()); + if (_quitRequested) { + _quitRequested = false; + setConnectionState(Network::Disconnected); + Core::setNetworkConnected(userId(), networkId(), false); + } + else if (_autoReconnectCount != 0) { + setConnectionState(Network::Reconnecting); + if (_autoReconnectCount == -1 || _autoReconnectCount == autoReconnectRetries()) + doAutoReconnect(); // first try is immediate + else + _autoReconnectTimer.start(); + } +} + + +void CoreNetwork::socketStateChanged(QAbstractSocket::SocketState socketState) +{ + Network::ConnectionState state; + switch (socketState) { case QAbstractSocket::UnconnectedState: - state = Network::Disconnected; - break; + state = Network::Disconnected; + break; case QAbstractSocket::HostLookupState: case QAbstractSocket::ConnectingState: - state = Network::Connecting; - break; + state = Network::Connecting; + break; case QAbstractSocket::ConnectedState: - state = Network::Initializing; - break; + state = Network::Initializing; + break; case QAbstractSocket::ClosingState: - state = Network::Disconnecting; - break; + state = Network::Disconnecting; + break; default: - state = Network::Disconnected; - } - setConnectionState(state); -} - -void CoreNetwork::networkInitialized() { - setConnectionState(Network::Initialized); - setConnected(true); - _quitRequested = false; - - if(useAutoReconnect()) { - // reset counter - _autoReconnectCount = unlimitedReconnectRetries() ? -1 : autoReconnectRetries(); - } + state = Network::Disconnected; + } + setConnectionState(state); +} - // restore away state - QString awayMsg = Core::awayMessage(userId(), networkId()); - if(!awayMsg.isEmpty()) - userInputHandler()->handleAway(BufferInfo(), Core::awayMessage(userId(), networkId())); - - sendPerform(); - - enablePingTimeout(); - - if(networkConfig()->autoWhoEnabled()) { - _autoWhoCycleTimer.start(); - _autoWhoTimer.start(); - startAutoWhoCycle(); // FIXME wait for autojoin to be completed - } - - Core::bufferInfo(userId(), networkId(), BufferInfo::StatusBuffer); // create status buffer - Core::setNetworkConnected(userId(), networkId(), true); -} -void CoreNetwork::sendPerform() { - BufferInfo statusBuf = BufferInfo::fakeStatusBuffer(networkId()); +void CoreNetwork::networkInitialized() +{ + setConnectionState(Network::Initialized); + setConnected(true); + _quitRequested = false; - // do auto identify - if(useAutoIdentify() && !autoIdentifyService().isEmpty() && !autoIdentifyPassword().isEmpty()) { - userInputHandler()->handleMsg(statusBuf, QString("%1 IDENTIFY %2").arg(autoIdentifyService(), autoIdentifyPassword())); - } + if (useAutoReconnect()) { + // reset counter + _autoReconnectCount = unlimitedReconnectRetries() ? -1 : autoReconnectRetries(); + } - // restore old user modes if server default mode is set. - IrcUser *me_ = me(); - if(me_) { - if(!me_->userModes().isEmpty()) { - restoreUserModes(); - } else { - connect(me_, SIGNAL(userModesSet(QString)), this, SLOT(restoreUserModes())); - connect(me_, SIGNAL(userModesAdded(QString)), this, SLOT(restoreUserModes())); + // restore away state + QString awayMsg = Core::awayMessage(userId(), networkId()); + if (!awayMsg.isEmpty()) + userInputHandler()->handleAway(BufferInfo(), Core::awayMessage(userId(), networkId())); + + sendPerform(); + + enablePingTimeout(); + + if (networkConfig()->autoWhoEnabled()) { + _autoWhoCycleTimer.start(); + _autoWhoTimer.start(); + startAutoWhoCycle(); // FIXME wait for autojoin to be completed } - } - // send perform list - foreach(QString line, perform()) { - if(!line.isEmpty()) userInput(statusBuf, line); - } + Core::bufferInfo(userId(), networkId(), BufferInfo::StatusBuffer); // create status buffer + Core::setNetworkConnected(userId(), networkId(), true); +} + + +void CoreNetwork::sendPerform() +{ + BufferInfo statusBuf = BufferInfo::fakeStatusBuffer(networkId()); + + // do auto identify + if (useAutoIdentify() && !autoIdentifyService().isEmpty() && !autoIdentifyPassword().isEmpty()) { + userInputHandler()->handleMsg(statusBuf, QString("%1 IDENTIFY %2").arg(autoIdentifyService(), autoIdentifyPassword())); + } + + // restore old user modes if server default mode is set. + IrcUser *me_ = me(); + if (me_) { + if (!me_->userModes().isEmpty()) { + restoreUserModes(); + } + else { + connect(me_, SIGNAL(userModesSet(QString)), this, SLOT(restoreUserModes())); + connect(me_, SIGNAL(userModesAdded(QString)), this, SLOT(restoreUserModes())); + } + } + + // send perform list + foreach(QString line, perform()) { + if (!line.isEmpty()) userInput(statusBuf, line); + } - // rejoin channels we've been in - if(rejoinChannels()) { - QStringList channels, keys; - foreach(QString chan, coreSession()->persistentChannels(networkId()).keys()) { - QString key = channelKey(chan); - if(!key.isEmpty()) { - channels.prepend(chan); - keys.prepend(key); - } else { - channels.append(chan); - } + // rejoin channels we've been in + if (rejoinChannels()) { + QStringList channels, keys; + foreach(QString chan, coreSession()->persistentChannels(networkId()).keys()) { + QString key = channelKey(chan); + if (!key.isEmpty()) { + channels.prepend(chan); + keys.prepend(key); + } + else { + channels.append(chan); + } + } + QString joinString = QString("%1 %2").arg(channels.join(",")).arg(keys.join(",")).trimmed(); + if (!joinString.isEmpty()) + userInputHandler()->handleJoin(statusBuf, joinString); } - QString joinString = QString("%1 %2").arg(channels.join(",")).arg(keys.join(",")).trimmed(); - if(!joinString.isEmpty()) - userInputHandler()->handleJoin(statusBuf, joinString); - } } -void CoreNetwork::restoreUserModes() { - IrcUser *me_ = me(); - Q_ASSERT(me_); - disconnect(me_, SIGNAL(userModesSet(QString)), this, SLOT(restoreUserModes())); - disconnect(me_, SIGNAL(userModesAdded(QString)), this, SLOT(restoreUserModes())); +void CoreNetwork::restoreUserModes() +{ + IrcUser *me_ = me(); + Q_ASSERT(me_); - QString modesDelta = Core::userModes(userId(), networkId()); - QString currentModes = me_->userModes(); + disconnect(me_, SIGNAL(userModesSet(QString)), this, SLOT(restoreUserModes())); + disconnect(me_, SIGNAL(userModesAdded(QString)), this, SLOT(restoreUserModes())); - QString addModes, removeModes; - if(modesDelta.contains('-')) { - addModes = modesDelta.section('-', 0, 0); - removeModes = modesDelta.section('-', 1); - } else { - addModes = modesDelta; - } + QString modesDelta = Core::userModes(userId(), networkId()); + QString currentModes = me_->userModes(); + QString addModes, removeModes; + if (modesDelta.contains('-')) { + addModes = modesDelta.section('-', 0, 0); + removeModes = modesDelta.section('-', 1); + } + else { + addModes = modesDelta; + } - addModes.remove(QRegExp(QString("[%1]").arg(currentModes))); - if(currentModes.isEmpty()) - removeModes = QString(); - else - removeModes.remove(QRegExp(QString("[^%1]").arg(currentModes))); + addModes.remove(QRegExp(QString("[%1]").arg(currentModes))); + if (currentModes.isEmpty()) + removeModes = QString(); + else + removeModes.remove(QRegExp(QString("[^%1]").arg(currentModes))); - if(addModes.isEmpty() && removeModes.isEmpty()) - return; + if (addModes.isEmpty() && removeModes.isEmpty()) + return; - if(!addModes.isEmpty()) - addModes = '+' + addModes; - if(!removeModes.isEmpty()) - removeModes = '-' + removeModes; + if (!addModes.isEmpty()) + addModes = '+' + addModes; + if (!removeModes.isEmpty()) + removeModes = '-' + removeModes; - // don't use InputHandler::handleMode() as it keeps track of our persistent mode changes - putRawLine(serverEncode(QString("MODE %1 %2%3").arg(me_->nick()).arg(addModes).arg(removeModes))); + // don't use InputHandler::handleMode() as it keeps track of our persistent mode changes + putRawLine(serverEncode(QString("MODE %1 %2%3").arg(me_->nick()).arg(addModes).arg(removeModes))); } -void CoreNetwork::updateIssuedModes(const QString &requestedModes) { - QString addModes; - QString removeModes; - bool addMode = true; - for(int i = 0; i < requestedModes.length(); i++) { - if(requestedModes[i] == '+') { - addMode = true; - continue; +void CoreNetwork::updateIssuedModes(const QString &requestedModes) +{ + QString addModes; + QString removeModes; + bool addMode = true; + + for (int i = 0; i < requestedModes.length(); i++) { + if (requestedModes[i] == '+') { + addMode = true; + continue; + } + if (requestedModes[i] == '-') { + addMode = false; + continue; + } + if (addMode) { + addModes += requestedModes[i]; + } + else { + removeModes += requestedModes[i]; + } } - if(requestedModes[i] == '-') { - addMode = false; - continue; + + QString addModesOld = _requestedUserModes.section('-', 0, 0); + QString removeModesOld = _requestedUserModes.section('-', 1); + + addModes.remove(QRegExp(QString("[%1]").arg(addModesOld))); // deduplicate + addModesOld.remove(QRegExp(QString("[%1]").arg(removeModes))); // update + addModes += addModesOld; + + removeModes.remove(QRegExp(QString("[%1]").arg(removeModesOld))); // deduplicate + removeModesOld.remove(QRegExp(QString("[%1]").arg(addModes))); // update + removeModes += removeModesOld; + + _requestedUserModes = QString("%1-%2").arg(addModes).arg(removeModes); +} + + +void CoreNetwork::updatePersistentModes(QString addModes, QString removeModes) +{ + QString persistentUserModes = Core::userModes(userId(), networkId()); + + QString requestedAdd = _requestedUserModes.section('-', 0, 0); + QString requestedRemove = _requestedUserModes.section('-', 1); + + QString persistentAdd, persistentRemove; + if (persistentUserModes.contains('-')) { + persistentAdd = persistentUserModes.section('-', 0, 0); + persistentRemove = persistentUserModes.section('-', 1); } - if(addMode) { - addModes += requestedModes[i]; - } else { - removeModes += requestedModes[i]; + else { + persistentAdd = persistentUserModes; } - } + // remove modes we didn't issue + if (requestedAdd.isEmpty()) + addModes = QString(); + else + addModes.remove(QRegExp(QString("[^%1]").arg(requestedAdd))); - QString addModesOld = _requestedUserModes.section('-', 0, 0); - QString removeModesOld = _requestedUserModes.section('-', 1); + if (requestedRemove.isEmpty()) + removeModes = QString(); + else + removeModes.remove(QRegExp(QString("[^%1]").arg(requestedRemove))); - addModes.remove(QRegExp(QString("[%1]").arg(addModesOld))); // deduplicate - addModesOld.remove(QRegExp(QString("[%1]").arg(removeModes))); // update - addModes += addModesOld; + // deduplicate + persistentAdd.remove(QRegExp(QString("[%1]").arg(addModes))); + persistentRemove.remove(QRegExp(QString("[%1]").arg(removeModes))); - removeModes.remove(QRegExp(QString("[%1]").arg(removeModesOld))); // deduplicate - removeModesOld.remove(QRegExp(QString("[%1]").arg(addModes))); // update - removeModes += removeModesOld; + // update + persistentAdd.remove(QRegExp(QString("[%1]").arg(removeModes))); + persistentRemove.remove(QRegExp(QString("[%1]").arg(addModes))); - _requestedUserModes = QString("%1-%2").arg(addModes).arg(removeModes); -} + // update issued mode list + requestedAdd.remove(QRegExp(QString("[%1]").arg(addModes))); + requestedRemove.remove(QRegExp(QString("[%1]").arg(removeModes))); + _requestedUserModes = QString("%1-%2").arg(requestedAdd).arg(requestedRemove); -void CoreNetwork::updatePersistentModes(QString addModes, QString removeModes) { - QString persistentUserModes = Core::userModes(userId(), networkId()); + persistentAdd += addModes; + persistentRemove += removeModes; + Core::setUserModes(userId(), networkId(), QString("%1-%2").arg(persistentAdd).arg(persistentRemove)); +} - QString requestedAdd = _requestedUserModes.section('-', 0, 0); - QString requestedRemove = _requestedUserModes.section('-', 1); - QString persistentAdd, persistentRemove; - if(persistentUserModes.contains('-')) { - persistentAdd = persistentUserModes.section('-', 0, 0); - persistentRemove = persistentUserModes.section('-', 1); - } else { - persistentAdd = persistentUserModes; - } +void CoreNetwork::resetPersistentModes() +{ + _requestedUserModes = QString('-'); + Core::setUserModes(userId(), networkId(), QString()); +} - // remove modes we didn't issue - if(requestedAdd.isEmpty()) - addModes = QString(); - else - addModes.remove(QRegExp(QString("[^%1]").arg(requestedAdd))); - if(requestedRemove.isEmpty()) - removeModes = QString(); - else - removeModes.remove(QRegExp(QString("[^%1]").arg(requestedRemove))); +void CoreNetwork::setUseAutoReconnect(bool use) +{ + Network::setUseAutoReconnect(use); + if (!use) + _autoReconnectTimer.stop(); +} - // deduplicate - persistentAdd.remove(QRegExp(QString("[%1]").arg(addModes))); - persistentRemove.remove(QRegExp(QString("[%1]").arg(removeModes))); - // update - persistentAdd.remove(QRegExp(QString("[%1]").arg(removeModes))); - persistentRemove.remove(QRegExp(QString("[%1]").arg(addModes))); +void CoreNetwork::setAutoReconnectInterval(quint32 interval) +{ + Network::setAutoReconnectInterval(interval); + _autoReconnectTimer.setInterval(interval * 1000); +} - // update issued mode list - requestedAdd.remove(QRegExp(QString("[%1]").arg(addModes))); - requestedRemove.remove(QRegExp(QString("[%1]").arg(removeModes))); - _requestedUserModes = QString("%1-%2").arg(requestedAdd).arg(requestedRemove); - persistentAdd += addModes; - persistentRemove += removeModes; - Core::setUserModes(userId(), networkId(), QString("%1-%2").arg(persistentAdd).arg(persistentRemove)); +void CoreNetwork::setAutoReconnectRetries(quint16 retries) +{ + Network::setAutoReconnectRetries(retries); + if (_autoReconnectCount != 0) { + if (unlimitedReconnectRetries()) + _autoReconnectCount = -1; + else + _autoReconnectCount = autoReconnectRetries(); + } } -void CoreNetwork::resetPersistentModes() { - _requestedUserModes = QString('-'); - Core::setUserModes(userId(), networkId(), QString()); + +void CoreNetwork::doAutoReconnect() +{ + if (connectionState() != Network::Disconnected && connectionState() != Network::Reconnecting) { + qWarning() << "CoreNetwork::doAutoReconnect(): Cannot reconnect while not being disconnected!"; + return; + } + if (_autoReconnectCount > 0 || _autoReconnectCount == -1) + _autoReconnectCount--; // -2 means we delay the next reconnect + connectToIrc(true); } -void CoreNetwork::setUseAutoReconnect(bool use) { - Network::setUseAutoReconnect(use); - if(!use) - _autoReconnectTimer.stop(); + +void CoreNetwork::sendPing() +{ + uint now = QDateTime::currentDateTime().toTime_t(); + if (_pingCount != 0) { + qDebug() << "UserId:" << userId() << "Network:" << networkName() << "missed" << _pingCount << "pings." + << "BA:" << socket.bytesAvailable() << "BTW:" << socket.bytesToWrite(); + } + if ((int)_pingCount >= networkConfig()->maxPingCount() && now - _lastPingTime <= (uint)(_pingTimer.interval() / 1000) + 1) { + // the second check compares the actual elapsed time since the last ping and the pingTimer interval + // if the interval is shorter then the actual elapsed time it means that this thread was somehow blocked + // and unable to even handle a ping answer. So we ignore those misses. + disconnectFromIrc(false, QString("No Ping reply in %1 seconds.").arg(_pingCount * _pingTimer.interval() / 1000), true /* withReconnect */); + } + else { + _lastPingTime = now; + _pingCount++; + userInputHandler()->handlePing(BufferInfo(), QString()); + } } -void CoreNetwork::setAutoReconnectInterval(quint32 interval) { - Network::setAutoReconnectInterval(interval); - _autoReconnectTimer.setInterval(interval * 1000); + +void CoreNetwork::enablePingTimeout(bool enable) +{ + if (!enable) + disablePingTimeout(); + else { + resetPingTimeout(); + if (networkConfig()->pingTimeoutEnabled()) + _pingTimer.start(); + } } -void CoreNetwork::setAutoReconnectRetries(quint16 retries) { - Network::setAutoReconnectRetries(retries); - if(_autoReconnectCount != 0) { - if(unlimitedReconnectRetries()) - _autoReconnectCount = -1; - else - _autoReconnectCount = autoReconnectRetries(); - } -} - -void CoreNetwork::doAutoReconnect() { - if(connectionState() != Network::Disconnected && connectionState() != Network::Reconnecting) { - qWarning() << "CoreNetwork::doAutoReconnect(): Cannot reconnect while not being disconnected!"; - return; - } - if(_autoReconnectCount > 0 || _autoReconnectCount == -1) - _autoReconnectCount--; // -2 means we delay the next reconnect - connectToIrc(true); -} - -void CoreNetwork::sendPing() { - uint now = QDateTime::currentDateTime().toTime_t(); - if(_pingCount != 0) { - qDebug() << "UserId:" << userId() << "Network:" << networkName() << "missed" << _pingCount << "pings." - << "BA:" << socket.bytesAvailable() << "BTW:" << socket.bytesToWrite(); - } - if((int)_pingCount >= networkConfig()->maxPingCount() && now - _lastPingTime <= (uint)(_pingTimer.interval() / 1000) + 1) { - // the second check compares the actual elapsed time since the last ping and the pingTimer interval - // if the interval is shorter then the actual elapsed time it means that this thread was somehow blocked - // and unable to even handle a ping answer. So we ignore those misses. - disconnectFromIrc(false, QString("No Ping reply in %1 seconds.").arg(_pingCount * _pingTimer.interval() / 1000), true /* withReconnect */); - } else { - _lastPingTime = now; - _pingCount++; - userInputHandler()->handlePing(BufferInfo(), QString()); - } -} - -void CoreNetwork::enablePingTimeout(bool enable) { - if(!enable) - disablePingTimeout(); - else { + +void CoreNetwork::disablePingTimeout() +{ + _pingTimer.stop(); resetPingTimeout(); - if(networkConfig()->pingTimeoutEnabled()) - _pingTimer.start(); - } } -void CoreNetwork::disablePingTimeout() { - _pingTimer.stop(); - resetPingTimeout(); -} -void CoreNetwork::setPingInterval(int interval) { - _pingTimer.setInterval(interval * 1000); +void CoreNetwork::setPingInterval(int interval) +{ + _pingTimer.setInterval(interval * 1000); } + /******** AutoWHO ********/ -void CoreNetwork::startAutoWhoCycle() { - if(!_autoWhoQueue.isEmpty()) { - _autoWhoCycleTimer.stop(); - return; - } - _autoWhoQueue = channels(); +void CoreNetwork::startAutoWhoCycle() +{ + if (!_autoWhoQueue.isEmpty()) { + _autoWhoCycleTimer.stop(); + return; + } + _autoWhoQueue = channels(); } -void CoreNetwork::setAutoWhoDelay(int delay) { - _autoWhoTimer.setInterval(delay * 1000); + +void CoreNetwork::setAutoWhoDelay(int delay) +{ + _autoWhoTimer.setInterval(delay * 1000); } -void CoreNetwork::setAutoWhoInterval(int interval) { - _autoWhoCycleTimer.setInterval(interval * 1000); + +void CoreNetwork::setAutoWhoInterval(int interval) +{ + _autoWhoCycleTimer.setInterval(interval * 1000); } -void CoreNetwork::setAutoWhoEnabled(bool enabled) { - if(enabled && isConnected() && !_autoWhoTimer.isActive()) - _autoWhoTimer.start(); - else if(!enabled) { - _autoWhoTimer.stop(); - _autoWhoCycleTimer.stop(); - } -} - -void CoreNetwork::sendAutoWho() { - // Don't send autowho if there are still some pending - if(_autoWhoPending.count()) - return; - - while(!_autoWhoQueue.isEmpty()) { - QString chan = _autoWhoQueue.takeFirst(); - IrcChannel *ircchan = ircChannel(chan); - if(!ircchan) continue; - if(networkConfig()->autoWhoNickLimit() > 0 && ircchan->ircUsers().count() >= networkConfig()->autoWhoNickLimit()) - continue; - _autoWhoPending[chan]++; - putRawLine("WHO " + serverEncode(chan)); - break; - } - if(_autoWhoQueue.isEmpty() && networkConfig()->autoWhoEnabled() && !_autoWhoCycleTimer.isActive()) { - // Timer was stopped, means a new cycle is due immediately - _autoWhoCycleTimer.start(); - startAutoWhoCycle(); - } + +void CoreNetwork::setAutoWhoEnabled(bool enabled) +{ + if (enabled && isConnected() && !_autoWhoTimer.isActive()) + _autoWhoTimer.start(); + else if (!enabled) { + _autoWhoTimer.stop(); + _autoWhoCycleTimer.stop(); + } +} + + +void CoreNetwork::sendAutoWho() +{ + // Don't send autowho if there are still some pending + if (_autoWhoPending.count()) + return; + + while (!_autoWhoQueue.isEmpty()) { + QString chan = _autoWhoQueue.takeFirst(); + IrcChannel *ircchan = ircChannel(chan); + if (!ircchan) continue; + if (networkConfig()->autoWhoNickLimit() > 0 && ircchan->ircUsers().count() >= networkConfig()->autoWhoNickLimit()) + continue; + _autoWhoPending[chan]++; + putRawLine("WHO " + serverEncode(chan)); + break; + } + if (_autoWhoQueue.isEmpty() && networkConfig()->autoWhoEnabled() && !_autoWhoCycleTimer.isActive()) { + // Timer was stopped, means a new cycle is due immediately + _autoWhoCycleTimer.start(); + startAutoWhoCycle(); + } } + #ifdef HAVE_SSL -void CoreNetwork::sslErrors(const QList &sslErrors) { - Q_UNUSED(sslErrors) - socket.ignoreSslErrors(); - // TODO errorhandling +void CoreNetwork::sslErrors(const QList &sslErrors) +{ + Q_UNUSED(sslErrors) + socket.ignoreSslErrors(); + // TODO errorhandling } + + #endif // HAVE_SSL -void CoreNetwork::fillBucketAndProcessQueue() { - if(_tokenBucket < _burstSize) { - _tokenBucket++; - } +void CoreNetwork::fillBucketAndProcessQueue() +{ + if (_tokenBucket < _burstSize) { + _tokenBucket++; + } - while(_msgQueue.size() > 0 && _tokenBucket > 0) { - writeToSocket(_msgQueue.takeFirst()); - } + while (_msgQueue.size() > 0 && _tokenBucket > 0) { + writeToSocket(_msgQueue.takeFirst()); + } } -void CoreNetwork::writeToSocket(const QByteArray &data) { - socket.write(data); - socket.write("\r\n"); - _tokenBucket--; + +void CoreNetwork::writeToSocket(const QByteArray &data) +{ + socket.write(data); + socket.write("\r\n"); + _tokenBucket--; } -Network::Server CoreNetwork::usedServer() const { - if(_lastUsedServerIndex < serverList().count()) - return serverList()[_lastUsedServerIndex]; - if(!serverList().isEmpty()) - return serverList()[0]; +Network::Server CoreNetwork::usedServer() const +{ + if (_lastUsedServerIndex < serverList().count()) + return serverList()[_lastUsedServerIndex]; + + if (!serverList().isEmpty()) + return serverList()[0]; - return Network::Server(); + return Network::Server(); } -void CoreNetwork::requestConnect() const { - if(connectionState() != Disconnected) { - qWarning() << "Requesting connect while already being connected!"; - return; - } - QMetaObject::invokeMethod(const_cast(this), "connectToIrc", Qt::QueuedConnection); + +void CoreNetwork::requestConnect() const +{ + if (connectionState() != Disconnected) { + qWarning() << "Requesting connect while already being connected!"; + return; + } + QMetaObject::invokeMethod(const_cast(this), "connectToIrc", Qt::QueuedConnection); } -void CoreNetwork::requestDisconnect() const { - if(connectionState() == Disconnected) { - qWarning() << "Requesting disconnect while not being connected!"; - return; - } - userInputHandler()->handleQuit(BufferInfo(), QString()); + +void CoreNetwork::requestDisconnect() const +{ + if (connectionState() == Disconnected) { + qWarning() << "Requesting disconnect while not being connected!"; + return; + } + userInputHandler()->handleQuit(BufferInfo(), QString()); } -void CoreNetwork::requestSetNetworkInfo(const NetworkInfo &info) { - Network::Server currentServer = usedServer(); - setNetworkInfo(info); - Core::updateNetwork(coreSession()->user(), info); - // the order of the servers might have changed, - // so we try to find the previously used server - _lastUsedServerIndex = 0; - for(int i = 0; i < serverList().count(); i++) { - Network::Server server = serverList()[i]; - if(server.host == currentServer.host && server.port == currentServer.port) { - _lastUsedServerIndex = i; - break; +void CoreNetwork::requestSetNetworkInfo(const NetworkInfo &info) +{ + Network::Server currentServer = usedServer(); + setNetworkInfo(info); + Core::updateNetwork(coreSession()->user(), info); + + // the order of the servers might have changed, + // so we try to find the previously used server + _lastUsedServerIndex = 0; + for (int i = 0; i < serverList().count(); i++) { + Network::Server server = serverList()[i]; + if (server.host == currentServer.host && server.port == currentServer.port) { + _lastUsedServerIndex = i; + break; + } } - } } diff --git a/src/core/corenetwork.h b/src/core/corenetwork.h index 7ad13f43..0bd3a181 100644 --- a/src/core/corenetwork.h +++ b/src/core/corenetwork.h @@ -45,198 +45,202 @@ class CoreUserInputHandler; class CoreIgnoreListManager; class Event; -class CoreNetwork : public Network { - SYNCABLE_OBJECT - Q_OBJECT +class CoreNetwork : public Network +{ + SYNCABLE_OBJECT + Q_OBJECT public: - CoreNetwork(const NetworkId &networkid, CoreSession *session); - ~CoreNetwork(); - inline virtual const QMetaObject *syncMetaObject() const { return &Network::staticMetaObject; } + CoreNetwork(const NetworkId &networkid, CoreSession *session); + ~CoreNetwork(); + inline virtual const QMetaObject *syncMetaObject() const { return &Network::staticMetaObject; } - inline CoreIdentity *identityPtr() const { return coreSession()->identity(identity()); } - inline CoreSession *coreSession() const { return _coreSession; } - inline CoreNetworkConfig *networkConfig() const { return coreSession()->networkConfig(); } + inline CoreIdentity *identityPtr() const { return coreSession()->identity(identity()); } + inline CoreSession *coreSession() const { return _coreSession; } + inline CoreNetworkConfig *networkConfig() const { return coreSession()->networkConfig(); } - inline CoreUserInputHandler *userInputHandler() const { return _userInputHandler; } - inline CoreIgnoreListManager *ignoreListManager() { return coreSession()->ignoreListManager(); } + inline CoreUserInputHandler *userInputHandler() const { return _userInputHandler; } + inline CoreIgnoreListManager *ignoreListManager() { return coreSession()->ignoreListManager(); } - //! Decode a string using the server (network) decoding. - inline QString serverDecode(const QByteArray &string) const { return decodeServerString(string); } + //! Decode a string using the server (network) decoding. + inline QString serverDecode(const QByteArray &string) const { return decodeServerString(string); } - //! Decode a string using a channel-specific encoding if one is set (and use the standard encoding else). - QString channelDecode(const QString &channelName, const QByteArray &string) const; + //! Decode a string using a channel-specific encoding if one is set (and use the standard encoding else). + QString channelDecode(const QString &channelName, const QByteArray &string) const; - //! Decode a string using an IrcUser-specific encoding, if one exists (using the standaed encoding else). - QString userDecode(const QString &userNick, const QByteArray &string) const; + //! Decode a string using an IrcUser-specific encoding, if one exists (using the standaed encoding else). + QString userDecode(const QString &userNick, const QByteArray &string) const; - //! Encode a string using the server (network) encoding. - inline QByteArray serverEncode(const QString &string) const { return encodeServerString(string); } + //! Encode a string using the server (network) encoding. + inline QByteArray serverEncode(const QString &string) const { return encodeServerString(string); } - //! Encode a string using the channel-specific encoding, if set, and use the standard encoding else. - QByteArray channelEncode(const QString &channelName, const QString &string) const; + //! Encode a string using the channel-specific encoding, if set, and use the standard encoding else. + QByteArray channelEncode(const QString &channelName, const QString &string) const; - //! Encode a string using the user-specific encoding, if set, and use the standard encoding else. - QByteArray userEncode(const QString &userNick, const QString &string) const; + //! Encode a string using the user-specific encoding, if set, and use the standard encoding else. + QByteArray userEncode(const QString &userNick, const QString &string) const; - inline QString channelKey(const QString &channel) const { return _channelKeys.value(channel.toLower(), QString()); } + inline QString channelKey(const QString &channel) const { return _channelKeys.value(channel.toLower(), QString()); } - inline bool isAutoWhoInProgress(const QString &channel) const { return _autoWhoPending.value(channel.toLower(), 0); } + inline bool isAutoWhoInProgress(const QString &channel) const { return _autoWhoPending.value(channel.toLower(), 0); } - inline UserId userId() const { return _coreSession->user(); } + inline UserId userId() const { return _coreSession->user(); } - inline QAbstractSocket::SocketState socketState() const { return socket.state(); } - inline bool socketConnected() const { return socket.state() == QAbstractSocket::ConnectedState; } - inline QHostAddress localAddress() const { return socket.localAddress(); } - inline QHostAddress peerAddress() const { return socket.peerAddress(); } - inline quint16 localPort() const { return socket.localPort(); } - inline quint16 peerPort() const { return socket.peerPort(); } + inline QAbstractSocket::SocketState socketState() const { return socket.state(); } + inline bool socketConnected() const { return socket.state() == QAbstractSocket::ConnectedState; } + inline QHostAddress localAddress() const { return socket.localAddress(); } + inline QHostAddress peerAddress() const { return socket.peerAddress(); } + inline quint16 localPort() const { return socket.localPort(); } + inline quint16 peerPort() const { return socket.peerPort(); } public slots: - virtual void setMyNick(const QString &mynick); + virtual void setMyNick(const QString &mynick); - virtual void requestConnect() const; - virtual void requestDisconnect() const; - virtual void requestSetNetworkInfo(const NetworkInfo &info); + virtual void requestConnect() const; + virtual void requestDisconnect() const; + virtual void requestSetNetworkInfo(const NetworkInfo &info); - virtual void setUseAutoReconnect(bool); - virtual void setAutoReconnectInterval(quint32); - virtual void setAutoReconnectRetries(quint16); + virtual void setUseAutoReconnect(bool); + virtual void setAutoReconnectInterval(quint32); + virtual void setAutoReconnectRetries(quint16); - void setPingInterval(int interval); + void setPingInterval(int interval); - void connectToIrc(bool reconnecting = false); - void disconnectFromIrc(bool requested = true, const QString &reason = QString(), bool withReconnect = false); + void connectToIrc(bool reconnecting = false); + void disconnectFromIrc(bool requested = true, const QString &reason = QString(), bool withReconnect = false); - void userInput(BufferInfo bufferInfo, QString msg); - void putRawLine(QByteArray input); - void putCmd(const QString &cmd, const QList ¶ms, const QByteArray &prefix = QByteArray()); + void userInput(BufferInfo bufferInfo, QString msg); + void putRawLine(QByteArray input); + void putCmd(const QString &cmd, const QList ¶ms, const QByteArray &prefix = QByteArray()); - void setChannelJoined(const QString &channel); - void setChannelParted(const QString &channel); - void addChannelKey(const QString &channel, const QString &key); - void removeChannelKey(const QString &channel); + void setChannelJoined(const QString &channel); + void setChannelParted(const QString &channel); + void addChannelKey(const QString &channel, const QString &key); + void removeChannelKey(const QString &channel); - // Blowfish stuff + // Blowfish stuff #ifdef HAVE_QCA2 - Cipher *cipher(const QString &recipient) const; - QByteArray cipherKey(const QString &recipient) const; - void setCipherKey(const QString &recipient, const QByteArray &key); + Cipher *cipher(const QString &recipient) const; + QByteArray cipherKey(const QString &recipient) const; + void setCipherKey(const QString &recipient, const QByteArray &key); #endif - void setAutoWhoEnabled(bool enabled); - void setAutoWhoInterval(int interval); - void setAutoWhoDelay(int delay); + void setAutoWhoEnabled(bool enabled); + void setAutoWhoInterval(int interval); + void setAutoWhoDelay(int delay); - bool setAutoWhoDone(const QString &channel); + bool setAutoWhoDone(const QString &channel); - void updateIssuedModes(const QString &requestedModes); - void updatePersistentModes(QString addModes, QString removeModes); - void resetPersistentModes(); + void updateIssuedModes(const QString &requestedModes); + void updatePersistentModes(QString addModes, QString removeModes); + void resetPersistentModes(); - Server usedServer() const; + Server usedServer() const; - inline void resetPingTimeout() { _pingCount = 0; } + inline void resetPingTimeout() { _pingCount = 0; } + + inline void displayMsg(Message::Type msgType, BufferInfo::Type bufferType, const QString &target, const QString &text, const QString &sender = "", Message::Flags flags = Message::None) + { + emit displayMsg(networkId(), msgType, bufferType, target, text, sender, flags); + } - inline void displayMsg(Message::Type msgType, BufferInfo::Type bufferType, const QString &target, const QString &text, const QString &sender = "", Message::Flags flags = Message::None) { - emit displayMsg(networkId(), msgType, bufferType, target, text, sender, flags); - } signals: - void recvRawServerMsg(QString); - void displayStatusMsg(QString); - void displayMsg(NetworkId, Message::Type, BufferInfo::Type, const QString &target, const QString &text, const QString &sender = "", Message::Flags flags = Message::None); - void disconnected(NetworkId networkId); - void connectionError(const QString &errorMsg); + void recvRawServerMsg(QString); + void displayStatusMsg(QString); + void displayMsg(NetworkId, Message::Type, BufferInfo::Type, const QString &target, const QString &text, const QString &sender = "", Message::Flags flags = Message::None); + void disconnected(NetworkId networkId); + void connectionError(const QString &errorMsg); - void quitRequested(NetworkId networkId); - void sslErrors(const QVariant &errorData); + void quitRequested(NetworkId networkId); + void sslErrors(const QVariant &errorData); - void newEvent(Event *event); - void socketInitialized(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, const QHostAddress &peerAddress, quint16 peerPort); - void socketDisconnected(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, const QHostAddress &peerAddress, quint16 peerPort); + void newEvent(Event *event); + void socketInitialized(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, const QHostAddress &peerAddress, quint16 peerPort); + void socketDisconnected(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, const QHostAddress &peerAddress, quint16 peerPort); protected: - inline virtual IrcChannel *ircChannelFactory(const QString &channelname) { return new CoreIrcChannel(channelname, this); } - inline virtual IrcUser *ircUserFactory(const QString &hostmask) { return new CoreIrcUser(hostmask, this); } + inline virtual IrcChannel *ircChannelFactory(const QString &channelname) { return new CoreIrcChannel(channelname, this); } + inline virtual IrcUser *ircUserFactory(const QString &hostmask) { return new CoreIrcUser(hostmask, this); } protected slots: - // TODO: remove cached cipher keys, when appropriate - //virtual void removeIrcUser(IrcUser *ircuser); - //virtual void removeIrcChannel(IrcChannel *ircChannel); - //virtual void removeChansAndUsers(); + // TODO: remove cached cipher keys, when appropriate + //virtual void removeIrcUser(IrcUser *ircuser); + //virtual void removeIrcChannel(IrcChannel *ircChannel); + //virtual void removeChansAndUsers(); private slots: - void socketHasData(); - void socketError(QAbstractSocket::SocketError); - void socketInitialized(); - inline void socketCloseTimeout() { socket.disconnectFromHost(); } - void socketDisconnected(); - void socketStateChanged(QAbstractSocket::SocketState); - void networkInitialized(); - - void sendPerform(); - void restoreUserModes(); - void doAutoReconnect(); - void sendPing(); - void enablePingTimeout(bool enable = true); - void disablePingTimeout(); - void sendAutoWho(); - void startAutoWhoCycle(); + void socketHasData(); + void socketError(QAbstractSocket::SocketError); + void socketInitialized(); + inline void socketCloseTimeout() { socket.disconnectFromHost(); } + void socketDisconnected(); + void socketStateChanged(QAbstractSocket::SocketState); + void networkInitialized(); + + void sendPerform(); + void restoreUserModes(); + void doAutoReconnect(); + void sendPing(); + void enablePingTimeout(bool enable = true); + void disablePingTimeout(); + void sendAutoWho(); + void startAutoWhoCycle(); #ifdef HAVE_SSL - void sslErrors(const QList &errors); + void sslErrors(const QList &errors); #endif - void fillBucketAndProcessQueue(); + void fillBucketAndProcessQueue(); - void writeToSocket(const QByteArray &data); + void writeToSocket(const QByteArray &data); private: - CoreSession *_coreSession; + CoreSession *_coreSession; #ifdef HAVE_SSL - QSslSocket socket; + QSslSocket socket; #else - QTcpSocket socket; + QTcpSocket socket; #endif - CoreUserInputHandler *_userInputHandler; + CoreUserInputHandler *_userInputHandler; - QHash _channelKeys; // stores persistent channels and their passwords, if any + QHash _channelKeys; // stores persistent channels and their passwords, if any - QTimer _autoReconnectTimer; - int _autoReconnectCount; + QTimer _autoReconnectTimer; + int _autoReconnectCount; - QTimer _socketCloseTimer; + QTimer _socketCloseTimer; - /* this flag triggers quitRequested() once the socket is closed - * it is needed to determine whether or not the connection needs to be - * in the automatic session restore. */ - bool _quitRequested; - QString _quitReason; + /* this flag triggers quitRequested() once the socket is closed + * it is needed to determine whether or not the connection needs to be + * in the automatic session restore. */ + bool _quitRequested; + QString _quitReason; - bool _previousConnectionAttemptFailed; - int _lastUsedServerIndex; + bool _previousConnectionAttemptFailed; + int _lastUsedServerIndex; - QTimer _pingTimer; - uint _lastPingTime; - uint _pingCount; + QTimer _pingTimer; + uint _lastPingTime; + uint _pingCount; - QStringList _autoWhoQueue; - QHash _autoWhoPending; - QTimer _autoWhoTimer, _autoWhoCycleTimer; + QStringList _autoWhoQueue; + QHash _autoWhoPending; + QTimer _autoWhoTimer, _autoWhoCycleTimer; - QTimer _tokenBucketTimer; - int _messageDelay; // token refill speed in ms - int _burstSize; // size of the token bucket - int _tokenBucket; // the virtual bucket that holds the tokens - QList _msgQueue; + QTimer _tokenBucketTimer; + int _messageDelay; // token refill speed in ms + int _burstSize; // size of the token bucket + int _tokenBucket; // the virtual bucket that holds the tokens + QList _msgQueue; - QString _requestedUserModes; // 2 strings separated by a '-' character. first part are requested modes to add, the second to remove + QString _requestedUserModes; // 2 strings separated by a '-' character. first part are requested modes to add, the second to remove - // Blowfish key map - QHash _cipherKeys; + // Blowfish key map + QHash _cipherKeys; }; + #endif //CORENETWORK_H diff --git a/src/core/corenetworkconfig.cpp b/src/core/corenetworkconfig.cpp index ba95db56..feb7fec1 100644 --- a/src/core/corenetworkconfig.cpp +++ b/src/core/corenetworkconfig.cpp @@ -23,25 +23,27 @@ #include "corenetworkconfig.h" INIT_SYNCABLE_OBJECT(CoreNetworkConfig) -CoreNetworkConfig::CoreNetworkConfig(const QString& objectName, CoreSession* session) - : NetworkConfig(objectName, session) +CoreNetworkConfig::CoreNetworkConfig(const QString &objectName, CoreSession *session) + : NetworkConfig(objectName, session) { - setAllowClientUpdates(true); + setAllowClientUpdates(true); - if(!session) { - qWarning() << Q_FUNC_INFO << "No CoreSession set, cannot load network configuration!"; - return; - } + if (!session) { + qWarning() << Q_FUNC_INFO << "No CoreSession set, cannot load network configuration!"; + return; + } - fromVariantMap(Core::getUserSetting(session->user(), objectName).toMap()); + fromVariantMap(Core::getUserSetting(session->user(), objectName).toMap()); } -void CoreNetworkConfig::save() { - CoreSession *session = qobject_cast(parent()); - if(!session) { - qWarning() << Q_FUNC_INFO << "No CoreSession set, cannot save network configuration!"; - return; - } - Core::setUserSetting(session->user(), objectName(), toVariantMap()); +void CoreNetworkConfig::save() +{ + CoreSession *session = qobject_cast(parent()); + if (!session) { + qWarning() << Q_FUNC_INFO << "No CoreSession set, cannot save network configuration!"; + return; + } + + Core::setUserSetting(session->user(), objectName(), toVariantMap()); } diff --git a/src/core/corenetworkconfig.h b/src/core/corenetworkconfig.h index 88aa2279..6c78c479 100644 --- a/src/core/corenetworkconfig.h +++ b/src/core/corenetworkconfig.h @@ -25,25 +25,27 @@ class CoreSession; -class CoreNetworkConfig : public NetworkConfig { - SYNCABLE_OBJECT - Q_OBJECT +class CoreNetworkConfig : public NetworkConfig +{ + SYNCABLE_OBJECT + Q_OBJECT public: - CoreNetworkConfig(const QString &objectName, CoreSession *parent); + CoreNetworkConfig(const QString &objectName, CoreSession *parent); - inline virtual const QMetaObject *syncMetaObject() const { return &NetworkConfig::staticMetaObject; } + inline virtual const QMetaObject *syncMetaObject() const { return &NetworkConfig::staticMetaObject; } - void save(); + void save(); public slots: - virtual inline void requestSetPingTimeoutEnabled(bool enabled) { setPingTimeoutEnabled(enabled); } - virtual inline void requestSetPingInterval(int interval) { setPingInterval(interval); } - virtual inline void requestSetMaxPingCount(int count) { setMaxPingCount(count); } - virtual inline void requestSetAutoWhoEnabled(bool enabled) { setAutoWhoEnabled(enabled); } - virtual inline void requestSetAutoWhoInterval(int interval) { setAutoWhoInterval(interval); } - virtual inline void requestSetAutoWhoNickLimit(int nickLimit) { setAutoWhoNickLimit(nickLimit); } - virtual inline void requestSetAutoWhoDelay(int delay) { setAutoWhoDelay(delay); } + virtual inline void requestSetPingTimeoutEnabled(bool enabled) { setPingTimeoutEnabled(enabled); } + virtual inline void requestSetPingInterval(int interval) { setPingInterval(interval); } + virtual inline void requestSetMaxPingCount(int count) { setMaxPingCount(count); } + virtual inline void requestSetAutoWhoEnabled(bool enabled) { setAutoWhoEnabled(enabled); } + virtual inline void requestSetAutoWhoInterval(int interval) { setAutoWhoInterval(interval); } + virtual inline void requestSetAutoWhoNickLimit(int nickLimit) { setAutoWhoNickLimit(nickLimit); } + virtual inline void requestSetAutoWhoDelay(int delay) { setAutoWhoDelay(delay); } }; + #endif diff --git a/src/core/coresession.cpp b/src/core/coresession.cpp index 6c0c5e13..9d739be3 100644 --- a/src/core/coresession.cpp +++ b/src/core/coresession.cpp @@ -46,13 +46,15 @@ #include "storage.h" #include "util.h" -class ProcessMessagesEvent : public QEvent { +class ProcessMessagesEvent : public QEvent +{ public: - ProcessMessagesEvent() : QEvent(QEvent::User) {} + ProcessMessagesEvent() : QEvent(QEvent::User) {} }; + CoreSession::CoreSession(UserId uid, bool restoreState, QObject *parent) - : QObject(parent), + : QObject(parent), _user(uid), _signalProxy(new SignalProxy(SignalProxy::Server, 0, this)), _aliasManager(this), @@ -71,519 +73,587 @@ CoreSession::CoreSession(UserId uid, bool restoreState, QObject *parent) _processMessages(false), _ignoreListManager(this) { - SignalProxy *p = signalProxy(); - p->setHeartBeatInterval(30); - p->setMaxHeartBeatCount(60); // 30 mins until we throw a dead socket out - - connect(p, SIGNAL(peerRemoved(QIODevice *)), this, SLOT(removeClient(QIODevice *))); - - connect(p, SIGNAL(connected()), this, SLOT(clientsConnected())); - connect(p, SIGNAL(disconnected()), this, SLOT(clientsDisconnected())); - - p->attachSlot(SIGNAL(sendInput(BufferInfo, QString)), this, SLOT(msgFromClient(BufferInfo, QString))); - p->attachSignal(this, SIGNAL(displayMsg(Message))); - p->attachSignal(this, SIGNAL(displayStatusMsg(QString, QString))); - - p->attachSignal(this, SIGNAL(identityCreated(const Identity &))); - p->attachSignal(this, SIGNAL(identityRemoved(IdentityId))); - p->attachSlot(SIGNAL(createIdentity(const Identity &, const QVariantMap &)), this, SLOT(createIdentity(const Identity &, const QVariantMap &))); - p->attachSlot(SIGNAL(removeIdentity(IdentityId)), this, SLOT(removeIdentity(IdentityId))); - - p->attachSignal(this, SIGNAL(networkCreated(NetworkId))); - p->attachSignal(this, SIGNAL(networkRemoved(NetworkId))); - p->attachSlot(SIGNAL(createNetwork(const NetworkInfo &, const QStringList &)), this, SLOT(createNetwork(const NetworkInfo &, const QStringList &))); - p->attachSlot(SIGNAL(removeNetwork(NetworkId)), this, SLOT(removeNetwork(NetworkId))); - - loadSettings(); - initScriptEngine(); - - eventManager()->registerObject(ircParser(), EventManager::NormalPriority); - eventManager()->registerObject(sessionEventProcessor(), EventManager::HighPriority); // needs to process events *before* the stringifier! - eventManager()->registerObject(ctcpParser(), EventManager::NormalPriority); - eventManager()->registerObject(eventStringifier(), EventManager::NormalPriority); - eventManager()->registerObject(this, EventManager::LowPriority); // for sending MessageEvents to the client - // some events need to be handled after msg generation - eventManager()->registerObject(sessionEventProcessor(), EventManager::LowPriority, "lateProcess"); - eventManager()->registerObject(ctcpParser(), EventManager::LowPriority, "send"); - - // periodically save our session state - connect(&(Core::instance()->syncTimer()), SIGNAL(timeout()), this, SLOT(saveSessionState())); - - p->synchronize(_bufferSyncer); - p->synchronize(&aliasManager()); - p->synchronize(_backlogManager); - p->synchronize(ircListHelper()); - p->synchronize(networkConfig()); - p->synchronize(&_coreInfo); - p->synchronize(&_ignoreListManager); - // Restore session state - if(restoreState) - restoreSessionState(); - - emit initialized(); -} - -CoreSession::~CoreSession() { - saveSessionState(); - foreach(CoreNetwork *net, _networks.values()) { - delete net; - } -} - -CoreNetwork *CoreSession::network(NetworkId id) const { - if(_networks.contains(id)) return _networks[id]; - return 0; -} - -CoreIdentity *CoreSession::identity(IdentityId id) const { - if(_identities.contains(id)) return _identities[id]; - return 0; -} - -void CoreSession::loadSettings() { - CoreUserSettings s(user()); - - // migrate to db - QList ids = s.identityIds(); - QList networkInfos = Core::networks(user()); - foreach(IdentityId id, ids) { - CoreIdentity identity(s.identity(id)); - IdentityId newId = Core::createIdentity(user(), identity); - QList::iterator networkIter = networkInfos.begin(); - while(networkIter != networkInfos.end()) { - if(networkIter->identity == id) { - networkIter->identity = newId; - Core::updateNetwork(user(), *networkIter); - networkIter = networkInfos.erase(networkIter); - } else { - networkIter++; - } + SignalProxy *p = signalProxy(); + p->setHeartBeatInterval(30); + p->setMaxHeartBeatCount(60); // 30 mins until we throw a dead socket out + + connect(p, SIGNAL(peerRemoved(QIODevice *)), this, SLOT(removeClient(QIODevice *))); + + connect(p, SIGNAL(connected()), this, SLOT(clientsConnected())); + connect(p, SIGNAL(disconnected()), this, SLOT(clientsDisconnected())); + + p->attachSlot(SIGNAL(sendInput(BufferInfo, QString)), this, SLOT(msgFromClient(BufferInfo, QString))); + p->attachSignal(this, SIGNAL(displayMsg(Message))); + p->attachSignal(this, SIGNAL(displayStatusMsg(QString, QString))); + + p->attachSignal(this, SIGNAL(identityCreated(const Identity &))); + p->attachSignal(this, SIGNAL(identityRemoved(IdentityId))); + p->attachSlot(SIGNAL(createIdentity(const Identity &, const QVariantMap &)), this, SLOT(createIdentity(const Identity &, const QVariantMap &))); + p->attachSlot(SIGNAL(removeIdentity(IdentityId)), this, SLOT(removeIdentity(IdentityId))); + + p->attachSignal(this, SIGNAL(networkCreated(NetworkId))); + p->attachSignal(this, SIGNAL(networkRemoved(NetworkId))); + p->attachSlot(SIGNAL(createNetwork(const NetworkInfo &, const QStringList &)), this, SLOT(createNetwork(const NetworkInfo &, const QStringList &))); + p->attachSlot(SIGNAL(removeNetwork(NetworkId)), this, SLOT(removeNetwork(NetworkId))); + + loadSettings(); + initScriptEngine(); + + eventManager()->registerObject(ircParser(), EventManager::NormalPriority); + eventManager()->registerObject(sessionEventProcessor(), EventManager::HighPriority); // needs to process events *before* the stringifier! + eventManager()->registerObject(ctcpParser(), EventManager::NormalPriority); + eventManager()->registerObject(eventStringifier(), EventManager::NormalPriority); + eventManager()->registerObject(this, EventManager::LowPriority); // for sending MessageEvents to the client + // some events need to be handled after msg generation + eventManager()->registerObject(sessionEventProcessor(), EventManager::LowPriority, "lateProcess"); + eventManager()->registerObject(ctcpParser(), EventManager::LowPriority, "send"); + + // periodically save our session state + connect(&(Core::instance()->syncTimer()), SIGNAL(timeout()), this, SLOT(saveSessionState())); + + p->synchronize(_bufferSyncer); + p->synchronize(&aliasManager()); + p->synchronize(_backlogManager); + p->synchronize(ircListHelper()); + p->synchronize(networkConfig()); + p->synchronize(&_coreInfo); + p->synchronize(&_ignoreListManager); + // Restore session state + if (restoreState) + restoreSessionState(); + + emit initialized(); +} + + +CoreSession::~CoreSession() +{ + saveSessionState(); + foreach(CoreNetwork *net, _networks.values()) { + delete net; } - s.removeIdentity(id); - } - // end of migration +} - foreach(CoreIdentity identity, Core::identities(user())) { - createIdentity(identity); - } - foreach(NetworkInfo info, Core::networks(user())) { - createNetwork(info); - } +CoreNetwork *CoreSession::network(NetworkId id) const +{ + if (_networks.contains(id)) return _networks[id]; + return 0; } -void CoreSession::saveSessionState() const { - _bufferSyncer->storeDirtyIds(); - _bufferViewManager->saveBufferViews(); - _networkConfig->save(); + +CoreIdentity *CoreSession::identity(IdentityId id) const +{ + if (_identities.contains(id)) return _identities[id]; + return 0; } -void CoreSession::restoreSessionState() { - QList nets = Core::connectedNetworks(user()); - CoreNetwork *net = 0; - foreach(NetworkId id, nets) { - net = network(id); - Q_ASSERT(net); - net->connectToIrc(); - } + +void CoreSession::loadSettings() +{ + CoreUserSettings s(user()); + + // migrate to db + QList ids = s.identityIds(); + QList networkInfos = Core::networks(user()); + foreach(IdentityId id, ids) { + CoreIdentity identity(s.identity(id)); + IdentityId newId = Core::createIdentity(user(), identity); + QList::iterator networkIter = networkInfos.begin(); + while (networkIter != networkInfos.end()) { + if (networkIter->identity == id) { + networkIter->identity = newId; + Core::updateNetwork(user(), *networkIter); + networkIter = networkInfos.erase(networkIter); + } + else { + networkIter++; + } + } + s.removeIdentity(id); + } + // end of migration + + foreach(CoreIdentity identity, Core::identities(user())) { + createIdentity(identity); + } + + foreach(NetworkInfo info, Core::networks(user())) { + createNetwork(info); + } +} + + +void CoreSession::saveSessionState() const +{ + _bufferSyncer->storeDirtyIds(); + _bufferViewManager->saveBufferViews(); + _networkConfig->save(); } -void CoreSession::addClient(QIODevice *device) { - if(!device) { - qCritical() << "Invoking CoreSession::addClient with a QObject that is not a QIODevice!"; - } else { - // if the socket is an orphan, the signalProxy adopts it. - // -> we don't need to care about it anymore - device->setParent(0); - signalProxy()->addPeer(device); - QVariantMap reply; - reply["MsgType"] = "SessionInit"; - reply["SessionState"] = sessionState(); - SignalProxy::writeDataToDevice(device, reply); - } + +void CoreSession::restoreSessionState() +{ + QList nets = Core::connectedNetworks(user()); + CoreNetwork *net = 0; + foreach(NetworkId id, nets) { + net = network(id); + Q_ASSERT(net); + net->connectToIrc(); + } } -void CoreSession::addClient(SignalProxy *proxy) { - signalProxy()->addPeer(proxy); - emit sessionState(sessionState()); + +void CoreSession::addClient(QIODevice *device) +{ + if (!device) { + qCritical() << "Invoking CoreSession::addClient with a QObject that is not a QIODevice!"; + } + else { + // if the socket is an orphan, the signalProxy adopts it. + // -> we don't need to care about it anymore + device->setParent(0); + signalProxy()->addPeer(device); + QVariantMap reply; + reply["MsgType"] = "SessionInit"; + reply["SessionState"] = sessionState(); + SignalProxy::writeDataToDevice(device, reply); + } } -void CoreSession::removeClient(QIODevice *iodev) { - QTcpSocket *socket = qobject_cast(iodev); - if(socket) - quInfo() << qPrintable(tr("Client")) << qPrintable(socket->peerAddress().toString()) << qPrintable(tr("disconnected (UserId: %1).").arg(user().toInt())); + +void CoreSession::addClient(SignalProxy *proxy) +{ + signalProxy()->addPeer(proxy); + emit sessionState(sessionState()); } -QHash CoreSession::persistentChannels(NetworkId id) const { - return Core::persistentChannels(user(), id); + +void CoreSession::removeClient(QIODevice *iodev) +{ + QTcpSocket *socket = qobject_cast(iodev); + if (socket) + quInfo() << qPrintable(tr("Client")) << qPrintable(socket->peerAddress().toString()) << qPrintable(tr("disconnected (UserId: %1).").arg(user().toInt())); } + +QHash CoreSession::persistentChannels(NetworkId id) const +{ + return Core::persistentChannels(user(), id); +} + + // FIXME switch to BufferId -void CoreSession::msgFromClient(BufferInfo bufinfo, QString msg) { - CoreNetwork *net = network(bufinfo.networkId()); - if(net) { - net->userInput(bufinfo, msg); - } else { - qWarning() << "Trying to send to unconnected network:" << msg; - } +void CoreSession::msgFromClient(BufferInfo bufinfo, QString msg) +{ + CoreNetwork *net = network(bufinfo.networkId()); + if (net) { + net->userInput(bufinfo, msg); + } + else { + qWarning() << "Trying to send to unconnected network:" << msg; + } } + // ALL messages coming pass through these functions before going to the GUI. // So this is the perfect place for storing the backlog and log stuff. void CoreSession::recvMessageFromServer(NetworkId networkId, Message::Type type, BufferInfo::Type bufferType, - const QString &target, const QString &text_, const QString &sender, Message::Flags flags) { - - // U+FDD0 and U+FDD1 are special characters for Qt's text engine, specifically they mark the boundaries of - // text frames in a QTextDocument. This might lead to problems in widgets displaying QTextDocuments (such as - // KDE's notifications), hence we remove those just to be safe. - QString text = text_; - text.remove(QChar(0xfdd0)).remove(QChar(0xfdd1)); - RawMessage rawMsg(networkId, type, bufferType, target, text, sender, flags); + const QString &target, const QString &text_, const QString &sender, Message::Flags flags) +{ + // U+FDD0 and U+FDD1 are special characters for Qt's text engine, specifically they mark the boundaries of + // text frames in a QTextDocument. This might lead to problems in widgets displaying QTextDocuments (such as + // KDE's notifications), hence we remove those just to be safe. + QString text = text_; + text.remove(QChar(0xfdd0)).remove(QChar(0xfdd1)); + RawMessage rawMsg(networkId, type, bufferType, target, text, sender, flags); + + // check for HardStrictness ignore + CoreNetwork *currentNetwork = network(networkId); + QString networkName = currentNetwork ? currentNetwork->networkName() : QString(""); + if (_ignoreListManager.match(rawMsg, networkName) == IgnoreListManager::HardStrictness) + return; + + _messageQueue << rawMsg; + if (!_processMessages) { + _processMessages = true; + QCoreApplication::postEvent(this, new ProcessMessagesEvent()); + } +} - // check for HardStrictness ignore - CoreNetwork *currentNetwork = network(networkId); - QString networkName = currentNetwork ? currentNetwork->networkName() : QString(""); - if(_ignoreListManager.match(rawMsg, networkName) == IgnoreListManager::HardStrictness) - return; - _messageQueue << rawMsg; - if(!_processMessages) { - _processMessages = true; - QCoreApplication::postEvent(this, new ProcessMessagesEvent()); - } +void CoreSession::recvStatusMsgFromServer(QString msg) +{ + CoreNetwork *net = qobject_cast(sender()); + Q_ASSERT(net); + emit displayStatusMsg(net->networkName(), msg); } -void CoreSession::recvStatusMsgFromServer(QString msg) { - CoreNetwork *net = qobject_cast(sender()); - Q_ASSERT(net); - emit displayStatusMsg(net->networkName(), msg); -} -void CoreSession::processMessageEvent(MessageEvent *event) { - recvMessageFromServer(event->networkId(), event->msgType(), event->bufferType(), - event->target().isNull()? "" : event->target(), - event->text().isNull()? "" : event->text(), - event->sender().isNull()? "" : event->sender(), - event->msgFlags()); +void CoreSession::processMessageEvent(MessageEvent *event) +{ + recvMessageFromServer(event->networkId(), event->msgType(), event->bufferType(), + event->target().isNull() ? "" : event->target(), + event->text().isNull() ? "" : event->text(), + event->sender().isNull() ? "" : event->sender(), + event->msgFlags()); } -QList CoreSession::buffers() const { - return Core::requestBuffers(user()); + +QList CoreSession::buffers() const +{ + return Core::requestBuffers(user()); } -void CoreSession::customEvent(QEvent *event) { - if(event->type() != QEvent::User) - return; - processMessages(); - event->accept(); +void CoreSession::customEvent(QEvent *event) +{ + if (event->type() != QEvent::User) + return; + + processMessages(); + event->accept(); } -void CoreSession::processMessages() { - if(_messageQueue.count() == 1) { - const RawMessage &rawMsg = _messageQueue.first(); - bool createBuffer = !(rawMsg.flags & Message::Redirected); - BufferInfo bufferInfo = Core::bufferInfo(user(), rawMsg.networkId, rawMsg.bufferType, rawMsg.target, createBuffer); - if(!bufferInfo.isValid()) { - Q_ASSERT(!createBuffer); - bufferInfo = Core::bufferInfo(user(), rawMsg.networkId, BufferInfo::StatusBuffer, ""); - } - Message msg(bufferInfo, rawMsg.type, rawMsg.text, rawMsg.sender, rawMsg.flags); - Core::storeMessage(msg); - emit displayMsg(msg); - } else { - QHash > bufferInfoCache; - MessageList messages; - QList redirectedMessages; // list of Messages which don't enforce a buffer creation - BufferInfo bufferInfo; - for(int i = 0; i < _messageQueue.count(); i++) { - const RawMessage &rawMsg = _messageQueue.at(i); - if(bufferInfoCache.contains(rawMsg.networkId) && bufferInfoCache[rawMsg.networkId].contains(rawMsg.target)) { - bufferInfo = bufferInfoCache[rawMsg.networkId][rawMsg.target]; - } else { + +void CoreSession::processMessages() +{ + if (_messageQueue.count() == 1) { + const RawMessage &rawMsg = _messageQueue.first(); bool createBuffer = !(rawMsg.flags & Message::Redirected); - bufferInfo = Core::bufferInfo(user(), rawMsg.networkId, rawMsg.bufferType, rawMsg.target, createBuffer); - if(!bufferInfo.isValid()) { - Q_ASSERT(!createBuffer); - redirectedMessages << rawMsg; - continue; + BufferInfo bufferInfo = Core::bufferInfo(user(), rawMsg.networkId, rawMsg.bufferType, rawMsg.target, createBuffer); + if (!bufferInfo.isValid()) { + Q_ASSERT(!createBuffer); + bufferInfo = Core::bufferInfo(user(), rawMsg.networkId, BufferInfo::StatusBuffer, ""); } - bufferInfoCache[rawMsg.networkId][rawMsg.target] = bufferInfo; - } - Message msg(bufferInfo, rawMsg.type, rawMsg.text, rawMsg.sender, rawMsg.flags); - messages << msg; + Message msg(bufferInfo, rawMsg.type, rawMsg.text, rawMsg.sender, rawMsg.flags); + Core::storeMessage(msg); + emit displayMsg(msg); } + else { + QHash > bufferInfoCache; + MessageList messages; + QList redirectedMessages; // list of Messages which don't enforce a buffer creation + BufferInfo bufferInfo; + for (int i = 0; i < _messageQueue.count(); i++) { + const RawMessage &rawMsg = _messageQueue.at(i); + if (bufferInfoCache.contains(rawMsg.networkId) && bufferInfoCache[rawMsg.networkId].contains(rawMsg.target)) { + bufferInfo = bufferInfoCache[rawMsg.networkId][rawMsg.target]; + } + else { + bool createBuffer = !(rawMsg.flags & Message::Redirected); + bufferInfo = Core::bufferInfo(user(), rawMsg.networkId, rawMsg.bufferType, rawMsg.target, createBuffer); + if (!bufferInfo.isValid()) { + Q_ASSERT(!createBuffer); + redirectedMessages << rawMsg; + continue; + } + bufferInfoCache[rawMsg.networkId][rawMsg.target] = bufferInfo; + } + Message msg(bufferInfo, rawMsg.type, rawMsg.text, rawMsg.sender, rawMsg.flags); + messages << msg; + } - // recheck if there exists a buffer to store a redirected message in - for(int i = 0; i < redirectedMessages.count(); i++) { - const RawMessage &rawMsg = _messageQueue.at(i); - if(bufferInfoCache.contains(rawMsg.networkId) && bufferInfoCache[rawMsg.networkId].contains(rawMsg.target)) { - bufferInfo = bufferInfoCache[rawMsg.networkId][rawMsg.target]; - } else { - // no luck -> we store them in the StatusBuffer - bufferInfo = Core::bufferInfo(user(), rawMsg.networkId, BufferInfo::StatusBuffer, ""); - // add the StatusBuffer to the Cache in case there are more Messages for the original target - bufferInfoCache[rawMsg.networkId][rawMsg.target] = bufferInfo; - } - Message msg(bufferInfo, rawMsg.type, rawMsg.text, rawMsg.sender, rawMsg.flags); - messages << msg; - } + // recheck if there exists a buffer to store a redirected message in + for (int i = 0; i < redirectedMessages.count(); i++) { + const RawMessage &rawMsg = _messageQueue.at(i); + if (bufferInfoCache.contains(rawMsg.networkId) && bufferInfoCache[rawMsg.networkId].contains(rawMsg.target)) { + bufferInfo = bufferInfoCache[rawMsg.networkId][rawMsg.target]; + } + else { + // no luck -> we store them in the StatusBuffer + bufferInfo = Core::bufferInfo(user(), rawMsg.networkId, BufferInfo::StatusBuffer, ""); + // add the StatusBuffer to the Cache in case there are more Messages for the original target + bufferInfoCache[rawMsg.networkId][rawMsg.target] = bufferInfo; + } + Message msg(bufferInfo, rawMsg.type, rawMsg.text, rawMsg.sender, rawMsg.flags); + messages << msg; + } - Core::storeMessages(messages); - // FIXME: extend protocol to a displayMessages(MessageList) - for(int i = 0; i < messages.count(); i++) { - emit displayMsg(messages[i]); + Core::storeMessages(messages); + // FIXME: extend protocol to a displayMessages(MessageList) + for (int i = 0; i < messages.count(); i++) { + emit displayMsg(messages[i]); + } } - } - _processMessages = false; - _messageQueue.clear(); + _processMessages = false; + _messageQueue.clear(); } -QVariant CoreSession::sessionState() { - QVariantMap v; - v["CoreFeatures"] = (int)Quassel::features(); +QVariant CoreSession::sessionState() +{ + QVariantMap v; + + v["CoreFeatures"] = (int)Quassel::features(); + + QVariantList bufs; + foreach(BufferInfo id, buffers()) bufs << qVariantFromValue(id); + v["BufferInfos"] = bufs; + QVariantList networkids; + foreach(NetworkId id, _networks.keys()) networkids << qVariantFromValue(id); + v["NetworkIds"] = networkids; + + quint32 ircusercount = 0; + quint32 ircchannelcount = 0; + foreach(Network *net, _networks.values()) { + ircusercount += net->ircUserCount(); + ircchannelcount += net->ircChannelCount(); + } + v["IrcUserCount"] = ircusercount; + v["IrcChannelCount"] = ircchannelcount; + + QList idlist; + foreach(Identity *i, _identities.values()) idlist << qVariantFromValue(*i); + v["Identities"] = idlist; - QVariantList bufs; - foreach(BufferInfo id, buffers()) bufs << qVariantFromValue(id); - v["BufferInfos"] = bufs; - QVariantList networkids; - foreach(NetworkId id, _networks.keys()) networkids << qVariantFromValue(id); - v["NetworkIds"] = networkids; + //v["Payload"] = QByteArray(100000000, 'a'); // for testing purposes + return v; +} - quint32 ircusercount = 0; - quint32 ircchannelcount = 0; - foreach(Network *net, _networks.values()) { - ircusercount += net->ircUserCount(); - ircchannelcount += net->ircChannelCount(); - } - v["IrcUserCount"] = ircusercount; - v["IrcChannelCount"] = ircchannelcount; - QList idlist; - foreach(Identity *i, _identities.values()) idlist << qVariantFromValue(*i); - v["Identities"] = idlist; +void CoreSession::initScriptEngine() +{ + signalProxy()->attachSlot(SIGNAL(scriptRequest(QString)), this, SLOT(scriptRequest(QString))); + signalProxy()->attachSignal(this, SIGNAL(scriptResult(QString))); - //v["Payload"] = QByteArray(100000000, 'a'); // for testing purposes - return v; + // FIXME + //QScriptValue storage_ = scriptEngine->newQObject(storage); + //scriptEngine->globalObject().setProperty("storage", storage_); } -void CoreSession::initScriptEngine() { - signalProxy()->attachSlot(SIGNAL(scriptRequest(QString)), this, SLOT(scriptRequest(QString))); - signalProxy()->attachSignal(this, SIGNAL(scriptResult(QString))); - // FIXME - //QScriptValue storage_ = scriptEngine->newQObject(storage); - //scriptEngine->globalObject().setProperty("storage", storage_); +void CoreSession::scriptRequest(QString script) +{ + emit scriptResult(scriptEngine->evaluate(script).toString()); } -void CoreSession::scriptRequest(QString script) { - emit scriptResult(scriptEngine->evaluate(script).toString()); -} /*** Identity Handling ***/ -void CoreSession::createIdentity(const Identity &identity, const QVariantMap &additional) { +void CoreSession::createIdentity(const Identity &identity, const QVariantMap &additional) +{ #ifndef HAVE_SSL - Q_UNUSED(additional) + Q_UNUSED(additional) #endif - CoreIdentity coreIdentity(identity); + CoreIdentity coreIdentity(identity); #ifdef HAVE_SSL - if(additional.contains("KeyPem")) - coreIdentity.setSslKey(additional["KeyPem"].toByteArray()); - if(additional.contains("CertPem")) - coreIdentity.setSslCert(additional["CertPem"].toByteArray()); + if (additional.contains("KeyPem")) + coreIdentity.setSslKey(additional["KeyPem"].toByteArray()); + if (additional.contains("CertPem")) + coreIdentity.setSslCert(additional["CertPem"].toByteArray()); #endif - qDebug() << Q_FUNC_INFO; - IdentityId id = Core::createIdentity(user(), coreIdentity); - if(!id.isValid()) - return; - else - createIdentity(coreIdentity); + qDebug() << Q_FUNC_INFO; + IdentityId id = Core::createIdentity(user(), coreIdentity); + if (!id.isValid()) + return; + else + createIdentity(coreIdentity); } -void CoreSession::createIdentity(const CoreIdentity &identity) { - CoreIdentity *coreIdentity = new CoreIdentity(identity, this); - _identities[identity.id()] = coreIdentity; - // CoreIdentity has its own synchronize method since its "private" sslManager needs to be synced as well - coreIdentity->synchronize(signalProxy()); - connect(coreIdentity, SIGNAL(updated()), this, SLOT(updateIdentityBySender())); - emit identityCreated(*coreIdentity); + +void CoreSession::createIdentity(const CoreIdentity &identity) +{ + CoreIdentity *coreIdentity = new CoreIdentity(identity, this); + _identities[identity.id()] = coreIdentity; + // CoreIdentity has its own synchronize method since its "private" sslManager needs to be synced as well + coreIdentity->synchronize(signalProxy()); + connect(coreIdentity, SIGNAL(updated()), this, SLOT(updateIdentityBySender())); + emit identityCreated(*coreIdentity); } -void CoreSession::updateIdentityBySender() { - CoreIdentity *identity = qobject_cast(sender()); - if(!identity) - return; - Core::updateIdentity(user(), *identity); + +void CoreSession::updateIdentityBySender() +{ + CoreIdentity *identity = qobject_cast(sender()); + if (!identity) + return; + Core::updateIdentity(user(), *identity); } -void CoreSession::removeIdentity(IdentityId id) { - CoreIdentity *identity = _identities.take(id); - if(identity) { - emit identityRemoved(id); - Core::removeIdentity(user(), id); - identity->deleteLater(); - } + +void CoreSession::removeIdentity(IdentityId id) +{ + CoreIdentity *identity = _identities.take(id); + if (identity) { + emit identityRemoved(id); + Core::removeIdentity(user(), id); + identity->deleteLater(); + } } + /*** Network Handling ***/ -void CoreSession::createNetwork(const NetworkInfo &info_, const QStringList &persistentChans) { - NetworkInfo info = info_; - int id; - - if(!info.networkId.isValid()) - Core::createNetwork(user(), info); - - if(!info.networkId.isValid()) { - qWarning() << qPrintable(tr("CoreSession::createNetwork(): Got invalid networkId from Core when trying to create network %1!").arg(info.networkName)); - return; - } - - id = info.networkId.toInt(); - if(!_networks.contains(id)) { - - // create persistent chans - QRegExp rx("\\s*(\\S+)(?:\\s*(\\S+))?\\s*"); - foreach(QString channel, persistentChans) { - if(!rx.exactMatch(channel)) { - qWarning() << QString("Invalid persistent channel declaration: %1").arg(channel); - continue; - } - Core::bufferInfo(user(), info.networkId, BufferInfo::ChannelBuffer, rx.cap(1), true); - Core::setChannelPersistent(user(), info.networkId, rx.cap(1), true); - if(!rx.cap(2).isEmpty()) - Core::setPersistentChannelKey(user(), info.networkId, rx.cap(1), rx.cap(2)); +void CoreSession::createNetwork(const NetworkInfo &info_, const QStringList &persistentChans) +{ + NetworkInfo info = info_; + int id; + + if (!info.networkId.isValid()) + Core::createNetwork(user(), info); + + if (!info.networkId.isValid()) { + qWarning() << qPrintable(tr("CoreSession::createNetwork(): Got invalid networkId from Core when trying to create network %1!").arg(info.networkName)); + return; } - CoreNetwork *net = new CoreNetwork(id, this); - connect(net, SIGNAL(displayMsg(NetworkId, Message::Type, BufferInfo::Type, const QString &, const QString &, const QString &, Message::Flags)), - SLOT(recvMessageFromServer(NetworkId, Message::Type, BufferInfo::Type, const QString &, const QString &, const QString &, Message::Flags))); - connect(net, SIGNAL(displayStatusMsg(QString)), SLOT(recvStatusMsgFromServer(QString))); - connect(net, SIGNAL(disconnected(NetworkId)), SIGNAL(networkDisconnected(NetworkId))); - - net->setNetworkInfo(info); - net->setProxy(signalProxy()); - _networks[id] = net; - signalProxy()->synchronize(net); - emit networkCreated(id); - } else { - qWarning() << qPrintable(tr("CoreSession::createNetwork(): Trying to create a network that already exists, updating instead!")); - _networks[info.networkId]->requestSetNetworkInfo(info); - } -} - -void CoreSession::removeNetwork(NetworkId id) { - // Make sure the network is disconnected! - CoreNetwork *net = network(id); - if(!net) - return; - - if(net->connectionState() != Network::Disconnected) { - // make sure we no longer receive data from the tcp buffer - disconnect(net, SIGNAL(displayMsg(NetworkId, Message::Type, BufferInfo::Type, const QString &, const QString &, const QString &, Message::Flags)), this, 0); - disconnect(net, SIGNAL(displayStatusMsg(QString)), this, 0); - connect(net, SIGNAL(disconnected(NetworkId)), this, SLOT(destroyNetwork(NetworkId))); - net->disconnectFromIrc(); - } else { - destroyNetwork(id); - } -} - -void CoreSession::destroyNetwork(NetworkId id) { - QList removedBuffers = Core::requestBufferIdsForNetwork(user(), id); - Network *net = _networks.take(id); - if(net && Core::removeNetwork(user(), id)) { - // make sure that all unprocessed RawMessages from this network are removed - QList::iterator messageIter = _messageQueue.begin(); - while(messageIter != _messageQueue.end()) { - if(messageIter->networkId == id) { - messageIter = _messageQueue.erase(messageIter); - } else { - messageIter++; - } + id = info.networkId.toInt(); + if (!_networks.contains(id)) { + // create persistent chans + QRegExp rx("\\s*(\\S+)(?:\\s*(\\S+))?\\s*"); + foreach(QString channel, persistentChans) { + if (!rx.exactMatch(channel)) { + qWarning() << QString("Invalid persistent channel declaration: %1").arg(channel); + continue; + } + Core::bufferInfo(user(), info.networkId, BufferInfo::ChannelBuffer, rx.cap(1), true); + Core::setChannelPersistent(user(), info.networkId, rx.cap(1), true); + if (!rx.cap(2).isEmpty()) + Core::setPersistentChannelKey(user(), info.networkId, rx.cap(1), rx.cap(2)); + } + + CoreNetwork *net = new CoreNetwork(id, this); + connect(net, SIGNAL(displayMsg(NetworkId, Message::Type, BufferInfo::Type, const QString &, const QString &, const QString &, Message::Flags)), + SLOT(recvMessageFromServer(NetworkId, Message::Type, BufferInfo::Type, const QString &, const QString &, const QString &, Message::Flags))); + connect(net, SIGNAL(displayStatusMsg(QString)), SLOT(recvStatusMsgFromServer(QString))); + connect(net, SIGNAL(disconnected(NetworkId)), SIGNAL(networkDisconnected(NetworkId))); + + net->setNetworkInfo(info); + net->setProxy(signalProxy()); + _networks[id] = net; + signalProxy()->synchronize(net); + emit networkCreated(id); } - // remove buffers from syncer - foreach(BufferId bufferId, removedBuffers) { - _bufferSyncer->removeBuffer(bufferId); + else { + qWarning() << qPrintable(tr("CoreSession::createNetwork(): Trying to create a network that already exists, updating instead!")); + _networks[info.networkId]->requestSetNetworkInfo(info); } - emit networkRemoved(id); - net->deleteLater(); - } -} - -void CoreSession::renameBuffer(const NetworkId &networkId, const QString &newName, const QString &oldName) { - BufferInfo bufferInfo = Core::bufferInfo(user(), networkId, BufferInfo::QueryBuffer, oldName, false); - if(bufferInfo.isValid()) { - _bufferSyncer->renameBuffer(bufferInfo.bufferId(), newName); - } -} - -void CoreSession::clientsConnected() { - QHash::iterator netIter = _networks.begin(); - Identity *identity = 0; - CoreNetwork *net = 0; - IrcUser *me = 0; - while(netIter != _networks.end()) { - net = *netIter; - netIter++; - - if(!net->isConnected()) - continue; - identity = net->identityPtr(); - if(!identity) - continue; - me = net->me(); - if(!me) - continue; - - if(identity->detachAwayEnabled() && me->isAway()) { - net->userInputHandler()->handleAway(BufferInfo(), QString()); +} + + +void CoreSession::removeNetwork(NetworkId id) +{ + // Make sure the network is disconnected! + CoreNetwork *net = network(id); + if (!net) + return; + + if (net->connectionState() != Network::Disconnected) { + // make sure we no longer receive data from the tcp buffer + disconnect(net, SIGNAL(displayMsg(NetworkId, Message::Type, BufferInfo::Type, const QString &, const QString &, const QString &, Message::Flags)), this, 0); + disconnect(net, SIGNAL(displayStatusMsg(QString)), this, 0); + connect(net, SIGNAL(disconnected(NetworkId)), this, SLOT(destroyNetwork(NetworkId))); + net->disconnectFromIrc(); + } + else { + destroyNetwork(id); + } +} + + +void CoreSession::destroyNetwork(NetworkId id) +{ + QList removedBuffers = Core::requestBufferIdsForNetwork(user(), id); + Network *net = _networks.take(id); + if (net && Core::removeNetwork(user(), id)) { + // make sure that all unprocessed RawMessages from this network are removed + QList::iterator messageIter = _messageQueue.begin(); + while (messageIter != _messageQueue.end()) { + if (messageIter->networkId == id) { + messageIter = _messageQueue.erase(messageIter); + } + else { + messageIter++; + } + } + // remove buffers from syncer + foreach(BufferId bufferId, removedBuffers) { + _bufferSyncer->removeBuffer(bufferId); + } + emit networkRemoved(id); + net->deleteLater(); + } +} + + +void CoreSession::renameBuffer(const NetworkId &networkId, const QString &newName, const QString &oldName) +{ + BufferInfo bufferInfo = Core::bufferInfo(user(), networkId, BufferInfo::QueryBuffer, oldName, false); + if (bufferInfo.isValid()) { + _bufferSyncer->renameBuffer(bufferInfo.bufferId(), newName); } - } -} - -void CoreSession::clientsDisconnected() { - QHash::iterator netIter = _networks.begin(); - Identity *identity = 0; - CoreNetwork *net = 0; - IrcUser *me = 0; - QString awayReason; - while(netIter != _networks.end()) { - net = *netIter; - netIter++; - - if(!net->isConnected()) - continue; - - identity = net->identityPtr(); - if(!identity) - continue; - me = net->me(); - if(!me) - continue; - - if(identity->detachAwayEnabled() && !me->isAway()) { - if(!identity->detachAwayReason().isEmpty()) - awayReason = identity->detachAwayReason(); - net->setAutoAwayActive(true); - net->userInputHandler()->handleAway(BufferInfo(), awayReason); +} + + +void CoreSession::clientsConnected() +{ + QHash::iterator netIter = _networks.begin(); + Identity *identity = 0; + CoreNetwork *net = 0; + IrcUser *me = 0; + while (netIter != _networks.end()) { + net = *netIter; + netIter++; + + if (!net->isConnected()) + continue; + identity = net->identityPtr(); + if (!identity) + continue; + me = net->me(); + if (!me) + continue; + + if (identity->detachAwayEnabled() && me->isAway()) { + net->userInputHandler()->handleAway(BufferInfo(), QString()); + } } - } } -void CoreSession::globalAway(const QString &msg) { - QHash::iterator netIter = _networks.begin(); - CoreNetwork *net = 0; - while(netIter != _networks.end()) { - net = *netIter; - netIter++; +void CoreSession::clientsDisconnected() +{ + QHash::iterator netIter = _networks.begin(); + Identity *identity = 0; + CoreNetwork *net = 0; + IrcUser *me = 0; + QString awayReason; + while (netIter != _networks.end()) { + net = *netIter; + netIter++; + + if (!net->isConnected()) + continue; + + identity = net->identityPtr(); + if (!identity) + continue; + me = net->me(); + if (!me) + continue; + + if (identity->detachAwayEnabled() && !me->isAway()) { + if (!identity->detachAwayReason().isEmpty()) + awayReason = identity->detachAwayReason(); + net->setAutoAwayActive(true); + net->userInputHandler()->handleAway(BufferInfo(), awayReason); + } + } +} - if(!net->isConnected()) - continue; - net->userInputHandler()->issueAway(msg, false /* no force away */); - } +void CoreSession::globalAway(const QString &msg) +{ + QHash::iterator netIter = _networks.begin(); + CoreNetwork *net = 0; + while (netIter != _networks.end()) { + net = *netIter; + netIter++; + + if (!net->isConnected()) + continue; + + net->userInputHandler()->issueAway(msg, false /* no force away */); + } } diff --git a/src/core/coresession.h b/src/core/coresession.h index 8b4305e3..9de37c01 100644 --- a/src/core/coresession.h +++ b/src/core/coresession.h @@ -50,174 +50,176 @@ struct NetworkInfo; class QScriptEngine; -class CoreSession : public QObject { - Q_OBJECT +class CoreSession : public QObject +{ + Q_OBJECT public: - CoreSession(UserId, bool restoreState, QObject *parent = 0); - ~CoreSession(); + CoreSession(UserId, bool restoreState, QObject *parent = 0); + ~CoreSession(); - QList buffers() const; - inline UserId user() const { return _user; } - CoreNetwork *network(NetworkId) const; - CoreIdentity *identity(IdentityId) const; - inline CoreNetworkConfig *networkConfig() const { return _networkConfig; } - NetworkConnection *networkConnection(NetworkId) const; + QList buffers() const; + inline UserId user() const { return _user; } + CoreNetwork *network(NetworkId) const; + CoreIdentity *identity(IdentityId) const; + inline CoreNetworkConfig *networkConfig() const { return _networkConfig; } + NetworkConnection *networkConnection(NetworkId) const; - QVariant sessionState(); + QVariant sessionState(); - inline SignalProxy *signalProxy() const { return _signalProxy; } + inline SignalProxy *signalProxy() const { return _signalProxy; } - const AliasManager &aliasManager() const { return _aliasManager; } - AliasManager &aliasManager() { return _aliasManager; } + const AliasManager &aliasManager() const { return _aliasManager; } + AliasManager &aliasManager() { return _aliasManager; } - inline EventManager *eventManager() const { return _eventManager; } - inline EventStringifier *eventStringifier() const { return _eventStringifier; } - inline CoreSessionEventProcessor *sessionEventProcessor() const { return _sessionEventProcessor; } - inline CtcpParser *ctcpParser() const { return _ctcpParser; } - inline IrcParser *ircParser() const { return _ircParser; } + inline EventManager *eventManager() const { return _eventManager; } + inline EventStringifier *eventStringifier() const { return _eventStringifier; } + inline CoreSessionEventProcessor *sessionEventProcessor() const { return _sessionEventProcessor; } + inline CtcpParser *ctcpParser() const { return _ctcpParser; } + inline IrcParser *ircParser() const { return _ircParser; } - inline CoreIrcListHelper *ircListHelper() const { return _ircListHelper; } + inline CoreIrcListHelper *ircListHelper() const { return _ircListHelper; } - inline CoreIgnoreListManager *ignoreListManager() { return &_ignoreListManager; } + inline CoreIgnoreListManager *ignoreListManager() { return &_ignoreListManager; } // void attachNetworkConnection(NetworkConnection *conn); - //! Return necessary data for restoring the session after restarting the core - void restoreSessionState(); + //! Return necessary data for restoring the session after restarting the core + void restoreSessionState(); public slots: - void addClient(QIODevice *device); - void addClient(SignalProxy *proxy); + void addClient(QIODevice *device); + void addClient(SignalProxy *proxy); - void msgFromClient(BufferInfo, QString message); + void msgFromClient(BufferInfo, QString message); - //! Create an identity and propagate the changes to the clients. - /** \param identity The identity to be created. - */ - void createIdentity(const Identity &identity, const QVariantMap &additional); - void createIdentity(const CoreIdentity &identity); + //! Create an identity and propagate the changes to the clients. + /** \param identity The identity to be created. + */ + void createIdentity(const Identity &identity, const QVariantMap &additional); + void createIdentity(const CoreIdentity &identity); - //! Remove identity and propagate that fact to the clients. - /** \param identity The identity to be removed. - */ - void removeIdentity(IdentityId identity); + //! Remove identity and propagate that fact to the clients. + /** \param identity The identity to be removed. + */ + void removeIdentity(IdentityId identity); - //! Create a network and propagate the changes to the clients. - /** \param info The network's settings. - */ - void createNetwork(const NetworkInfo &info, const QStringList &persistentChannels = QStringList()); + //! Create a network and propagate the changes to the clients. + /** \param info The network's settings. + */ + void createNetwork(const NetworkInfo &info, const QStringList &persistentChannels = QStringList()); - //! Remove network and propagate that fact to the clients. - /** \param network The id of the network to be removed. - */ - void removeNetwork(NetworkId network); + //! Remove network and propagate that fact to the clients. + /** \param network The id of the network to be removed. + */ + void removeNetwork(NetworkId network); - //! Rename a Buffer for a given network - /* \param networkId The id of the network the buffer belongs to - * \param newName The new name of the buffer - * \param oldName The old name of the buffer - */ - void renameBuffer(const NetworkId &networkId, const QString &newName, const QString &oldName); + //! Rename a Buffer for a given network + /* \param networkId The id of the network the buffer belongs to + * \param newName The new name of the buffer + * \param oldName The old name of the buffer + */ + void renameBuffer(const NetworkId &networkId, const QString &newName, const QString &oldName); - QHash persistentChannels(NetworkId) const; + QHash persistentChannels(NetworkId) const; - //! Marks us away (or unaway) on all networks - void globalAway(const QString &msg = QString()); + //! Marks us away (or unaway) on all networks + void globalAway(const QString &msg = QString()); signals: - void initialized(); - void sessionState(const QVariant &); + void initialized(); + void sessionState(const QVariant &); - //void msgFromGui(uint netid, QString buf, QString message); - void displayMsg(Message message); - void displayStatusMsg(QString, QString); + //void msgFromGui(uint netid, QString buf, QString message); + void displayMsg(Message message); + void displayStatusMsg(QString, QString); - void scriptResult(QString result); + void scriptResult(QString result); - //! Identity has been created. - /** This signal is propagated to the clients to tell them that the given identity has been created. - * \param identity The new identity. - */ - void identityCreated(const Identity &identity); + //! Identity has been created. + /** This signal is propagated to the clients to tell them that the given identity has been created. + * \param identity The new identity. + */ + void identityCreated(const Identity &identity); - //! Identity has been removed. - /** This signal is propagated to the clients to inform them about the removal of the given identity. - * \param identity The identity that has been removed. - */ - void identityRemoved(IdentityId identity); + //! Identity has been removed. + /** This signal is propagated to the clients to inform them about the removal of the given identity. + * \param identity The identity that has been removed. + */ + void identityRemoved(IdentityId identity); - void networkCreated(NetworkId); - void networkRemoved(NetworkId); - void networkDisconnected(NetworkId); + void networkCreated(NetworkId); + void networkRemoved(NetworkId); + void networkDisconnected(NetworkId); protected: - virtual void customEvent(QEvent *event); + virtual void customEvent(QEvent *event); private slots: - void removeClient(QIODevice *dev); + void removeClient(QIODevice *dev); - void recvStatusMsgFromServer(QString msg); - void recvMessageFromServer(NetworkId networkId, Message::Type, BufferInfo::Type, const QString &target, const QString &text, const QString &sender = "", Message::Flags flags = Message::None); + void recvStatusMsgFromServer(QString msg); + void recvMessageFromServer(NetworkId networkId, Message::Type, BufferInfo::Type, const QString &target, const QString &text, const QString &sender = "", Message::Flags flags = Message::None); - void destroyNetwork(NetworkId); + void destroyNetwork(NetworkId); - void scriptRequest(QString script); + void scriptRequest(QString script); - void clientsConnected(); - void clientsDisconnected(); + void clientsConnected(); + void clientsDisconnected(); - void updateIdentityBySender(); + void updateIdentityBySender(); - void saveSessionState() const; + void saveSessionState() const; private: - void processMessages(); + void processMessages(); - void loadSettings(); - void initScriptEngine(); + void loadSettings(); + void initScriptEngine(); - /// Hook for converting events to the old displayMsg() handlers - Q_INVOKABLE void processMessageEvent(MessageEvent *event); + /// Hook for converting events to the old displayMsg() handlers + Q_INVOKABLE void processMessageEvent(MessageEvent *event); - UserId _user; + UserId _user; - SignalProxy *_signalProxy; - CoreAliasManager _aliasManager; - // QHash _connections; - QHash _networks; - // QHash _networksToRemove; - QHash _identities; + SignalProxy *_signalProxy; + CoreAliasManager _aliasManager; + // QHash _connections; + QHash _networks; + // QHash _networksToRemove; + QHash _identities; - CoreBufferSyncer *_bufferSyncer; - CoreBacklogManager *_backlogManager; - CoreBufferViewManager *_bufferViewManager; - CoreIrcListHelper *_ircListHelper; - CoreNetworkConfig *_networkConfig; - CoreCoreInfo _coreInfo; + CoreBufferSyncer *_bufferSyncer; + CoreBacklogManager *_backlogManager; + CoreBufferViewManager *_bufferViewManager; + CoreIrcListHelper *_ircListHelper; + CoreNetworkConfig *_networkConfig; + CoreCoreInfo _coreInfo; - EventManager *_eventManager; - EventStringifier *_eventStringifier; // should eventually move into client - CoreSessionEventProcessor *_sessionEventProcessor; - CtcpParser *_ctcpParser; - IrcParser *_ircParser; + EventManager *_eventManager; + EventStringifier *_eventStringifier; // should eventually move into client + CoreSessionEventProcessor *_sessionEventProcessor; + CtcpParser *_ctcpParser; + IrcParser *_ircParser; - QScriptEngine *scriptEngine; + QScriptEngine *scriptEngine; - QList _messageQueue; - bool _processMessages; - CoreIgnoreListManager _ignoreListManager; + QList _messageQueue; + bool _processMessages; + CoreIgnoreListManager _ignoreListManager; }; + struct RawMessage { - NetworkId networkId; - Message::Type type; - BufferInfo::Type bufferType; - QString target; - QString text; - QString sender; - Message::Flags flags; - RawMessage(NetworkId networkId, Message::Type type, BufferInfo::Type bufferType, const QString &target, const QString &text, const QString &sender, Message::Flags flags) - : networkId(networkId), type(type), bufferType(bufferType), target(target), text(text), sender(sender), flags(flags) {} + NetworkId networkId; + Message::Type type; + BufferInfo::Type bufferType; + QString target; + QString text; + QString sender; + Message::Flags flags; + RawMessage(NetworkId networkId, Message::Type type, BufferInfo::Type bufferType, const QString &target, const QString &text, const QString &sender, Message::Flags flags) + : networkId(networkId), type(type), bufferType(bufferType), target(target), text(text), sender(sender), flags(flags) {} }; #endif diff --git a/src/core/coresessioneventprocessor.cpp b/src/core/coresessioneventprocessor.cpp index 1082617c..597f6d29 100644 --- a/src/core/coresessioneventprocessor.cpp +++ b/src/core/coresessioneventprocessor.cpp @@ -31,397 +31,452 @@ #include "quassel.h" CoreSessionEventProcessor::CoreSessionEventProcessor(CoreSession *session) - : BasicHandler("handleCtcp", session), - _coreSession(session) -{ - connect(coreSession(), SIGNAL(networkDisconnected(NetworkId)), this, SLOT(destroyNetsplits(NetworkId))); - connect(this, SIGNAL(newEvent(Event *)), coreSession()->eventManager(), SLOT(postEvent(Event *))); -} - -bool CoreSessionEventProcessor::checkParamCount(IrcEvent *e, int minParams) { - if(e->params().count() < minParams) { - if(e->type() == EventManager::IrcEventNumeric) { - qWarning() << "Command " << static_cast(e)->number() << " requires " << minParams << "params, got: " << e->params(); - } else { - QString name = coreSession()->eventManager()->enumName(e->type()); - qWarning() << qPrintable(name) << "requires" << minParams << "params, got:" << e->params(); - } - e->stop(); - return false; - } - return true; -} - -void CoreSessionEventProcessor::tryNextNick(NetworkEvent *e, const QString &errnick, bool erroneus) { - QStringList desiredNicks = coreSession()->identity(e->network()->identity())->nicks(); - int nextNickIdx = desiredNicks.indexOf(errnick) + 1; - QString nextNick; - if(nextNickIdx > 0 && desiredNicks.size() > nextNickIdx) { - nextNick = desiredNicks[nextNickIdx]; - } else { - if(erroneus) { - // FIXME Make this an ErrorEvent or something like that, so it's translated in the client - MessageEvent *msgEvent = new MessageEvent(Message::Error, e->network(), - tr("No free and valid nicks in nicklist found. use: /nick to continue"), - QString(), QString(), Message::None, e->timestamp()); - emit newEvent(msgEvent); - return; - } else { - nextNick = errnick + "_"; - } - } - // FIXME Use a proper output event for this - coreNetwork(e)->putRawLine("NICK " + coreNetwork(e)->encodeServerString(nextNick)); -} - -void CoreSessionEventProcessor::processIrcEventNumeric(IrcEventNumeric *e) { - switch(e->number()) { - - // CAP stuff - case 903: case 904: case 905: case 906: case 907: - qobject_cast(e->network())->putRawLine("CAP END"); - break; - - default: - break; - } -} - -void CoreSessionEventProcessor::processIrcEventAuthenticate(IrcEvent *e) { - if(!checkParamCount(e, 1)) - return; + : BasicHandler("handleCtcp", session), + _coreSession(session) +{ + connect(coreSession(), SIGNAL(networkDisconnected(NetworkId)), this, SLOT(destroyNetsplits(NetworkId))); + connect(this, SIGNAL(newEvent(Event *)), coreSession()->eventManager(), SLOT(postEvent(Event *))); +} - if(e->params().at(0) != "+") { - qWarning() << "Invalid AUTHENTICATE" << e; - return; - } - CoreNetwork *net = coreNetwork(e); +bool CoreSessionEventProcessor::checkParamCount(IrcEvent *e, int minParams) +{ + if (e->params().count() < minParams) { + if (e->type() == EventManager::IrcEventNumeric) { + qWarning() << "Command " << static_cast(e)->number() << " requires " << minParams << "params, got: " << e->params(); + } + else { + QString name = coreSession()->eventManager()->enumName(e->type()); + qWarning() << qPrintable(name) << "requires" << minParams << "params, got:" << e->params(); + } + e->stop(); + return false; + } + return true; +} + - QString construct = net->saslAccount(); - construct.append(QChar(QChar::Null)); - construct.append(net->saslAccount()); - construct.append(QChar(QChar::Null)); - construct.append(net->saslPassword()); - QByteArray saslData = QByteArray(construct.toAscii().toBase64()); - saslData.prepend("AUTHENTICATE "); - net->putRawLine(saslData); +void CoreSessionEventProcessor::tryNextNick(NetworkEvent *e, const QString &errnick, bool erroneus) +{ + QStringList desiredNicks = coreSession()->identity(e->network()->identity())->nicks(); + int nextNickIdx = desiredNicks.indexOf(errnick) + 1; + QString nextNick; + if (nextNickIdx > 0 && desiredNicks.size() > nextNickIdx) { + nextNick = desiredNicks[nextNickIdx]; + } + else { + if (erroneus) { + // FIXME Make this an ErrorEvent or something like that, so it's translated in the client + MessageEvent *msgEvent = new MessageEvent(Message::Error, e->network(), + tr("No free and valid nicks in nicklist found. use: /nick to continue"), + QString(), QString(), Message::None, e->timestamp()); + emit newEvent(msgEvent); + return; + } + else { + nextNick = errnick + "_"; + } + } + // FIXME Use a proper output event for this + coreNetwork(e)->putRawLine("NICK " + coreNetwork(e)->encodeServerString(nextNick)); } -void CoreSessionEventProcessor::processIrcEventCap(IrcEvent *e) { - // for SASL, there will only be a single param of 'sasl', however you can check here for - // additional CAP messages (ls, multi-prefix, et cetera). - if(e->params().count() == 3) { - if(e->params().at(2) == "sasl") { - // FIXME use event - coreNetwork(e)->putRawLine(coreNetwork(e)->serverEncode("AUTHENTICATE PLAIN")); // Only working with PLAIN atm, blowfish later +void CoreSessionEventProcessor::processIrcEventNumeric(IrcEventNumeric *e) +{ + switch (e->number()) { + // CAP stuff + case 903: + case 904: + case 905: + case 906: + case 907: + qobject_cast(e->network())->putRawLine("CAP END"); + break; + + default: + break; } - } } -void CoreSessionEventProcessor::processIrcEventInvite(IrcEvent *e) { - if(checkParamCount(e, 2)) { - e->network()->updateNickFromMask(e->prefix()); - } + +void CoreSessionEventProcessor::processIrcEventAuthenticate(IrcEvent *e) +{ + if (!checkParamCount(e, 1)) + return; + + if (e->params().at(0) != "+") { + qWarning() << "Invalid AUTHENTICATE" << e; + return; + } + + CoreNetwork *net = coreNetwork(e); + + QString construct = net->saslAccount(); + construct.append(QChar(QChar::Null)); + construct.append(net->saslAccount()); + construct.append(QChar(QChar::Null)); + construct.append(net->saslPassword()); + QByteArray saslData = QByteArray(construct.toAscii().toBase64()); + saslData.prepend("AUTHENTICATE "); + net->putRawLine(saslData); } -void CoreSessionEventProcessor::processIrcEventJoin(IrcEvent *e) { - if(e->testFlag(EventManager::Fake)) // generated by handleEarlyNetsplitJoin - return; - if(!checkParamCount(e, 1)) - return; +void CoreSessionEventProcessor::processIrcEventCap(IrcEvent *e) +{ + // for SASL, there will only be a single param of 'sasl', however you can check here for + // additional CAP messages (ls, multi-prefix, et cetera). + + if (e->params().count() == 3) { + if (e->params().at(2) == "sasl") { + // FIXME use event + coreNetwork(e)->putRawLine(coreNetwork(e)->serverEncode("AUTHENTICATE PLAIN")); // Only working with PLAIN atm, blowfish later + } + } +} + + +void CoreSessionEventProcessor::processIrcEventInvite(IrcEvent *e) +{ + if (checkParamCount(e, 2)) { + e->network()->updateNickFromMask(e->prefix()); + } +} + + +void CoreSessionEventProcessor::processIrcEventJoin(IrcEvent *e) +{ + if (e->testFlag(EventManager::Fake)) // generated by handleEarlyNetsplitJoin + return; + + if (!checkParamCount(e, 1)) + return; - CoreNetwork *net = coreNetwork(e); - QString channel = e->params()[0]; - IrcUser *ircuser = net->updateNickFromMask(e->prefix()); + CoreNetwork *net = coreNetwork(e); + QString channel = e->params()[0]; + IrcUser *ircuser = net->updateNickFromMask(e->prefix()); - bool handledByNetsplit = false; - foreach(Netsplit* n, _netsplits.value(e->network())) { - handledByNetsplit = n->userJoined(e->prefix(), channel); - if(handledByNetsplit) - break; - } + bool handledByNetsplit = false; + foreach(Netsplit* n, _netsplits.value(e->network())) { + handledByNetsplit = n->userJoined(e->prefix(), channel); + if (handledByNetsplit) + break; + } - if(!handledByNetsplit) - ircuser->joinChannel(channel); - else - e->setFlag(EventManager::Netsplit); + if (!handledByNetsplit) + ircuser->joinChannel(channel); + else + e->setFlag(EventManager::Netsplit); - if(net->isMe(ircuser)) { - net->setChannelJoined(channel); - // FIXME use event - net->putRawLine(net->serverEncode("MODE " + channel)); // we want to know the modes of the channel we just joined, so we ask politely - } + if (net->isMe(ircuser)) { + net->setChannelJoined(channel); + // FIXME use event + net->putRawLine(net->serverEncode("MODE " + channel)); // we want to know the modes of the channel we just joined, so we ask politely + } } -void CoreSessionEventProcessor::lateProcessIrcEventKick(IrcEvent *e) { - if(checkParamCount(e, 2)) { - e->network()->updateNickFromMask(e->prefix()); - IrcUser *victim = e->network()->ircUser(e->params().at(1)); - if(victim) { - victim->partChannel(e->params().at(0)); - //if(e->network()->isMe(victim)) e->network()->setKickedFromChannel(channel); + +void CoreSessionEventProcessor::lateProcessIrcEventKick(IrcEvent *e) +{ + if (checkParamCount(e, 2)) { + e->network()->updateNickFromMask(e->prefix()); + IrcUser *victim = e->network()->ircUser(e->params().at(1)); + if (victim) { + victim->partChannel(e->params().at(0)); + //if(e->network()->isMe(victim)) e->network()->setKickedFromChannel(channel); + } } - } } -void CoreSessionEventProcessor::processIrcEventMode(IrcEvent *e) { - if(!checkParamCount(e, 2)) - return; - if(e->network()->isChannelName(e->params().first())) { - // Channel Modes - - IrcChannel *channel = e->network()->ircChannel(e->params()[0]); - if(!channel) { - // we received mode information for a channel we're not in. that means probably we've just been kicked out or something like that - // anyways: we don't have a place to store the data --> discard the info. - return; - } - - QString modes = e->params()[1]; - bool add = true; - int paramOffset = 2; - for(int c = 0; c < modes.length(); c++) { - if(modes[c] == '+') { - add = true; - continue; - } - if(modes[c] == '-') { - add = false; - continue; - } - - if(e->network()->prefixModes().contains(modes[c])) { - // user channel modes (op, voice, etc...) - if(paramOffset < e->params().count()) { - IrcUser *ircUser = e->network()->ircUser(e->params()[paramOffset]); - if(!ircUser) { - qWarning() << Q_FUNC_INFO << "Unknown IrcUser:" << e->params()[paramOffset]; - } else { - if(add) { - bool handledByNetsplit = false; - QHash splits = _netsplits.value(e->network()); - foreach(Netsplit* n, _netsplits.value(e->network())) { - handledByNetsplit = n->userAlreadyJoined(ircUser->hostmask(), channel->name()); - if(handledByNetsplit) { - n->addMode(ircUser->hostmask(), channel->name(), QString(modes[c])); - break; +void CoreSessionEventProcessor::processIrcEventMode(IrcEvent *e) +{ + if (!checkParamCount(e, 2)) + return; + + if (e->network()->isChannelName(e->params().first())) { + // Channel Modes + + IrcChannel *channel = e->network()->ircChannel(e->params()[0]); + if (!channel) { + // we received mode information for a channel we're not in. that means probably we've just been kicked out or something like that + // anyways: we don't have a place to store the data --> discard the info. + return; + } + + QString modes = e->params()[1]; + bool add = true; + int paramOffset = 2; + for (int c = 0; c < modes.length(); c++) { + if (modes[c] == '+') { + add = true; + continue; + } + if (modes[c] == '-') { + add = false; + continue; + } + + if (e->network()->prefixModes().contains(modes[c])) { + // user channel modes (op, voice, etc...) + if (paramOffset < e->params().count()) { + IrcUser *ircUser = e->network()->ircUser(e->params()[paramOffset]); + if (!ircUser) { + qWarning() << Q_FUNC_INFO << "Unknown IrcUser:" << e->params()[paramOffset]; + } + else { + if (add) { + bool handledByNetsplit = false; + QHash splits = _netsplits.value(e->network()); + foreach(Netsplit* n, _netsplits.value(e->network())) { + handledByNetsplit = n->userAlreadyJoined(ircUser->hostmask(), channel->name()); + if (handledByNetsplit) { + n->addMode(ircUser->hostmask(), channel->name(), QString(modes[c])); + break; + } + } + if (!handledByNetsplit) + channel->addUserMode(ircUser, QString(modes[c])); + } + else + channel->removeUserMode(ircUser, QString(modes[c])); + } } - } - if(!handledByNetsplit) - channel->addUserMode(ircUser, QString(modes[c])); + else { + qWarning() << "Received MODE with too few parameters:" << e->params(); + } + ++paramOffset; + } + else { + // regular channel modes + QString value; + Network::ChannelModeType modeType = e->network()->channelModeType(modes[c]); + if (modeType == Network::A_CHANMODE || modeType == Network::B_CHANMODE || (modeType == Network::C_CHANMODE && add)) { + if (paramOffset < e->params().count()) { + value = e->params()[paramOffset]; + } + else { + qWarning() << "Received MODE with too few parameters:" << e->params(); + } + ++paramOffset; + } + + if (add) + channel->addChannelMode(modes[c], value); + else + channel->removeChannelMode(modes[c], value); } - else - channel->removeUserMode(ircUser, QString(modes[c])); - } - } else { - qWarning() << "Received MODE with too few parameters:" << e->params(); } - ++paramOffset; - } else { - // regular channel modes - QString value; - Network::ChannelModeType modeType = e->network()->channelModeType(modes[c]); - if(modeType == Network::A_CHANMODE || modeType == Network::B_CHANMODE || (modeType == Network::C_CHANMODE && add)) { - if(paramOffset < e->params().count()) { - value = e->params()[paramOffset]; - } else { - qWarning() << "Received MODE with too few parameters:" << e->params(); - } - ++paramOffset; + } + else { + // pure User Modes + IrcUser *ircUser = e->network()->newIrcUser(e->params().first()); + QString modeString(e->params()[1]); + QString addModes; + QString removeModes; + bool add = false; + for (int c = 0; c < modeString.count(); c++) { + if (modeString[c] == '+') { + add = true; + continue; + } + if (modeString[c] == '-') { + add = false; + continue; + } + if (add) + addModes += modeString[c]; + else + removeModes += modeString[c]; } + if (!addModes.isEmpty()) + ircUser->addUserModes(addModes); + if (!removeModes.isEmpty()) + ircUser->removeUserModes(removeModes); - if(add) - channel->addChannelMode(modes[c], value); - else - channel->removeChannelMode(modes[c], value); - } - } - - } else { - // pure User Modes - IrcUser *ircUser = e->network()->newIrcUser(e->params().first()); - QString modeString(e->params()[1]); - QString addModes; - QString removeModes; - bool add = false; - for(int c = 0; c < modeString.count(); c++) { - if(modeString[c] == '+') { - add = true; - continue; - } - if(modeString[c] == '-') { - add = false; - continue; - } - if(add) - addModes += modeString[c]; - else - removeModes += modeString[c]; - } - if(!addModes.isEmpty()) - ircUser->addUserModes(addModes); - if(!removeModes.isEmpty()) - ircUser->removeUserModes(removeModes); - - if(e->network()->isMe(ircUser)) { - coreNetwork(e)->updatePersistentModes(addModes, removeModes); - } - } -} - -void CoreSessionEventProcessor::lateProcessIrcEventNick(IrcEvent *e) { - if(checkParamCount(e, 1)) { - IrcUser *ircuser = e->network()->updateNickFromMask(e->prefix()); - if(!ircuser) { - qWarning() << Q_FUNC_INFO << "Unknown IrcUser!"; - return; + if (e->network()->isMe(ircUser)) { + coreNetwork(e)->updatePersistentModes(addModes, removeModes); + } } - QString newnick = e->params().at(0); - QString oldnick = ircuser->nick(); - - // the order is cruicial - // otherwise the client would rename the buffer, see that the assigned ircuser doesn't match anymore - // and remove the ircuser from the querybuffer leading to a wrong on/offline state - ircuser->setNick(newnick); - coreSession()->renameBuffer(e->networkId(), newnick, oldnick); - } } -void CoreSessionEventProcessor::lateProcessIrcEventPart(IrcEvent *e) { - if(checkParamCount(e, 1)) { - IrcUser *ircuser = e->network()->updateNickFromMask(e->prefix()); - if(!ircuser) { - qWarning() << Q_FUNC_INFO<< "Unknown IrcUser!"; - return; + +void CoreSessionEventProcessor::lateProcessIrcEventNick(IrcEvent *e) +{ + if (checkParamCount(e, 1)) { + IrcUser *ircuser = e->network()->updateNickFromMask(e->prefix()); + if (!ircuser) { + qWarning() << Q_FUNC_INFO << "Unknown IrcUser!"; + return; + } + QString newnick = e->params().at(0); + QString oldnick = ircuser->nick(); + + // the order is cruicial + // otherwise the client would rename the buffer, see that the assigned ircuser doesn't match anymore + // and remove the ircuser from the querybuffer leading to a wrong on/offline state + ircuser->setNick(newnick); + coreSession()->renameBuffer(e->networkId(), newnick, oldnick); } - QString channel = e->params().at(0); - ircuser->partChannel(channel); - if(e->network()->isMe(ircuser)) - qobject_cast(e->network())->setChannelParted(channel); - } } -void CoreSessionEventProcessor::processIrcEventPing(IrcEvent *e) { - QString param = e->params().count()? e->params().first() : QString(); - // FIXME use events - coreNetwork(e)->putRawLine("PONG " + coreNetwork(e)->serverEncode(param)); + +void CoreSessionEventProcessor::lateProcessIrcEventPart(IrcEvent *e) +{ + if (checkParamCount(e, 1)) { + IrcUser *ircuser = e->network()->updateNickFromMask(e->prefix()); + if (!ircuser) { + qWarning() << Q_FUNC_INFO<< "Unknown IrcUser!"; + return; + } + QString channel = e->params().at(0); + ircuser->partChannel(channel); + if (e->network()->isMe(ircuser)) + qobject_cast(e->network())->setChannelParted(channel); + } } -void CoreSessionEventProcessor::processIrcEventPong(IrcEvent *e) { - // the server is supposed to send back what we passed as param. and we send a timestamp - // but using quote and whatnought one can send arbitrary pings, so we have to do some sanity checks - if(checkParamCount(e, 2)) { - QString timestamp = e->params().at(1); - QTime sendTime = QTime::fromString(timestamp, "hh:mm:ss.zzz"); - if(sendTime.isValid()) - e->network()->setLatency(sendTime.msecsTo(QTime::currentTime()) / 2); - } + +void CoreSessionEventProcessor::processIrcEventPing(IrcEvent *e) +{ + QString param = e->params().count() ? e->params().first() : QString(); + // FIXME use events + coreNetwork(e)->putRawLine("PONG " + coreNetwork(e)->serverEncode(param)); } -void CoreSessionEventProcessor::processIrcEventQuit(IrcEvent *e) { - IrcUser *ircuser = e->network()->updateNickFromMask(e->prefix()); - if(!ircuser) - return; - QString msg; - if(e->params().count() > 0) - msg = e->params()[0]; - - // check if netsplit - if(Netsplit::isNetsplit(msg)) { - Netsplit *n; - if(!_netsplits[e->network()].contains(msg)) { - n = new Netsplit(e->network(), this); - connect(n, SIGNAL(finished()), this, SLOT(handleNetsplitFinished())); - connect(n, SIGNAL(netsplitJoin(Network*,QString,QStringList,QStringList,QString)), - this, SLOT(handleNetsplitJoin(Network*,QString,QStringList,QStringList,QString))); - connect(n, SIGNAL(netsplitQuit(Network*,QString,QStringList,QString)), - this, SLOT(handleNetsplitQuit(Network*,QString,QStringList,QString))); - connect(n, SIGNAL(earlyJoin(Network*,QString,QStringList,QStringList)), - this, SLOT(handleEarlyNetsplitJoin(Network*,QString,QStringList,QStringList))); - _netsplits[e->network()].insert(msg, n); +void CoreSessionEventProcessor::processIrcEventPong(IrcEvent *e) +{ + // the server is supposed to send back what we passed as param. and we send a timestamp + // but using quote and whatnought one can send arbitrary pings, so we have to do some sanity checks + if (checkParamCount(e, 2)) { + QString timestamp = e->params().at(1); + QTime sendTime = QTime::fromString(timestamp, "hh:mm:ss.zzz"); + if (sendTime.isValid()) + e->network()->setLatency(sendTime.msecsTo(QTime::currentTime()) / 2); } - else { - n = _netsplits[e->network()][msg]; +} + + +void CoreSessionEventProcessor::processIrcEventQuit(IrcEvent *e) +{ + IrcUser *ircuser = e->network()->updateNickFromMask(e->prefix()); + if (!ircuser) + return; + + QString msg; + if (e->params().count() > 0) + msg = e->params()[0]; + + // check if netsplit + if (Netsplit::isNetsplit(msg)) { + Netsplit *n; + if (!_netsplits[e->network()].contains(msg)) { + n = new Netsplit(e->network(), this); + connect(n, SIGNAL(finished()), this, SLOT(handleNetsplitFinished())); + connect(n, SIGNAL(netsplitJoin(Network*, QString, QStringList, QStringList, QString)), + this, SLOT(handleNetsplitJoin(Network*, QString, QStringList, QStringList, QString))); + connect(n, SIGNAL(netsplitQuit(Network*, QString, QStringList, QString)), + this, SLOT(handleNetsplitQuit(Network*, QString, QStringList, QString))); + connect(n, SIGNAL(earlyJoin(Network*, QString, QStringList, QStringList)), + this, SLOT(handleEarlyNetsplitJoin(Network*, QString, QStringList, QStringList))); + _netsplits[e->network()].insert(msg, n); + } + else { + n = _netsplits[e->network()][msg]; + } + // add this user to the netsplit + n->userQuit(e->prefix(), ircuser->channels(), msg); + e->setFlag(EventManager::Netsplit); } - // add this user to the netsplit - n->userQuit(e->prefix(), ircuser->channels(), msg); - e->setFlag(EventManager::Netsplit); - } - // normal quit is handled in lateProcessIrcEventQuit() + // normal quit is handled in lateProcessIrcEventQuit() } -void CoreSessionEventProcessor::lateProcessIrcEventQuit(IrcEvent *e) { - if(e->testFlag(EventManager::Netsplit)) - return; - IrcUser *ircuser = e->network()->updateNickFromMask(e->prefix()); - if(!ircuser) - return; +void CoreSessionEventProcessor::lateProcessIrcEventQuit(IrcEvent *e) +{ + if (e->testFlag(EventManager::Netsplit)) + return; + + IrcUser *ircuser = e->network()->updateNickFromMask(e->prefix()); + if (!ircuser) + return; - ircuser->quit(); + ircuser->quit(); } -void CoreSessionEventProcessor::processIrcEventTopic(IrcEvent *e) { - if(checkParamCount(e, 2)) { - e->network()->updateNickFromMask(e->prefix()); - IrcChannel *channel = e->network()->ircChannel(e->params().at(0)); - if(channel) - channel->setTopic(e->params().at(1)); - } + +void CoreSessionEventProcessor::processIrcEventTopic(IrcEvent *e) +{ + if (checkParamCount(e, 2)) { + e->network()->updateNickFromMask(e->prefix()); + IrcChannel *channel = e->network()->ircChannel(e->params().at(0)); + if (channel) + channel->setTopic(e->params().at(1)); + } } + /* RPL_WELCOME */ -void CoreSessionEventProcessor::processIrcEvent001(IrcEvent *e) { - if(!checkParamCount(e, 1)) - return; +void CoreSessionEventProcessor::processIrcEvent001(IrcEvent *e) +{ + if (!checkParamCount(e, 1)) + return; - QString myhostmask = e->params().at(0).section(' ', -1, -1); - e->network()->setCurrentServer(e->prefix()); - e->network()->setMyNick(nickFromMask(myhostmask)); + QString myhostmask = e->params().at(0).section(' ', -1, -1); + e->network()->setCurrentServer(e->prefix()); + e->network()->setMyNick(nickFromMask(myhostmask)); } + /* RPL_ISUPPORT */ // TODO Complete 005 handling, also use sensible defaults for non-sent stuff -void CoreSessionEventProcessor::processIrcEvent005(IrcEvent *e) { - if(!checkParamCount(e, 1)) - return; - - QString key, value; - for(int i = 0; i < e->params().count() - 1; i++) { - QString key = e->params()[i].section("=", 0, 0); - QString value = e->params()[i].section("=", 1); - e->network()->addSupport(key, value); - } +void CoreSessionEventProcessor::processIrcEvent005(IrcEvent *e) +{ + if (!checkParamCount(e, 1)) + return; + + QString key, value; + for (int i = 0; i < e->params().count() - 1; i++) { + QString key = e->params()[i].section("=", 0, 0); + QString value = e->params()[i].section("=", 1); + e->network()->addSupport(key, value); + } - /* determine our prefixes here to get an accurate result */ - e->network()->determinePrefixes(); + /* determine our prefixes here to get an accurate result */ + e->network()->determinePrefixes(); } + /* RPL_UMODEIS - " []" */ -void CoreSessionEventProcessor::processIrcEvent221(IrcEvent *) { - // TODO: save information in network object +void CoreSessionEventProcessor::processIrcEvent221(IrcEvent *) +{ + // TODO: save information in network object } + /* RPL_STATSCONN - "Highest connection cout: 8000 (7999 clients)" */ -void CoreSessionEventProcessor::processIrcEvent250(IrcEvent *) { - // TODO: save information in network object +void CoreSessionEventProcessor::processIrcEvent250(IrcEvent *) +{ + // TODO: save information in network object } + /* RPL_LOCALUSERS - "Current local user: 5024 Max: 7999 */ -void CoreSessionEventProcessor::processIrcEvent265(IrcEvent *) { - // TODO: save information in network object +void CoreSessionEventProcessor::processIrcEvent265(IrcEvent *) +{ + // TODO: save information in network object } + /* RPL_GLOBALUSERS - "Current global users: 46093 Max: 47650" */ -void CoreSessionEventProcessor::processIrcEvent266(IrcEvent *) { - // TODO: save information in network object +void CoreSessionEventProcessor::processIrcEvent266(IrcEvent *) +{ + // TODO: save information in network object } + /* WHOIS-Message: Replies 311 - 313, 317 - 319 are all replies generated in response to a WHOIS message. @@ -436,284 +491,324 @@ WHOWAS-Message: */ /* RPL_AWAY - " :" */ -void CoreSessionEventProcessor::processIrcEvent301(IrcEvent *e) { - if(!checkParamCount(e, 2)) - return; - - IrcUser *ircuser = e->network()->ircUser(e->params().at(0)); - if(ircuser) { - ircuser->setAway(true); - ircuser->setAwayMessage(e->params().at(1)); - //ircuser->setLastAwayMessage(now); - } +void CoreSessionEventProcessor::processIrcEvent301(IrcEvent *e) +{ + if (!checkParamCount(e, 2)) + return; + + IrcUser *ircuser = e->network()->ircUser(e->params().at(0)); + if (ircuser) { + ircuser->setAway(true); + ircuser->setAwayMessage(e->params().at(1)); + //ircuser->setLastAwayMessage(now); + } } + /* RPL_UNAWAY - ":You are no longer marked as being away" */ -void CoreSessionEventProcessor::processIrcEvent305(IrcEvent *e) { - IrcUser *me = e->network()->me(); - if(me) - me->setAway(false); +void CoreSessionEventProcessor::processIrcEvent305(IrcEvent *e) +{ + IrcUser *me = e->network()->me(); + if (me) + me->setAway(false); - if(e->network()->autoAwayActive()) { - e->network()->setAutoAwayActive(false); - e->setFlag(EventManager::Silent); - } + if (e->network()->autoAwayActive()) { + e->network()->setAutoAwayActive(false); + e->setFlag(EventManager::Silent); + } } + /* RPL_NOWAWAY - ":You have been marked as being away" */ -void CoreSessionEventProcessor::processIrcEvent306(IrcEvent *e) { - IrcUser *me = e->network()->me(); - if(me) - me->setAway(true); +void CoreSessionEventProcessor::processIrcEvent306(IrcEvent *e) +{ + IrcUser *me = e->network()->me(); + if (me) + me->setAway(true); } + /* RPL_WHOISSERVICE - " is registered nick" */ -void CoreSessionEventProcessor::processIrcEvent307(IrcEvent *e) { - if(!checkParamCount(e, 1)) - return; +void CoreSessionEventProcessor::processIrcEvent307(IrcEvent *e) +{ + if (!checkParamCount(e, 1)) + return; - IrcUser *ircuser = e->network()->ircUser(e->params().at(0)); - if(ircuser) - ircuser->setWhoisServiceReply(e->params().join(" ")); + IrcUser *ircuser = e->network()->ircUser(e->params().at(0)); + if (ircuser) + ircuser->setWhoisServiceReply(e->params().join(" ")); } + /* RPL_SUSERHOST - " is available for help." */ -void CoreSessionEventProcessor::processIrcEvent310(IrcEvent *e) { - if(!checkParamCount(e, 1)) - return; +void CoreSessionEventProcessor::processIrcEvent310(IrcEvent *e) +{ + if (!checkParamCount(e, 1)) + return; - IrcUser *ircuser = e->network()->ircUser(e->params().at(0)); - if(ircuser) - ircuser->setSuserHost(e->params().join(" ")); + IrcUser *ircuser = e->network()->ircUser(e->params().at(0)); + if (ircuser) + ircuser->setSuserHost(e->params().join(" ")); } -/* RPL_WHOISUSER - " * :" */ -void CoreSessionEventProcessor::processIrcEvent311(IrcEvent *e) { - if(!checkParamCount(e, 3)) - return; - IrcUser *ircuser = e->network()->ircUser(e->params().at(0)); - if(ircuser) { - ircuser->setUser(e->params().at(1)); - ircuser->setHost(e->params().at(2)); - ircuser->setRealName(e->params().last()); - } +/* RPL_WHOISUSER - " * :" */ +void CoreSessionEventProcessor::processIrcEvent311(IrcEvent *e) +{ + if (!checkParamCount(e, 3)) + return; + + IrcUser *ircuser = e->network()->ircUser(e->params().at(0)); + if (ircuser) { + ircuser->setUser(e->params().at(1)); + ircuser->setHost(e->params().at(2)); + ircuser->setRealName(e->params().last()); + } } + /* RPL_WHOISSERVER - " :" */ -void CoreSessionEventProcessor::processIrcEvent312(IrcEvent *e) { - if(!checkParamCount(e, 2)) - return; +void CoreSessionEventProcessor::processIrcEvent312(IrcEvent *e) +{ + if (!checkParamCount(e, 2)) + return; - IrcUser *ircuser = e->network()->ircUser(e->params().at(0)); - if(ircuser) - ircuser->setServer(e->params().at(1)); + IrcUser *ircuser = e->network()->ircUser(e->params().at(0)); + if (ircuser) + ircuser->setServer(e->params().at(1)); } + /* RPL_WHOISOPERATOR - " :is an IRC operator" */ -void CoreSessionEventProcessor::processIrcEvent313(IrcEvent *e) { - if(!checkParamCount(e, 1)) - return; +void CoreSessionEventProcessor::processIrcEvent313(IrcEvent *e) +{ + if (!checkParamCount(e, 1)) + return; - IrcUser *ircuser = e->network()->ircUser(e->params().at(0)); - if(ircuser) - ircuser->setIrcOperator(e->params().last()); + IrcUser *ircuser = e->network()->ircUser(e->params().at(0)); + if (ircuser) + ircuser->setIrcOperator(e->params().last()); } + /* RPL_ENDOFWHO: " :End of WHO list" */ -void CoreSessionEventProcessor::processIrcEvent315(IrcEvent *e) { - if(!checkParamCount(e, 1)) - return; +void CoreSessionEventProcessor::processIrcEvent315(IrcEvent *e) +{ + if (!checkParamCount(e, 1)) + return; - if(coreNetwork(e)->setAutoWhoDone(e->params()[0])) - e->setFlag(EventManager::Silent); + if (coreNetwork(e)->setAutoWhoDone(e->params()[0])) + e->setFlag(EventManager::Silent); } + /* RPL_WHOISIDLE - " :seconds idle" (real life: " :seconds idle, signon time) */ -void CoreSessionEventProcessor::processIrcEvent317(IrcEvent *e) { - if(!checkParamCount(e, 2)) - return; +void CoreSessionEventProcessor::processIrcEvent317(IrcEvent *e) +{ + if (!checkParamCount(e, 2)) + return; - QDateTime loginTime; + QDateTime loginTime; - int idleSecs = e->params()[1].toInt(); - if(e->params().count() > 3) { // if we have more then 3 params we have the above mentioned "real life" situation - int logintime = e->params()[2].toInt(); - loginTime = QDateTime::fromTime_t(logintime); - } + int idleSecs = e->params()[1].toInt(); + if (e->params().count() > 3) { // if we have more then 3 params we have the above mentioned "real life" situation + int logintime = e->params()[2].toInt(); + loginTime = QDateTime::fromTime_t(logintime); + } - IrcUser *ircuser = e->network()->ircUser(e->params()[0]); - if(ircuser) { - ircuser->setIdleTime(e->timestamp().addSecs(-idleSecs)); - if(loginTime.isValid()) - ircuser->setLoginTime(loginTime); - } + IrcUser *ircuser = e->network()->ircUser(e->params()[0]); + if (ircuser) { + ircuser->setIdleTime(e->timestamp().addSecs(-idleSecs)); + if (loginTime.isValid()) + ircuser->setLoginTime(loginTime); + } } -/* RPL_LIST - " <# visible> :" */ -void CoreSessionEventProcessor::processIrcEvent322(IrcEvent *e) { - if(!checkParamCount(e, 1)) - return; - - QString channelName; - quint32 userCount = 0; - QString topic; - switch(e->params().count()) { - case 3: - topic = e->params()[2]; - case 2: - userCount = e->params()[1].toUInt(); - case 1: - channelName = e->params()[0]; - default: - break; - } - if(coreSession()->ircListHelper()->addChannel(e->networkId(), channelName, userCount, topic)) - e->stop(); // consumed by IrcListHelper, so don't further process/show this event +/* RPL_LIST - " <# visible> :" */ +void CoreSessionEventProcessor::processIrcEvent322(IrcEvent *e) +{ + if (!checkParamCount(e, 1)) + return; + + QString channelName; + quint32 userCount = 0; + QString topic; + + switch (e->params().count()) { + case 3: + topic = e->params()[2]; + case 2: + userCount = e->params()[1].toUInt(); + case 1: + channelName = e->params()[0]; + default: + break; + } + if (coreSession()->ircListHelper()->addChannel(e->networkId(), channelName, userCount, topic)) + e->stop(); // consumed by IrcListHelper, so don't further process/show this event } + /* RPL_LISTEND ":End of LIST" */ -void CoreSessionEventProcessor::processIrcEvent323(IrcEvent *e) { - if(!checkParamCount(e, 1)) - return; +void CoreSessionEventProcessor::processIrcEvent323(IrcEvent *e) +{ + if (!checkParamCount(e, 1)) + return; - if(coreSession()->ircListHelper()->endOfChannelList(e->networkId())) - e->stop(); // consumed by IrcListHelper, so don't further process/show this event + if (coreSession()->ircListHelper()->endOfChannelList(e->networkId())) + e->stop(); // consumed by IrcListHelper, so don't further process/show this event } + /* RPL_CHANNELMODEIS - " " */ -void CoreSessionEventProcessor::processIrcEvent324(IrcEvent *e) { - processIrcEventMode(e); +void CoreSessionEventProcessor::processIrcEvent324(IrcEvent *e) +{ + processIrcEventMode(e); } + /* RPL_NOTOPIC */ -void CoreSessionEventProcessor::processIrcEvent331(IrcEvent *e) { - if(!checkParamCount(e, 1)) - return; +void CoreSessionEventProcessor::processIrcEvent331(IrcEvent *e) +{ + if (!checkParamCount(e, 1)) + return; - IrcChannel *chan = e->network()->ircChannel(e->params()[0]); - if(chan) - chan->setTopic(QString()); + IrcChannel *chan = e->network()->ircChannel(e->params()[0]); + if (chan) + chan->setTopic(QString()); } + /* RPL_TOPIC */ -void CoreSessionEventProcessor::processIrcEvent332(IrcEvent *e) { - if(!checkParamCount(e, 2)) - return; +void CoreSessionEventProcessor::processIrcEvent332(IrcEvent *e) +{ + if (!checkParamCount(e, 2)) + return; - IrcChannel *chan = e->network()->ircChannel(e->params()[0]); - if(chan) - chan->setTopic(e->params()[1]); + IrcChannel *chan = e->network()->ircChannel(e->params()[0]); + if (chan) + chan->setTopic(e->params()[1]); } + /* RPL_WHOREPLY: " ( "H" / "G" > ["*"] [ ( "@" / "+" ) ] : " */ -void CoreSessionEventProcessor::processIrcEvent352(IrcEvent *e) { - if(!checkParamCount(e, 6)) - return; - - QString channel = e->params()[0]; - IrcUser *ircuser = e->network()->ircUser(e->params()[4]); - if(ircuser) { - ircuser->setUser(e->params()[1]); - ircuser->setHost(e->params()[2]); - - bool away = e->params()[5].startsWith("G"); - ircuser->setAway(away); - ircuser->setServer(e->params()[3]); - ircuser->setRealName(e->params().last().section(" ", 1)); - } +void CoreSessionEventProcessor::processIrcEvent352(IrcEvent *e) +{ + if (!checkParamCount(e, 6)) + return; + + QString channel = e->params()[0]; + IrcUser *ircuser = e->network()->ircUser(e->params()[4]); + if (ircuser) { + ircuser->setUser(e->params()[1]); + ircuser->setHost(e->params()[2]); + + bool away = e->params()[5].startsWith("G"); + ircuser->setAway(away); + ircuser->setServer(e->params()[3]); + ircuser->setRealName(e->params().last().section(" ", 1)); + } - if(coreNetwork(e)->isAutoWhoInProgress(channel)) - e->setFlag(EventManager::Silent); + if (coreNetwork(e)->isAutoWhoInProgress(channel)) + e->setFlag(EventManager::Silent); } + /* RPL_NAMREPLY */ -void CoreSessionEventProcessor::processIrcEvent353(IrcEvent *e) { - if(!checkParamCount(e, 3)) - return; +void CoreSessionEventProcessor::processIrcEvent353(IrcEvent *e) +{ + if (!checkParamCount(e, 3)) + return; - // param[0] is either "=", "*" or "@" indicating a public, private or secret channel - // we don't use this information at the time beeing - QString channelname = e->params()[1]; + // param[0] is either "=", "*" or "@" indicating a public, private or secret channel + // we don't use this information at the time beeing + QString channelname = e->params()[1]; - IrcChannel *channel = e->network()->ircChannel(channelname); - if(!channel) { - qWarning() << Q_FUNC_INFO << "Received unknown target channel:" << channelname; - return; - } + IrcChannel *channel = e->network()->ircChannel(channelname); + if (!channel) { + qWarning() << Q_FUNC_INFO << "Received unknown target channel:" << channelname; + return; + } - QStringList nicks; - QStringList modes; + QStringList nicks; + QStringList modes; - foreach(QString nick, e->params()[2].split(' ')) { - QString mode; + foreach(QString nick, e->params()[2].split(' ')) { + QString mode; - if(e->network()->prefixes().contains(nick[0])) { - mode = e->network()->prefixToMode(nick[0]); - nick = nick.mid(1); - } + if (e->network()->prefixes().contains(nick[0])) { + mode = e->network()->prefixToMode(nick[0]); + nick = nick.mid(1); + } - nicks << nick; - modes << mode; - } + nicks << nick; + modes << mode; + } - channel->joinIrcUsers(nicks, modes); + channel->joinIrcUsers(nicks, modes); } -/* ERR_ERRONEUSNICKNAME */ -void CoreSessionEventProcessor::processIrcEvent432(IrcEventNumeric *e) { - if(!checkParamCount(e, 1)) - return; - QString errnick; - if(e->params().count() < 2) { - // handle unreal-ircd bug, where unreal ircd doesnt supply a TARGET in ERR_ERRONEUSNICKNAME during registration phase: - // nick @@@ - // :irc.scortum.moep.net 432 @@@ :Erroneous Nickname: Illegal characters - // correct server reply: - // :irc.scortum.moep.net 432 * @@@ :Erroneous Nickname: Illegal characters - e->params().prepend(e->target()); - e->setTarget("*"); - } - errnick = e->params()[0]; +/* ERR_ERRONEUSNICKNAME */ +void CoreSessionEventProcessor::processIrcEvent432(IrcEventNumeric *e) +{ + if (!checkParamCount(e, 1)) + return; + + QString errnick; + if (e->params().count() < 2) { + // handle unreal-ircd bug, where unreal ircd doesnt supply a TARGET in ERR_ERRONEUSNICKNAME during registration phase: + // nick @@@ + // :irc.scortum.moep.net 432 @@@ :Erroneous Nickname: Illegal characters + // correct server reply: + // :irc.scortum.moep.net 432 * @@@ :Erroneous Nickname: Illegal characters + e->params().prepend(e->target()); + e->setTarget("*"); + } + errnick = e->params()[0]; - tryNextNick(e, errnick, true /* erroneus */); + tryNextNick(e, errnick, true /* erroneus */); } + /* ERR_NICKNAMEINUSE */ -void CoreSessionEventProcessor::processIrcEvent433(IrcEventNumeric *e) { - if(!checkParamCount(e, 1)) - return; +void CoreSessionEventProcessor::processIrcEvent433(IrcEventNumeric *e) +{ + if (!checkParamCount(e, 1)) + return; - QString errnick = e->params().first(); + QString errnick = e->params().first(); - // if there is a problem while connecting to the server -> we handle it - // but only if our connection has not been finished yet... - if(!e->network()->currentServer().isEmpty()) - return; + // if there is a problem while connecting to the server -> we handle it + // but only if our connection has not been finished yet... + if (!e->network()->currentServer().isEmpty()) + return; - tryNextNick(e, errnick); + tryNextNick(e, errnick); } + /* ERR_UNAVAILRESOURCE */ -void CoreSessionEventProcessor::processIrcEvent437(IrcEventNumeric *e) { - if(!checkParamCount(e, 1)) - return; +void CoreSessionEventProcessor::processIrcEvent437(IrcEventNumeric *e) +{ + if (!checkParamCount(e, 1)) + return; - QString errnick = e->params().first(); + QString errnick = e->params().first(); - // if there is a problem while connecting to the server -> we handle it - // but only if our connection has not been finished yet... - if(!e->network()->currentServer().isEmpty()) - return; + // if there is a problem while connecting to the server -> we handle it + // but only if our connection has not been finished yet... + if (!e->network()->currentServer().isEmpty()) + return; - if(!e->network()->isChannelName(errnick)) - tryNextNick(e, errnick); + if (!e->network()->isChannelName(errnick)) + tryNextNick(e, errnick); } + /* template void CoreSessionEventProcessor::processIrcEvent(IrcEvent *e) { if(!checkParamCount(e, 1)) @@ -725,134 +820,156 @@ void CoreSessionEventProcessor::processIrcEvent(IrcEvent *e) { /* Handle signals from Netsplit objects */ void CoreSessionEventProcessor::handleNetsplitJoin(Network *net, - const QString &channel, - const QStringList &users, - const QStringList &modes, - const QString& quitMessage) + const QString &channel, + const QStringList &users, + const QStringList &modes, + const QString &quitMessage) { - IrcChannel *ircChannel = net->ircChannel(channel); - if(!ircChannel) { - return; - } - QList ircUsers; - QStringList newModes = modes; - QStringList newUsers = users; - - foreach(const QString &user, users) { - IrcUser *iu = net->ircUser(nickFromMask(user)); - if(iu) - ircUsers.append(iu); - else { // the user already quit - int idx = users.indexOf(user); - newUsers.removeAt(idx); - newModes.removeAt(idx); - } - } - - ircChannel->joinIrcUsers(ircUsers, newModes); - NetworkSplitEvent *event = new NetworkSplitEvent(EventManager::NetworkSplitJoin, net, channel, newUsers, quitMessage); - emit newEvent(event); -} - -void CoreSessionEventProcessor::handleNetsplitQuit(Network *net, const QString &channel, const QStringList &users, const QString& quitMessage) { - NetworkSplitEvent *event = new NetworkSplitEvent(EventManager::NetworkSplitQuit, net, channel, users, quitMessage); - emit newEvent(event); - foreach(QString user, users) { - IrcUser *iu = net->ircUser(nickFromMask(user)); - if(iu) - iu->quit(); - } -} - -void CoreSessionEventProcessor::handleEarlyNetsplitJoin(Network *net, const QString &channel, const QStringList &users, const QStringList &modes) { - IrcChannel *ircChannel = net->ircChannel(channel); - if(!ircChannel) { - qDebug() << "handleEarlyNetsplitJoin(): channel " << channel << " invalid"; - return; - } - QList events; - QList ircUsers; - QStringList newModes = modes; - - foreach(QString user, users) { - IrcUser *iu = net->updateNickFromMask(user); - if(iu) { - ircUsers.append(iu); - // fake event for scripts that consume join events - events << new IrcEvent(EventManager::IrcEventJoin, net, iu->hostmask(), QStringList() << channel); + IrcChannel *ircChannel = net->ircChannel(channel); + if (!ircChannel) { + return; } - else { - newModes.removeAt(users.indexOf(user)); + QList ircUsers; + QStringList newModes = modes; + QStringList newUsers = users; + + foreach(const QString &user, users) { + IrcUser *iu = net->ircUser(nickFromMask(user)); + if (iu) + ircUsers.append(iu); + else { // the user already quit + int idx = users.indexOf(user); + newUsers.removeAt(idx); + newModes.removeAt(idx); + } } - } - ircChannel->joinIrcUsers(ircUsers, newModes); - foreach(NetworkEvent *event, events) { - event->setFlag(EventManager::Fake); // ignore this in here! + + ircChannel->joinIrcUsers(ircUsers, newModes); + NetworkSplitEvent *event = new NetworkSplitEvent(EventManager::NetworkSplitJoin, net, channel, newUsers, quitMessage); emit newEvent(event); - } } -void CoreSessionEventProcessor::handleNetsplitFinished() { - Netsplit* n = qobject_cast(sender()); - Q_ASSERT(n); - QHash splithash = _netsplits.take(n->network()); - splithash.remove(splithash.key(n)); - if(splithash.count()) - _netsplits[n->network()] = splithash; - n->deleteLater(); + +void CoreSessionEventProcessor::handleNetsplitQuit(Network *net, const QString &channel, const QStringList &users, const QString &quitMessage) +{ + NetworkSplitEvent *event = new NetworkSplitEvent(EventManager::NetworkSplitQuit, net, channel, users, quitMessage); + emit newEvent(event); + foreach(QString user, users) { + IrcUser *iu = net->ircUser(nickFromMask(user)); + if (iu) + iu->quit(); + } } -void CoreSessionEventProcessor::destroyNetsplits(NetworkId netId) { - Network *net = coreSession()->network(netId); - if(!net) - return; - QHash splits = _netsplits.take(net); - qDeleteAll(splits); +void CoreSessionEventProcessor::handleEarlyNetsplitJoin(Network *net, const QString &channel, const QStringList &users, const QStringList &modes) +{ + IrcChannel *ircChannel = net->ircChannel(channel); + if (!ircChannel) { + qDebug() << "handleEarlyNetsplitJoin(): channel " << channel << " invalid"; + return; + } + QList events; + QList ircUsers; + QStringList newModes = modes; + + foreach(QString user, users) { + IrcUser *iu = net->updateNickFromMask(user); + if (iu) { + ircUsers.append(iu); + // fake event for scripts that consume join events + events << new IrcEvent(EventManager::IrcEventJoin, net, iu->hostmask(), QStringList() << channel); + } + else { + newModes.removeAt(users.indexOf(user)); + } + } + ircChannel->joinIrcUsers(ircUsers, newModes); + foreach(NetworkEvent *event, events) { + event->setFlag(EventManager::Fake); // ignore this in here! + emit newEvent(event); + } +} + + +void CoreSessionEventProcessor::handleNetsplitFinished() +{ + Netsplit *n = qobject_cast(sender()); + Q_ASSERT(n); + QHash splithash = _netsplits.take(n->network()); + splithash.remove(splithash.key(n)); + if (splithash.count()) + _netsplits[n->network()] = splithash; + n->deleteLater(); +} + + +void CoreSessionEventProcessor::destroyNetsplits(NetworkId netId) +{ + Network *net = coreSession()->network(netId); + if (!net) + return; + + QHash splits = _netsplits.take(net); + qDeleteAll(splits); } + /*******************************/ /******** CTCP HANDLING ********/ /*******************************/ -void CoreSessionEventProcessor::processCtcpEvent(CtcpEvent *e) { - if(e->testFlag(EventManager::Self)) - return; // ignore ctcp events generated by user input +void CoreSessionEventProcessor::processCtcpEvent(CtcpEvent *e) +{ + if (e->testFlag(EventManager::Self)) + return; // ignore ctcp events generated by user input - if(e->type() != EventManager::CtcpEvent || e->ctcpType() != CtcpEvent::Query) - return; + if (e->type() != EventManager::CtcpEvent || e->ctcpType() != CtcpEvent::Query) + return; - handle(e->ctcpCmd(), Q_ARG(CtcpEvent *, e)); + handle(e->ctcpCmd(), Q_ARG(CtcpEvent *, e)); } -void CoreSessionEventProcessor::defaultHandler(const QString &ctcpCmd, CtcpEvent *e) { - // This handler is only there to avoid warnings for unknown CTCPs - Q_UNUSED(e); - Q_UNUSED(ctcpCmd); + +void CoreSessionEventProcessor::defaultHandler(const QString &ctcpCmd, CtcpEvent *e) +{ + // This handler is only there to avoid warnings for unknown CTCPs + Q_UNUSED(e); + Q_UNUSED(ctcpCmd); } -void CoreSessionEventProcessor::handleCtcpAction(CtcpEvent *e) { - // This handler is only there to feed CLIENTINFO - Q_UNUSED(e); + +void CoreSessionEventProcessor::handleCtcpAction(CtcpEvent *e) +{ + // This handler is only there to feed CLIENTINFO + Q_UNUSED(e); } -void CoreSessionEventProcessor::handleCtcpClientinfo(CtcpEvent *e) { - QStringList supportedHandlers; - foreach(QString handler, providesHandlers()) + +void CoreSessionEventProcessor::handleCtcpClientinfo(CtcpEvent *e) +{ + QStringList supportedHandlers; + foreach(QString handler, providesHandlers()) supportedHandlers << handler.toUpper(); - qSort(supportedHandlers); - e->setReply(supportedHandlers.join(" ")); + qSort(supportedHandlers); + e->setReply(supportedHandlers.join(" ")); } -void CoreSessionEventProcessor::handleCtcpPing(CtcpEvent *e) { - e->setReply(e->param()); + +void CoreSessionEventProcessor::handleCtcpPing(CtcpEvent *e) +{ + e->setReply(e->param()); } -void CoreSessionEventProcessor::handleCtcpTime(CtcpEvent *e) { - e->setReply(QDateTime::currentDateTime().toString()); + +void CoreSessionEventProcessor::handleCtcpTime(CtcpEvent *e) +{ + e->setReply(QDateTime::currentDateTime().toString()); } -void CoreSessionEventProcessor::handleCtcpVersion(CtcpEvent *e) { - e->setReply(QString("Quassel IRC %1 (built on %2) -- http://www.quassel-irc.org") - .arg(Quassel::buildInfo().plainVersionString).arg(Quassel::buildInfo().buildDate)); + +void CoreSessionEventProcessor::handleCtcpVersion(CtcpEvent *e) +{ + e->setReply(QString("Quassel IRC %1 (built on %2) -- http://www.quassel-irc.org") + .arg(Quassel::buildInfo().plainVersionString).arg(Quassel::buildInfo().buildDate)); } diff --git a/src/core/coresessioneventprocessor.h b/src/core/coresessioneventprocessor.h index 9647bc6d..7c4362aa 100644 --- a/src/core/coresessioneventprocessor.h +++ b/src/core/coresessioneventprocessor.h @@ -31,118 +31,120 @@ class IrcEvent; class IrcEventNumeric; class Netsplit; -class CoreSessionEventProcessor : public BasicHandler { - Q_OBJECT +class CoreSessionEventProcessor : public BasicHandler +{ + Q_OBJECT public: - CoreSessionEventProcessor(CoreSession *session); - - inline CoreSession *coreSession() const { return _coreSession; } - - Q_INVOKABLE void processIrcEventNumeric(IrcEventNumeric *event); - - Q_INVOKABLE void processIrcEventAuthenticate(IrcEvent *event); // SASL auth - Q_INVOKABLE void processIrcEventCap(IrcEvent *event); // CAP framework - Q_INVOKABLE void processIrcEventInvite(IrcEvent *event); - Q_INVOKABLE void processIrcEventJoin(IrcEvent *event); - Q_INVOKABLE void lateProcessIrcEventKick(IrcEvent *event); - Q_INVOKABLE void processIrcEventMode(IrcEvent *event); - Q_INVOKABLE void lateProcessIrcEventNick(IrcEvent *event); - Q_INVOKABLE void lateProcessIrcEventPart(IrcEvent *event); - Q_INVOKABLE void processIrcEventPing(IrcEvent *event); - Q_INVOKABLE void processIrcEventPong(IrcEvent *event); - Q_INVOKABLE void processIrcEventQuit(IrcEvent *event); - Q_INVOKABLE void lateProcessIrcEventQuit(IrcEvent *event); - Q_INVOKABLE void processIrcEventTopic(IrcEvent *event); - - Q_INVOKABLE void processIrcEvent001(IrcEvent *event); // RPL_WELCOME - Q_INVOKABLE void processIrcEvent005(IrcEvent *event); // RPL_ISUPPORT - Q_INVOKABLE void processIrcEvent221(IrcEvent *event); // RPL_UMODEIS - Q_INVOKABLE void processIrcEvent250(IrcEvent *event); // RPL_STATSCONN - Q_INVOKABLE void processIrcEvent265(IrcEvent *event); // RPL_LOCALUSERS - Q_INVOKABLE void processIrcEvent266(IrcEvent *event); // RPL_GLOBALUSERS - Q_INVOKABLE void processIrcEvent301(IrcEvent *event); // RPL_AWAY - Q_INVOKABLE void processIrcEvent305(IrcEvent *event); // RPL_UNAWAY - Q_INVOKABLE void processIrcEvent306(IrcEvent *event); // RPL_NOWAWAY - Q_INVOKABLE void processIrcEvent307(IrcEvent *event); // RPL_WHOISSERVICE - Q_INVOKABLE void processIrcEvent310(IrcEvent *event); // RPL_SUSERHOST - Q_INVOKABLE void processIrcEvent311(IrcEvent *event); // RPL_WHOISUSER - Q_INVOKABLE void processIrcEvent312(IrcEvent *event); // RPL_WHOISSERVER - Q_INVOKABLE void processIrcEvent313(IrcEvent *event); // RPL_WHOISOPERATOR - Q_INVOKABLE void processIrcEvent315(IrcEvent *event); // RPL_ENDOFWHO - Q_INVOKABLE void processIrcEvent317(IrcEvent *event); // RPL_WHOISIDLE - Q_INVOKABLE void processIrcEvent322(IrcEvent *event); // RPL_LIST - Q_INVOKABLE void processIrcEvent323(IrcEvent *event); // RPL_LISTEND - Q_INVOKABLE void processIrcEvent324(IrcEvent *event); // RPL_CHANNELMODEIS - Q_INVOKABLE void processIrcEvent331(IrcEvent *event); // RPL_NOTOPIC - Q_INVOKABLE void processIrcEvent332(IrcEvent *event); // RPL_TOPIC - Q_INVOKABLE void processIrcEvent352(IrcEvent *event); // RPL_WHOREPLY - Q_INVOKABLE void processIrcEvent353(IrcEvent *event); // RPL_NAMREPLY - Q_INVOKABLE void processIrcEvent432(IrcEventNumeric *event); // ERR_ERRONEUSNICKNAME - Q_INVOKABLE void processIrcEvent433(IrcEventNumeric *event); // ERR_NICKNAMEINUSE - Q_INVOKABLE void processIrcEvent437(IrcEventNumeric *event); // ERR_UNAVAILRESOURCE - - // Q_INVOKABLE void processIrcEvent(IrcEvent *event); - - /* CTCP handlers */ - Q_INVOKABLE void processCtcpEvent(CtcpEvent *event); - - Q_INVOKABLE void handleCtcpAction(CtcpEvent *event); - Q_INVOKABLE void handleCtcpClientinfo(CtcpEvent *event); - Q_INVOKABLE void handleCtcpPing(CtcpEvent *event); - Q_INVOKABLE void handleCtcpTime(CtcpEvent *event); - Q_INVOKABLE void handleCtcpVersion(CtcpEvent *event); - Q_INVOKABLE void defaultHandler(const QString &ctcpCmd, CtcpEvent *event); + CoreSessionEventProcessor(CoreSession *session); + + inline CoreSession *coreSession() const { return _coreSession; } + + Q_INVOKABLE void processIrcEventNumeric(IrcEventNumeric *event); + + Q_INVOKABLE void processIrcEventAuthenticate(IrcEvent *event); // SASL auth + Q_INVOKABLE void processIrcEventCap(IrcEvent *event); // CAP framework + Q_INVOKABLE void processIrcEventInvite(IrcEvent *event); + Q_INVOKABLE void processIrcEventJoin(IrcEvent *event); + Q_INVOKABLE void lateProcessIrcEventKick(IrcEvent *event); + Q_INVOKABLE void processIrcEventMode(IrcEvent *event); + Q_INVOKABLE void lateProcessIrcEventNick(IrcEvent *event); + Q_INVOKABLE void lateProcessIrcEventPart(IrcEvent *event); + Q_INVOKABLE void processIrcEventPing(IrcEvent *event); + Q_INVOKABLE void processIrcEventPong(IrcEvent *event); + Q_INVOKABLE void processIrcEventQuit(IrcEvent *event); + Q_INVOKABLE void lateProcessIrcEventQuit(IrcEvent *event); + Q_INVOKABLE void processIrcEventTopic(IrcEvent *event); + + Q_INVOKABLE void processIrcEvent001(IrcEvent *event); // RPL_WELCOME + Q_INVOKABLE void processIrcEvent005(IrcEvent *event); // RPL_ISUPPORT + Q_INVOKABLE void processIrcEvent221(IrcEvent *event); // RPL_UMODEIS + Q_INVOKABLE void processIrcEvent250(IrcEvent *event); // RPL_STATSCONN + Q_INVOKABLE void processIrcEvent265(IrcEvent *event); // RPL_LOCALUSERS + Q_INVOKABLE void processIrcEvent266(IrcEvent *event); // RPL_GLOBALUSERS + Q_INVOKABLE void processIrcEvent301(IrcEvent *event); // RPL_AWAY + Q_INVOKABLE void processIrcEvent305(IrcEvent *event); // RPL_UNAWAY + Q_INVOKABLE void processIrcEvent306(IrcEvent *event); // RPL_NOWAWAY + Q_INVOKABLE void processIrcEvent307(IrcEvent *event); // RPL_WHOISSERVICE + Q_INVOKABLE void processIrcEvent310(IrcEvent *event); // RPL_SUSERHOST + Q_INVOKABLE void processIrcEvent311(IrcEvent *event); // RPL_WHOISUSER + Q_INVOKABLE void processIrcEvent312(IrcEvent *event); // RPL_WHOISSERVER + Q_INVOKABLE void processIrcEvent313(IrcEvent *event); // RPL_WHOISOPERATOR + Q_INVOKABLE void processIrcEvent315(IrcEvent *event); // RPL_ENDOFWHO + Q_INVOKABLE void processIrcEvent317(IrcEvent *event); // RPL_WHOISIDLE + Q_INVOKABLE void processIrcEvent322(IrcEvent *event); // RPL_LIST + Q_INVOKABLE void processIrcEvent323(IrcEvent *event); // RPL_LISTEND + Q_INVOKABLE void processIrcEvent324(IrcEvent *event); // RPL_CHANNELMODEIS + Q_INVOKABLE void processIrcEvent331(IrcEvent *event); // RPL_NOTOPIC + Q_INVOKABLE void processIrcEvent332(IrcEvent *event); // RPL_TOPIC + Q_INVOKABLE void processIrcEvent352(IrcEvent *event); // RPL_WHOREPLY + Q_INVOKABLE void processIrcEvent353(IrcEvent *event); // RPL_NAMREPLY + Q_INVOKABLE void processIrcEvent432(IrcEventNumeric *event); // ERR_ERRONEUSNICKNAME + Q_INVOKABLE void processIrcEvent433(IrcEventNumeric *event); // ERR_NICKNAMEINUSE + Q_INVOKABLE void processIrcEvent437(IrcEventNumeric *event); // ERR_UNAVAILRESOURCE + + // Q_INVOKABLE void processIrcEvent(IrcEvent *event); + + /* CTCP handlers */ + Q_INVOKABLE void processCtcpEvent(CtcpEvent *event); + + Q_INVOKABLE void handleCtcpAction(CtcpEvent *event); + Q_INVOKABLE void handleCtcpClientinfo(CtcpEvent *event); + Q_INVOKABLE void handleCtcpPing(CtcpEvent *event); + Q_INVOKABLE void handleCtcpTime(CtcpEvent *event); + Q_INVOKABLE void handleCtcpVersion(CtcpEvent *event); + Q_INVOKABLE void defaultHandler(const QString &ctcpCmd, CtcpEvent *event); signals: - void newEvent(Event *event); + void newEvent(Event *event); protected: - bool checkParamCount(IrcEvent *event, int minParams); - inline CoreNetwork *coreNetwork(NetworkEvent *e) const { return qobject_cast(e->network()); } - void tryNextNick(NetworkEvent *e, const QString &errnick, bool erroneous = false); + bool checkParamCount(IrcEvent *event, int minParams); + inline CoreNetwork *coreNetwork(NetworkEvent *e) const { return qobject_cast(e->network()); } + void tryNextNick(NetworkEvent *e, const QString &errnick, bool erroneous = false); private slots: - //! Joins after a netsplit - /** This slot handles a bulk-join after a netsplit is over - * \param net The network - * \param channel The channel the users joined - * \param users The list of users that joind the channel - * \param modes The list of modes the users get set - * \param quitMessage The message we received when the netsplit occured - */ - void handleNetsplitJoin(Network *net, const QString &channel, const QStringList &users, const QStringList &modes, const QString &quitMessage); - - //! Quits after a netsplit - /** This slot handles a bulk-quit after a netsplit occured - * \param net The network - * \param channel The channel the users quitted - * \param users The list of users that got split - * \param quitMessage The message we received when the netsplit occured - */ - void handleNetsplitQuit(Network *net, const QString &channel, const QStringList &users, const QString &quitMessage); - - //! Netsplit finished - /** This slot deletes the netsplit object that sent the finished() signal - */ - void handleNetsplitFinished(); - - void handleEarlyNetsplitJoin(Network *net, const QString &channel, const QStringList &users, const QStringList &modes); - - //! Destroy any existing netsplits - /** This slot deletes all netsplit objects - * Used to get rid of existing netsplits on network reconnect - * \param network The network we want to clear - */ - void destroyNetsplits(NetworkId network); + //! Joins after a netsplit + /** This slot handles a bulk-join after a netsplit is over + * \param net The network + * \param channel The channel the users joined + * \param users The list of users that joind the channel + * \param modes The list of modes the users get set + * \param quitMessage The message we received when the netsplit occured + */ + void handleNetsplitJoin(Network *net, const QString &channel, const QStringList &users, const QStringList &modes, const QString &quitMessage); + + //! Quits after a netsplit + /** This slot handles a bulk-quit after a netsplit occured + * \param net The network + * \param channel The channel the users quitted + * \param users The list of users that got split + * \param quitMessage The message we received when the netsplit occured + */ + void handleNetsplitQuit(Network *net, const QString &channel, const QStringList &users, const QString &quitMessage); + + //! Netsplit finished + /** This slot deletes the netsplit object that sent the finished() signal + */ + void handleNetsplitFinished(); + + void handleEarlyNetsplitJoin(Network *net, const QString &channel, const QStringList &users, const QStringList &modes); + + //! Destroy any existing netsplits + /** This slot deletes all netsplit objects + * Used to get rid of existing netsplits on network reconnect + * \param network The network we want to clear + */ + void destroyNetsplits(NetworkId network); private: - CoreSession *_coreSession; + CoreSession *_coreSession; - // structure to organize netsplits - // key: quit message - // value: the corresponding netsplit object - QHash > _netsplits; + // structure to organize netsplits + // key: quit message + // value: the corresponding netsplit object + QHash > _netsplits; }; + #endif diff --git a/src/core/coresettings.cpp b/src/core/coresettings.cpp index a08fc445..d35b9ccf 100644 --- a/src/core/coresettings.cpp +++ b/src/core/coresettings.cpp @@ -22,30 +22,42 @@ #include "quassel.h" -CoreSettings::CoreSettings(const QString group) : Settings(group, Quassel::buildInfo().coreApplicationName) { - +CoreSettings::CoreSettings(const QString group) : Settings(group, Quassel::buildInfo().coreApplicationName) +{ } -CoreSettings::~CoreSettings() { + +CoreSettings::~CoreSettings() +{ } -void CoreSettings::setStorageSettings(const QVariant &data) { - setLocalValue("StorageSettings", data); + +void CoreSettings::setStorageSettings(const QVariant &data) +{ + setLocalValue("StorageSettings", data); } -QVariant CoreSettings::storageSettings(const QVariant &def) { - return localValue("StorageSettings", def); + +QVariant CoreSettings::storageSettings(const QVariant &def) +{ + return localValue("StorageSettings", def); } + // FIXME remove -QVariant CoreSettings::oldDbSettings() { - return localValue("DatabaseSettings"); +QVariant CoreSettings::oldDbSettings() +{ + return localValue("DatabaseSettings"); } -void CoreSettings::setCoreState(const QVariant &data) { - setLocalValue("CoreState", data); + +void CoreSettings::setCoreState(const QVariant &data) +{ + setLocalValue("CoreState", data); } -QVariant CoreSettings::coreState(const QVariant &def) { - return localValue("CoreState", def); + +QVariant CoreSettings::coreState(const QVariant &def) +{ + return localValue("CoreState", def); } diff --git a/src/core/coresettings.h b/src/core/coresettings.h index 70e16075..80d4ec15 100644 --- a/src/core/coresettings.h +++ b/src/core/coresettings.h @@ -23,9 +23,9 @@ #include "settings.h" -class CoreSettings : public Settings { - - public: +class CoreSettings : public Settings +{ +public: virtual ~CoreSettings(); CoreSettings(const QString group = "Core"); @@ -36,7 +36,7 @@ class CoreSettings : public Settings { void setCoreState(const QVariant &data); QVariant coreState(const QVariant &def = QVariant()); - }; + #endif /*_CORESETTINGS_H_*/ diff --git a/src/core/coreuserinputhandler.cpp b/src/core/coreuserinputhandler.cpp index 0f0be89a..5783bdcb 100644 --- a/src/core/coreuserinputhandler.cpp +++ b/src/core/coreuserinputhandler.cpp @@ -30,703 +30,800 @@ #endif CoreUserInputHandler::CoreUserInputHandler(CoreNetwork *parent) - : CoreBasicHandler(parent) + : CoreBasicHandler(parent) { } -void CoreUserInputHandler::handleUserInput(const BufferInfo &bufferInfo, const QString &msg) { - if(msg.isEmpty()) - return; - AliasManager::CommandList list = coreSession()->aliasManager().processInput(bufferInfo, msg); +void CoreUserInputHandler::handleUserInput(const BufferInfo &bufferInfo, const QString &msg) +{ + if (msg.isEmpty()) + return; + + AliasManager::CommandList list = coreSession()->aliasManager().processInput(bufferInfo, msg); - for(int i = 0; i < list.count(); i++) { - QString cmd = list.at(i).second.section(' ', 0, 0).remove(0, 1).toUpper(); - QString payload = list.at(i).second.section(' ', 1); - handle(cmd, Q_ARG(BufferInfo, list.at(i).first), Q_ARG(QString, payload)); - } + for (int i = 0; i < list.count(); i++) { + QString cmd = list.at(i).second.section(' ', 0, 0).remove(0, 1).toUpper(); + QString payload = list.at(i).second.section(' ', 1); + handle(cmd, Q_ARG(BufferInfo, list.at(i).first), Q_ARG(QString, payload)); + } } + // ==================== // Public Slots // ==================== -void CoreUserInputHandler::handleAway(const BufferInfo &bufferInfo, const QString &msg) { - Q_UNUSED(bufferInfo) - if(msg.startsWith("-all")) { - if(msg.length() == 4) { - coreSession()->globalAway(); - return; - } - Q_ASSERT(msg.length() > 4); - if(msg[4] == ' ') { - coreSession()->globalAway(msg.mid(5)); - return; +void CoreUserInputHandler::handleAway(const BufferInfo &bufferInfo, const QString &msg) +{ + Q_UNUSED(bufferInfo) + if (msg.startsWith("-all")) { + if (msg.length() == 4) { + coreSession()->globalAway(); + return; + } + Q_ASSERT(msg.length() > 4); + if (msg[4] == ' ') { + coreSession()->globalAway(msg.mid(5)); + return; + } } - } - issueAway(msg); -} - -void CoreUserInputHandler::issueAway(const QString &msg, bool autoCheck) { - QString awayMsg = msg; - IrcUser *me = network()->me(); - - // if there is no message supplied we have to check if we are already away or not - if(autoCheck && msg.isEmpty()) { - if(me && !me->isAway()) { - Identity *identity = network()->identityPtr(); - if(identity) { - awayMsg = identity->awayReason(); - } - if(awayMsg.isEmpty()) { - awayMsg = tr("away"); - } + issueAway(msg); +} + + +void CoreUserInputHandler::issueAway(const QString &msg, bool autoCheck) +{ + QString awayMsg = msg; + IrcUser *me = network()->me(); + + // if there is no message supplied we have to check if we are already away or not + if (autoCheck && msg.isEmpty()) { + if (me && !me->isAway()) { + Identity *identity = network()->identityPtr(); + if (identity) { + awayMsg = identity->awayReason(); + } + if (awayMsg.isEmpty()) { + awayMsg = tr("away"); + } + } } - } - if(me) - me->setAwayMessage(awayMsg); + if (me) + me->setAwayMessage(awayMsg); - putCmd("AWAY", serverEncode(awayMsg)); + putCmd("AWAY", serverEncode(awayMsg)); } -void CoreUserInputHandler::handleBan(const BufferInfo &bufferInfo, const QString &msg) { - banOrUnban(bufferInfo, msg, true); + +void CoreUserInputHandler::handleBan(const BufferInfo &bufferInfo, const QString &msg) +{ + banOrUnban(bufferInfo, msg, true); } -void CoreUserInputHandler::handleUnban(const BufferInfo &bufferInfo, const QString &msg) { - banOrUnban(bufferInfo, msg, false); + +void CoreUserInputHandler::handleUnban(const BufferInfo &bufferInfo, const QString &msg) +{ + banOrUnban(bufferInfo, msg, false); } -void CoreUserInputHandler::banOrUnban(const BufferInfo &bufferInfo, const QString &msg, bool ban) { - QString banChannel; - QString banUser; - QStringList params = msg.split(" "); +void CoreUserInputHandler::banOrUnban(const BufferInfo &bufferInfo, const QString &msg, bool ban) +{ + QString banChannel; + QString banUser; - if(!params.isEmpty() && isChannelName(params[0])) { - banChannel = params.takeFirst(); - } else if(bufferInfo.type() == BufferInfo::ChannelBuffer) { - banChannel = bufferInfo.bufferName(); - } else { - emit displayMsg(Message::Error, BufferInfo::StatusBuffer, "", QString("Error: channel unknown in command: /BAN %1").arg(msg)); - return; - } + QStringList params = msg.split(" "); - if(!params.isEmpty() && !params.contains("!") && network()->ircUser(params[0])) { - IrcUser *ircuser = network()->ircUser(params[0]); - // generalizedHost changes to *!ident@*.sld.tld. - QString generalizedHost = ircuser->host(); - if(generalizedHost.isEmpty()) { - emit displayMsg(Message::Error, BufferInfo::StatusBuffer, "", QString("Error: host unknown in command: /BAN %1").arg(msg)); - return; + if (!params.isEmpty() && isChannelName(params[0])) { + banChannel = params.takeFirst(); + } + else if (bufferInfo.type() == BufferInfo::ChannelBuffer) { + banChannel = bufferInfo.bufferName(); + } + else { + emit displayMsg(Message::Error, BufferInfo::StatusBuffer, "", QString("Error: channel unknown in command: /BAN %1").arg(msg)); + return; } - static QRegExp ipAddress("\\d+\\.\\d+\\.\\d+\\.\\d+"); - if(ipAddress.exactMatch(generalizedHost)) { - int lastDotPos = generalizedHost.lastIndexOf('.') + 1; - generalizedHost.replace(lastDotPos, generalizedHost.length() - lastDotPos, '*'); - } else if(generalizedHost.lastIndexOf(".") != -1 && generalizedHost.lastIndexOf(".", generalizedHost.lastIndexOf(".")-1) != -1) { - int secondLastPeriodPosition = generalizedHost.lastIndexOf(".", generalizedHost.lastIndexOf(".")-1); - generalizedHost.replace(0, secondLastPeriodPosition, "*"); + if (!params.isEmpty() && !params.contains("!") && network()->ircUser(params[0])) { + IrcUser *ircuser = network()->ircUser(params[0]); + // generalizedHost changes to *!ident@*.sld.tld. + QString generalizedHost = ircuser->host(); + if (generalizedHost.isEmpty()) { + emit displayMsg(Message::Error, BufferInfo::StatusBuffer, "", QString("Error: host unknown in command: /BAN %1").arg(msg)); + return; + } + + static QRegExp ipAddress("\\d+\\.\\d+\\.\\d+\\.\\d+"); + if (ipAddress.exactMatch(generalizedHost)) { + int lastDotPos = generalizedHost.lastIndexOf('.') + 1; + generalizedHost.replace(lastDotPos, generalizedHost.length() - lastDotPos, '*'); + } + else if (generalizedHost.lastIndexOf(".") != -1 && generalizedHost.lastIndexOf(".", generalizedHost.lastIndexOf(".")-1) != -1) { + int secondLastPeriodPosition = generalizedHost.lastIndexOf(".", generalizedHost.lastIndexOf(".")-1); + generalizedHost.replace(0, secondLastPeriodPosition, "*"); + } + banUser = QString("*!%1@%2").arg(ircuser->user(), generalizedHost); + } + else { + banUser = params.join(" "); } - banUser = QString("*!%1@%2").arg(ircuser->user(), generalizedHost); - } else { - banUser = params.join(" "); - } - QString banMode = ban ? "+b" : "-b"; - QString banMsg = QString("MODE %1 %2 %3").arg(banChannel, banMode, banUser); - emit putRawLine(serverEncode(banMsg)); + QString banMode = ban ? "+b" : "-b"; + QString banMsg = QString("MODE %1 %2 %3").arg(banChannel, banMode, banUser); + emit putRawLine(serverEncode(banMsg)); } -void CoreUserInputHandler::handleCtcp(const BufferInfo &bufferInfo, const QString &msg) { - Q_UNUSED(bufferInfo) - QString nick = msg.section(' ', 0, 0); - QString ctcpTag = msg.section(' ', 1, 1).toUpper(); - if(ctcpTag.isEmpty()) - return; +void CoreUserInputHandler::handleCtcp(const BufferInfo &bufferInfo, const QString &msg) +{ + Q_UNUSED(bufferInfo) + + QString nick = msg.section(' ', 0, 0); + QString ctcpTag = msg.section(' ', 1, 1).toUpper(); + if (ctcpTag.isEmpty()) + return; - QString message = msg.section(' ', 2); - QString verboseMessage = tr("sending CTCP-%1 request to %2").arg(ctcpTag).arg(nick); + QString message = msg.section(' ', 2); + QString verboseMessage = tr("sending CTCP-%1 request to %2").arg(ctcpTag).arg(nick); - if(ctcpTag == "PING") { - uint now = QDateTime::currentDateTime().toTime_t(); - message = QString::number(now); - } + if (ctcpTag == "PING") { + uint now = QDateTime::currentDateTime().toTime_t(); + message = QString::number(now); + } - // FIXME make this a proper event - coreNetwork()->coreSession()->ctcpParser()->query(coreNetwork(), nick, ctcpTag, message); - emit displayMsg(Message::Action, BufferInfo::StatusBuffer, "", verboseMessage, network()->myNick()); + // FIXME make this a proper event + coreNetwork()->coreSession()->ctcpParser()->query(coreNetwork(), nick, ctcpTag, message); + emit displayMsg(Message::Action, BufferInfo::StatusBuffer, "", verboseMessage, network()->myNick()); } -void CoreUserInputHandler::handleDelkey(const BufferInfo &bufferInfo, const QString &msg) { + +void CoreUserInputHandler::handleDelkey(const BufferInfo &bufferInfo, const QString &msg) +{ #ifdef HAVE_QCA2 - if(!bufferInfo.isValid()) - return; + if (!bufferInfo.isValid()) + return; - if(!Cipher::neededFeaturesAvailable()) - return; + if (!Cipher::neededFeaturesAvailable()) + return; - QStringList parms = msg.split(' ', QString::SkipEmptyParts); + QStringList parms = msg.split(' ', QString::SkipEmptyParts); - if(parms.isEmpty() && !bufferInfo.bufferName().isEmpty()) - parms.prepend(bufferInfo.bufferName()); + if (parms.isEmpty() && !bufferInfo.bufferName().isEmpty()) + parms.prepend(bufferInfo.bufferName()); - if(parms.isEmpty()) { - emit displayMsg(Message::Info, bufferInfo.bufferName(), "", - tr("[usage] /delkey deletes the encryption key for nick or channel or just /delkey when in a channel or query.")); - return; - } + if (parms.isEmpty()) { + emit displayMsg(Message::Info, bufferInfo.bufferName(), "", + tr("[usage] /delkey deletes the encryption key for nick or channel or just /delkey when in a channel or query.")); + return; + } - QString target = parms.at(0); + QString target = parms.at(0); - if(network()->cipherKey(target).isEmpty()) { - emit displayMsg(Message::Info, bufferInfo.bufferName(), tr("No key has been set for %1.").arg(target)); - return; - } + if (network()->cipherKey(target).isEmpty()) { + emit displayMsg(Message::Info, bufferInfo.bufferName(), tr("No key has been set for %1.").arg(target)); + return; + } - network()->setCipherKey(target, QByteArray()); + network()->setCipherKey(target, QByteArray()); - if(network()->isChannelName(target) && network()->channels().contains(target)) { - qobject_cast(network()->ircChannel(target))->setEncrypted(false); - } - else if(network()->nicks().contains(target)) { - qobject_cast(network()->ircUser(target))->setEncrypted(false); - } + if (network()->isChannelName(target) && network()->channels().contains(target)) { + qobject_cast(network()->ircChannel(target))->setEncrypted(false); + } + else if (network()->nicks().contains(target)) { + qobject_cast(network()->ircUser(target))->setEncrypted(false); + } - emit displayMsg(Message::Info, bufferInfo.bufferName(), tr("The key for %1 has been deleted.").arg(target)); + emit displayMsg(Message::Info, bufferInfo.bufferName(), tr("The key for %1 has been deleted.").arg(target)); #else - Q_UNUSED(msg) - emit displayMsg(Message::Error, bufferInfo.bufferName(), "", tr("Error: Setting an encryption key requires Quassel to have been built " - "with support for the Qt Cryptographic Architecture (QCA2) library. " - "Contact your distributor about a Quassel package with QCA2 " - "support, or rebuild Quassel with QCA2 present.")); + Q_UNUSED(msg) + emit displayMsg(Message::Error, bufferInfo.bufferName(), "", tr("Error: Setting an encryption key requires Quassel to have been built " + "with support for the Qt Cryptographic Architecture (QCA2) library. " + "Contact your distributor about a Quassel package with QCA2 " + "support, or rebuild Quassel with QCA2 present.")); #endif } -void CoreUserInputHandler::handleDeop(const BufferInfo &bufferInfo, const QString &msg) { - QStringList nicks = msg.split(' ', QString::SkipEmptyParts); - QString m = "-"; for(int i = 0; i < nicks.count(); i++) m += 'o'; - QStringList params; - params << bufferInfo.bufferName() << m << nicks; - emit putCmd("MODE", serverEncode(params)); -} -void CoreUserInputHandler::handleDehalfop(const BufferInfo &bufferInfo, const QString &msg) { - QStringList nicks = msg.split(' ', QString::SkipEmptyParts); - QString m = "-"; for(int i = 0; i < nicks.count(); i++) m += 'h'; - QStringList params; - params << bufferInfo.bufferName() << m << nicks; - emit putCmd("MODE", serverEncode(params)); +void CoreUserInputHandler::handleDeop(const BufferInfo &bufferInfo, const QString &msg) +{ + QStringList nicks = msg.split(' ', QString::SkipEmptyParts); + QString m = "-"; for (int i = 0; i < nicks.count(); i++) m += 'o'; + QStringList params; + params << bufferInfo.bufferName() << m << nicks; + emit putCmd("MODE", serverEncode(params)); } -void CoreUserInputHandler::handleDevoice(const BufferInfo &bufferInfo, const QString &msg) { - QStringList nicks = msg.split(' ', QString::SkipEmptyParts); - QString m = "-"; for(int i = 0; i < nicks.count(); i++) m += 'v'; - QStringList params; - params << bufferInfo.bufferName() << m << nicks; - emit putCmd("MODE", serverEncode(params)); -} -void CoreUserInputHandler::handleInvite(const BufferInfo &bufferInfo, const QString &msg) { - QStringList params; - params << msg << bufferInfo.bufferName(); - emit putCmd("INVITE", serverEncode(params)); +void CoreUserInputHandler::handleDehalfop(const BufferInfo &bufferInfo, const QString &msg) +{ + QStringList nicks = msg.split(' ', QString::SkipEmptyParts); + QString m = "-"; for (int i = 0; i < nicks.count(); i++) m += 'h'; + QStringList params; + params << bufferInfo.bufferName() << m << nicks; + emit putCmd("MODE", serverEncode(params)); } -void CoreUserInputHandler::handleJoin(const BufferInfo &bufferInfo, const QString &msg) { - Q_UNUSED(bufferInfo); - // trim spaces before chans or keys - QString sane_msg = msg; - sane_msg.replace(QRegExp(", +"), ","); - QStringList params = sane_msg.trimmed().split(" "); +void CoreUserInputHandler::handleDevoice(const BufferInfo &bufferInfo, const QString &msg) +{ + QStringList nicks = msg.split(' ', QString::SkipEmptyParts); + QString m = "-"; for (int i = 0; i < nicks.count(); i++) m += 'v'; + QStringList params; + params << bufferInfo.bufferName() << m << nicks; + emit putCmd("MODE", serverEncode(params)); +} - QStringList chans = params[0].split(",", QString::SkipEmptyParts); - QStringList keys; - if(params.count() > 1) - keys = params[1].split(","); - int i; - for(i = 0; i < chans.count(); i++) { - if(!network()->isChannelName(chans[i])) - chans[i].prepend('#'); +void CoreUserInputHandler::handleInvite(const BufferInfo &bufferInfo, const QString &msg) +{ + QStringList params; + params << msg << bufferInfo.bufferName(); + emit putCmd("INVITE", serverEncode(params)); +} - if(i < keys.count()) { - network()->addChannelKey(chans[i], keys[i]); - } else { - network()->removeChannelKey(chans[i]); + +void CoreUserInputHandler::handleJoin(const BufferInfo &bufferInfo, const QString &msg) +{ + Q_UNUSED(bufferInfo); + + // trim spaces before chans or keys + QString sane_msg = msg; + sane_msg.replace(QRegExp(", +"), ","); + QStringList params = sane_msg.trimmed().split(" "); + + QStringList chans = params[0].split(",", QString::SkipEmptyParts); + QStringList keys; + if (params.count() > 1) + keys = params[1].split(","); + + int i; + for (i = 0; i < chans.count(); i++) { + if (!network()->isChannelName(chans[i])) + chans[i].prepend('#'); + + if (i < keys.count()) { + network()->addChannelKey(chans[i], keys[i]); + } + else { + network()->removeChannelKey(chans[i]); + } } - } - - static const char *cmd = "JOIN"; - i = 0; - QStringList joinChans, joinKeys; - int slicesize = chans.count(); - QList encodedParams; - - // go through all to-be-joined channels and (re)build the join list - while(i < chans.count()) { - joinChans.append(chans.at(i)); - if(i < keys.count()) - joinKeys.append(keys.at(i)); - - // if the channel list we built so far either contains all requested channels or exceeds - // the desired amount of channels in this slice, try to send what we have so far - if(++i == chans.count() || joinChans.count() >= slicesize) { - params.clear(); - params.append(joinChans.join(",")); - params.append(joinKeys.join(",")); - encodedParams = serverEncode(params); - // check if it fits in one command - if(lastParamOverrun(cmd, encodedParams) == 0) { - emit putCmd(cmd, encodedParams); - } else if(slicesize > 1) { - // back to start of slice, try again with half the amount of channels - i -= slicesize; - slicesize /= 2; - } - joinChans.clear(); - joinKeys.clear(); + + static const char *cmd = "JOIN"; + i = 0; + QStringList joinChans, joinKeys; + int slicesize = chans.count(); + QList encodedParams; + + // go through all to-be-joined channels and (re)build the join list + while (i < chans.count()) { + joinChans.append(chans.at(i)); + if (i < keys.count()) + joinKeys.append(keys.at(i)); + + // if the channel list we built so far either contains all requested channels or exceeds + // the desired amount of channels in this slice, try to send what we have so far + if (++i == chans.count() || joinChans.count() >= slicesize) { + params.clear(); + params.append(joinChans.join(",")); + params.append(joinKeys.join(",")); + encodedParams = serverEncode(params); + // check if it fits in one command + if (lastParamOverrun(cmd, encodedParams) == 0) { + emit putCmd(cmd, encodedParams); + } + else if (slicesize > 1) { + // back to start of slice, try again with half the amount of channels + i -= slicesize; + slicesize /= 2; + } + joinChans.clear(); + joinKeys.clear(); + } } - } } -void CoreUserInputHandler::handleKick(const BufferInfo &bufferInfo, const QString &msg) { - QString nick = msg.section(' ', 0, 0, QString::SectionSkipEmpty); - QString reason = msg.section(' ', 1, -1, QString::SectionSkipEmpty).trimmed(); - if(reason.isEmpty()) - reason = network()->identityPtr()->kickReason(); - QList params; - params << serverEncode(bufferInfo.bufferName()) << serverEncode(nick) << channelEncode(bufferInfo.bufferName(), reason); - emit putCmd("KICK", params); +void CoreUserInputHandler::handleKick(const BufferInfo &bufferInfo, const QString &msg) +{ + QString nick = msg.section(' ', 0, 0, QString::SectionSkipEmpty); + QString reason = msg.section(' ', 1, -1, QString::SectionSkipEmpty).trimmed(); + if (reason.isEmpty()) + reason = network()->identityPtr()->kickReason(); + + QList params; + params << serverEncode(bufferInfo.bufferName()) << serverEncode(nick) << channelEncode(bufferInfo.bufferName(), reason); + emit putCmd("KICK", params); } -void CoreUserInputHandler::handleKill(const BufferInfo &bufferInfo, const QString &msg) { - Q_UNUSED(bufferInfo) - QString nick = msg.section(' ', 0, 0, QString::SectionSkipEmpty); - QString pass = msg.section(' ', 1, -1, QString::SectionSkipEmpty); - QList params; - params << serverEncode(nick) << serverEncode(pass); - emit putCmd("KILL", params); + +void CoreUserInputHandler::handleKill(const BufferInfo &bufferInfo, const QString &msg) +{ + Q_UNUSED(bufferInfo) + QString nick = msg.section(' ', 0, 0, QString::SectionSkipEmpty); + QString pass = msg.section(' ', 1, -1, QString::SectionSkipEmpty); + QList params; + params << serverEncode(nick) << serverEncode(pass); + emit putCmd("KILL", params); } -void CoreUserInputHandler::handleList(const BufferInfo &bufferInfo, const QString &msg) { - Q_UNUSED(bufferInfo) - emit putCmd("LIST", serverEncode(msg.split(' ', QString::SkipEmptyParts))); +void CoreUserInputHandler::handleList(const BufferInfo &bufferInfo, const QString &msg) +{ + Q_UNUSED(bufferInfo) + emit putCmd("LIST", serverEncode(msg.split(' ', QString::SkipEmptyParts))); } -void CoreUserInputHandler::handleMe(const BufferInfo &bufferInfo, const QString &msg) { - if(bufferInfo.bufferName().isEmpty()) return; // server buffer - // FIXME make this a proper event - coreNetwork()->coreSession()->ctcpParser()->query(coreNetwork(), bufferInfo.bufferName(), "ACTION", msg); - emit displayMsg(Message::Action, bufferInfo.type(), bufferInfo.bufferName(), msg, network()->myNick(), Message::Self); + +void CoreUserInputHandler::handleMe(const BufferInfo &bufferInfo, const QString &msg) +{ + if (bufferInfo.bufferName().isEmpty()) return; // server buffer + // FIXME make this a proper event + coreNetwork()->coreSession()->ctcpParser()->query(coreNetwork(), bufferInfo.bufferName(), "ACTION", msg); + emit displayMsg(Message::Action, bufferInfo.type(), bufferInfo.bufferName(), msg, network()->myNick(), Message::Self); } -void CoreUserInputHandler::handleMode(const BufferInfo &bufferInfo, const QString &msg) { - Q_UNUSED(bufferInfo) - QStringList params = msg.split(' ', QString::SkipEmptyParts); - // if the first argument is neither a channel nor us (user modes are only to oneself) the current buffer is assumed to be the target - if(!params.isEmpty()) { - if(!network()->isChannelName(params[0]) && !network()->isMyNick(params[0])) - params.prepend(bufferInfo.bufferName()); - if(network()->isMyNick(params[0]) && params.count() == 2) - network()->updateIssuedModes(params[1]); - if(params[0] == "-reset" && params.count() == 1) { - // FIXME: give feedback to the user (I don't want to add new strings right now) - network()->resetPersistentModes(); - return; +void CoreUserInputHandler::handleMode(const BufferInfo &bufferInfo, const QString &msg) +{ + Q_UNUSED(bufferInfo) + + QStringList params = msg.split(' ', QString::SkipEmptyParts); + // if the first argument is neither a channel nor us (user modes are only to oneself) the current buffer is assumed to be the target + if (!params.isEmpty()) { + if (!network()->isChannelName(params[0]) && !network()->isMyNick(params[0])) + params.prepend(bufferInfo.bufferName()); + if (network()->isMyNick(params[0]) && params.count() == 2) + network()->updateIssuedModes(params[1]); + if (params[0] == "-reset" && params.count() == 1) { + // FIXME: give feedback to the user (I don't want to add new strings right now) + network()->resetPersistentModes(); + return; + } } - } - // TODO handle correct encoding for buffer modes (channelEncode()) - emit putCmd("MODE", serverEncode(params)); + // TODO handle correct encoding for buffer modes (channelEncode()) + emit putCmd("MODE", serverEncode(params)); } + // TODO: show privmsgs -void CoreUserInputHandler::handleMsg(const BufferInfo &bufferInfo, const QString &msg) { - Q_UNUSED(bufferInfo); - if(!msg.contains(' ')) - return; +void CoreUserInputHandler::handleMsg(const BufferInfo &bufferInfo, const QString &msg) +{ + Q_UNUSED(bufferInfo); + if (!msg.contains(' ')) + return; - QString target = msg.section(' ', 0, 0); - QByteArray encMsg = userEncode(target, msg.section(' ', 1)); + QString target = msg.section(' ', 0, 0); + QByteArray encMsg = userEncode(target, msg.section(' ', 1)); #ifdef HAVE_QCA2 - putPrivmsg(serverEncode(target), encMsg, network()->cipher(target)); + putPrivmsg(serverEncode(target), encMsg, network()->cipher(target)); #else - putPrivmsg(serverEncode(target), encMsg); + putPrivmsg(serverEncode(target), encMsg); #endif } -void CoreUserInputHandler::handleNick(const BufferInfo &bufferInfo, const QString &msg) { - Q_UNUSED(bufferInfo) - QString nick = msg.section(' ', 0, 0); - emit putCmd("NICK", serverEncode(nick)); + +void CoreUserInputHandler::handleNick(const BufferInfo &bufferInfo, const QString &msg) +{ + Q_UNUSED(bufferInfo) + QString nick = msg.section(' ', 0, 0); + emit putCmd("NICK", serverEncode(nick)); } -void CoreUserInputHandler::handleNotice(const BufferInfo &bufferInfo, const QString &msg) { - QString bufferName = msg.section(' ', 0, 0); - QString payload = msg.section(' ', 1); - QList params; - params << serverEncode(bufferName) << channelEncode(bufferInfo.bufferName(), payload); - emit putCmd("NOTICE", params); - emit displayMsg(Message::Notice, bufferName, payload, network()->myNick(), Message::Self); + +void CoreUserInputHandler::handleNotice(const BufferInfo &bufferInfo, const QString &msg) +{ + QString bufferName = msg.section(' ', 0, 0); + QString payload = msg.section(' ', 1); + QList params; + params << serverEncode(bufferName) << channelEncode(bufferInfo.bufferName(), payload); + emit putCmd("NOTICE", params); + emit displayMsg(Message::Notice, bufferName, payload, network()->myNick(), Message::Self); } -void CoreUserInputHandler::handleHalfop(const BufferInfo &bufferInfo, const QString &msg) { - QStringList nicks = msg.split(' ', QString::SkipEmptyParts); - QString m = "+"; for(int i = 0; i < nicks.count(); i++) m += 'h'; - QStringList params; - params << bufferInfo.bufferName() << m << nicks; - emit putCmd("MODE", serverEncode(params)); + +void CoreUserInputHandler::handleHalfop(const BufferInfo &bufferInfo, const QString &msg) +{ + QStringList nicks = msg.split(' ', QString::SkipEmptyParts); + QString m = "+"; for (int i = 0; i < nicks.count(); i++) m += 'h'; + QStringList params; + params << bufferInfo.bufferName() << m << nicks; + emit putCmd("MODE", serverEncode(params)); } -void CoreUserInputHandler::handleOp(const BufferInfo &bufferInfo, const QString &msg) { - QStringList nicks = msg.split(' ', QString::SkipEmptyParts); - QString m = "+"; for(int i = 0; i < nicks.count(); i++) m += 'o'; - QStringList params; - params << bufferInfo.bufferName() << m << nicks; - emit putCmd("MODE", serverEncode(params)); + +void CoreUserInputHandler::handleOp(const BufferInfo &bufferInfo, const QString &msg) +{ + QStringList nicks = msg.split(' ', QString::SkipEmptyParts); + QString m = "+"; for (int i = 0; i < nicks.count(); i++) m += 'o'; + QStringList params; + params << bufferInfo.bufferName() << m << nicks; + emit putCmd("MODE", serverEncode(params)); } -void CoreUserInputHandler::handleOper(const BufferInfo &bufferInfo, const QString &msg) { - Q_UNUSED(bufferInfo) - emit putRawLine(serverEncode(QString("OPER %1").arg(msg))); + +void CoreUserInputHandler::handleOper(const BufferInfo &bufferInfo, const QString &msg) +{ + Q_UNUSED(bufferInfo) + emit putRawLine(serverEncode(QString("OPER %1").arg(msg))); } -void CoreUserInputHandler::handlePart(const BufferInfo &bufferInfo, const QString &msg) { - QList params; - QString partReason; - // msg might contain either a channel name and/or a reaon, so we have to check if the first word is a known channel - QString channelName = msg.section(' ', 0, 0); - if(channelName.isEmpty() || !network()->ircChannel(channelName)) { - channelName = bufferInfo.bufferName(); - partReason = msg; - } else { - partReason = msg.mid(channelName.length() + 1); - } +void CoreUserInputHandler::handlePart(const BufferInfo &bufferInfo, const QString &msg) +{ + QList params; + QString partReason; + + // msg might contain either a channel name and/or a reaon, so we have to check if the first word is a known channel + QString channelName = msg.section(' ', 0, 0); + if (channelName.isEmpty() || !network()->ircChannel(channelName)) { + channelName = bufferInfo.bufferName(); + partReason = msg; + } + else { + partReason = msg.mid(channelName.length() + 1); + } - if(partReason.isEmpty()) - partReason = network()->identityPtr()->partReason(); + if (partReason.isEmpty()) + partReason = network()->identityPtr()->partReason(); - params << serverEncode(channelName) << channelEncode(bufferInfo.bufferName(), partReason); - emit putCmd("PART", params); + params << serverEncode(channelName) << channelEncode(bufferInfo.bufferName(), partReason); + emit putCmd("PART", params); } -void CoreUserInputHandler::handlePing(const BufferInfo &bufferInfo, const QString &msg) { - Q_UNUSED(bufferInfo) - QString param = msg; - if(param.isEmpty()) - param = QTime::currentTime().toString("hh:mm:ss.zzz"); +void CoreUserInputHandler::handlePing(const BufferInfo &bufferInfo, const QString &msg) +{ + Q_UNUSED(bufferInfo) + + QString param = msg; + if (param.isEmpty()) + param = QTime::currentTime().toString("hh:mm:ss.zzz"); - putCmd("PING", serverEncode(param)); + putCmd("PING", serverEncode(param)); } + // TODO: implement queries -void CoreUserInputHandler::handleQuery(const BufferInfo &bufferInfo, const QString &msg) { - Q_UNUSED(bufferInfo) - QString target = msg.section(' ', 0, 0); - QString message = msg.section(' ', 1); - if(message.isEmpty()) - emit displayMsg(Message::Server, BufferInfo::QueryBuffer, target, tr("Starting query with %1").arg(target), network()->myNick(), Message::Self); - else - emit displayMsg(Message::Plain, BufferInfo::QueryBuffer, target, message, network()->myNick(), Message::Self); - handleMsg(bufferInfo, msg); +void CoreUserInputHandler::handleQuery(const BufferInfo &bufferInfo, const QString &msg) +{ + Q_UNUSED(bufferInfo) + QString target = msg.section(' ', 0, 0); + QString message = msg.section(' ', 1); + if (message.isEmpty()) + emit displayMsg(Message::Server, BufferInfo::QueryBuffer, target, tr("Starting query with %1").arg(target), network()->myNick(), Message::Self); + else + emit displayMsg(Message::Plain, BufferInfo::QueryBuffer, target, message, network()->myNick(), Message::Self); + handleMsg(bufferInfo, msg); } -void CoreUserInputHandler::handleQuit(const BufferInfo &bufferInfo, const QString &msg) { - Q_UNUSED(bufferInfo) - network()->disconnectFromIrc(true, msg); + +void CoreUserInputHandler::handleQuit(const BufferInfo &bufferInfo, const QString &msg) +{ + Q_UNUSED(bufferInfo) + network()->disconnectFromIrc(true, msg); } -void CoreUserInputHandler::issueQuit(const QString &reason) { - emit putCmd("QUIT", serverEncode(reason)); + +void CoreUserInputHandler::issueQuit(const QString &reason) +{ + emit putCmd("QUIT", serverEncode(reason)); } -void CoreUserInputHandler::handleQuote(const BufferInfo &bufferInfo, const QString &msg) { - Q_UNUSED(bufferInfo) - emit putRawLine(serverEncode(msg)); + +void CoreUserInputHandler::handleQuote(const BufferInfo &bufferInfo, const QString &msg) +{ + Q_UNUSED(bufferInfo) + emit putRawLine(serverEncode(msg)); } -void CoreUserInputHandler::handleSay(const BufferInfo &bufferInfo, const QString &msg) { - if(bufferInfo.bufferName().isEmpty()) - return; // server buffer - QByteArray encMsg = channelEncode(bufferInfo.bufferName(), msg); +void CoreUserInputHandler::handleSay(const BufferInfo &bufferInfo, const QString &msg) +{ + if (bufferInfo.bufferName().isEmpty()) + return; // server buffer + + QByteArray encMsg = channelEncode(bufferInfo.bufferName(), msg); #ifdef HAVE_QCA2 - putPrivmsg(serverEncode(bufferInfo.bufferName()), encMsg, network()->cipher(bufferInfo.bufferName())); + putPrivmsg(serverEncode(bufferInfo.bufferName()), encMsg, network()->cipher(bufferInfo.bufferName())); #else - putPrivmsg(serverEncode(bufferInfo.bufferName()), encMsg); + putPrivmsg(serverEncode(bufferInfo.bufferName()), encMsg); #endif - emit displayMsg(Message::Plain, bufferInfo.type(), bufferInfo.bufferName(), msg, network()->myNick(), Message::Self); + emit displayMsg(Message::Plain, bufferInfo.type(), bufferInfo.bufferName(), msg, network()->myNick(), Message::Self); } -void CoreUserInputHandler::handleSetkey(const BufferInfo &bufferInfo, const QString &msg) { + +void CoreUserInputHandler::handleSetkey(const BufferInfo &bufferInfo, const QString &msg) +{ #ifdef HAVE_QCA2 - if(!bufferInfo.isValid()) - return; + if (!bufferInfo.isValid()) + return; - if(!Cipher::neededFeaturesAvailable()) - return; + if (!Cipher::neededFeaturesAvailable()) + return; - QStringList parms = msg.split(' ', QString::SkipEmptyParts); + QStringList parms = msg.split(' ', QString::SkipEmptyParts); - if(parms.count() == 1 && !bufferInfo.bufferName().isEmpty()) - parms.prepend(bufferInfo.bufferName()); - else if(parms.count() != 2) { - emit displayMsg(Message::Info, bufferInfo.bufferName(), - tr("[usage] /setkey sets the encryption key for nick or channel. " - "/setkey when in a channel or query buffer sets the key for it.")); - return; - } + if (parms.count() == 1 && !bufferInfo.bufferName().isEmpty()) + parms.prepend(bufferInfo.bufferName()); + else if (parms.count() != 2) { + emit displayMsg(Message::Info, bufferInfo.bufferName(), + tr("[usage] /setkey sets the encryption key for nick or channel. " + "/setkey when in a channel or query buffer sets the key for it.")); + return; + } - QString target = parms.at(0); - QByteArray key = parms.at(1).toLocal8Bit(); + QString target = parms.at(0); + QByteArray key = parms.at(1).toLocal8Bit(); - network()->setCipherKey(target, key); + network()->setCipherKey(target, key); - if(network()->isChannelName(target) && network()->channels().contains(target)) - qobject_cast(network()->ircChannel(target))->setEncrypted(true); - else if(network()->nicks().contains(target)) - qobject_cast(network()->ircUser(target))->setEncrypted(true); + if (network()->isChannelName(target) && network()->channels().contains(target)) + qobject_cast(network()->ircChannel(target))->setEncrypted(true); + else if (network()->nicks().contains(target)) + qobject_cast(network()->ircUser(target))->setEncrypted(true); - emit displayMsg(Message::Info, bufferInfo.bufferName(), tr("The key for %1 has been set.").arg(target)); + emit displayMsg(Message::Info, bufferInfo.bufferName(), tr("The key for %1 has been set.").arg(target)); #else - Q_UNUSED(msg) - emit displayMsg(Message::Error, bufferInfo.bufferName(), tr("Error: Setting an encryption key requires Quassel to have been built " - "with support for the Qt Cryptographic Architecture (QCA) library. " - "Contact your distributor about a Quassel package with QCA " - "support, or rebuild Quassel with QCA present.")); + Q_UNUSED(msg) + emit displayMsg(Message::Error, bufferInfo.bufferName(), tr("Error: Setting an encryption key requires Quassel to have been built " + "with support for the Qt Cryptographic Architecture (QCA) library. " + "Contact your distributor about a Quassel package with QCA " + "support, or rebuild Quassel with QCA present.")); #endif } -void CoreUserInputHandler::handleShowkey(const BufferInfo &bufferInfo, const QString &msg) { + +void CoreUserInputHandler::handleShowkey(const BufferInfo &bufferInfo, const QString &msg) +{ #ifdef HAVE_QCA2 - if(!bufferInfo.isValid()) - return; + if (!bufferInfo.isValid()) + return; - if(!Cipher::neededFeaturesAvailable()) - return; + if (!Cipher::neededFeaturesAvailable()) + return; - QStringList parms = msg.split(' ', QString::SkipEmptyParts); + QStringList parms = msg.split(' ', QString::SkipEmptyParts); - if(parms.isEmpty() && !bufferInfo.bufferName().isEmpty()) - parms.prepend(bufferInfo.bufferName()); + if (parms.isEmpty() && !bufferInfo.bufferName().isEmpty()) + parms.prepend(bufferInfo.bufferName()); - if(parms.isEmpty()) { - emit displayMsg(Message::Info, bufferInfo.bufferName(), "", - tr("[usage] /showkey shows the encryption key for nick or channel or just /showkey when in a channel or query.")); - return; - } + if (parms.isEmpty()) { + emit displayMsg(Message::Info, bufferInfo.bufferName(), "", + tr("[usage] /showkey shows the encryption key for nick or channel or just /showkey when in a channel or query.")); + return; + } - QString target = parms.at(0); - QByteArray key = network()->cipherKey(target); + QString target = parms.at(0); + QByteArray key = network()->cipherKey(target); - if(key.isEmpty()) { - emit displayMsg(Message::Info, bufferInfo.bufferName(), tr("No key has been set for %1.").arg(target)); - return; - } + if (key.isEmpty()) { + emit displayMsg(Message::Info, bufferInfo.bufferName(), tr("No key has been set for %1.").arg(target)); + return; + } - emit displayMsg(Message::Info, bufferInfo.bufferName(), tr("The key for %1 is %2").arg(target).arg(QString(key))); + emit displayMsg(Message::Info, bufferInfo.bufferName(), tr("The key for %1 is %2").arg(target).arg(QString(key))); #else - Q_UNUSED(msg) - emit displayMsg(Message::Error, bufferInfo.bufferName(), "", tr("Error: Setting an encryption key requires Quassel to have been built " - "with support for the Qt Cryptographic Architecture (QCA2) library. " - "Contact your distributor about a Quassel package with QCA2 " - "support, or rebuild Quassel with QCA2 present.")); + Q_UNUSED(msg) + emit displayMsg(Message::Error, bufferInfo.bufferName(), "", tr("Error: Setting an encryption key requires Quassel to have been built " + "with support for the Qt Cryptographic Architecture (QCA2) library. " + "Contact your distributor about a Quassel package with QCA2 " + "support, or rebuild Quassel with QCA2 present.")); #endif } -void CoreUserInputHandler::handleTopic(const BufferInfo &bufferInfo, const QString &msg) { - if(bufferInfo.bufferName().isEmpty()) - return; - QList params; - params << serverEncode(bufferInfo.bufferName()); +void CoreUserInputHandler::handleTopic(const BufferInfo &bufferInfo, const QString &msg) +{ + if (bufferInfo.bufferName().isEmpty()) + return; - if(!msg.isEmpty()) { + QList params; + params << serverEncode(bufferInfo.bufferName()); + + if (!msg.isEmpty()) { # ifdef HAVE_QCA2 - params << encrypt(bufferInfo.bufferName(), channelEncode(bufferInfo.bufferName(), msg)); + params << encrypt(bufferInfo.bufferName(), channelEncode(bufferInfo.bufferName(), msg)); # else - params << channelEncode(bufferInfo.bufferName(), msg); + params << channelEncode(bufferInfo.bufferName(), msg); # endif - } + } - emit putCmd("TOPIC", params); + emit putCmd("TOPIC", params); } -void CoreUserInputHandler::handleVoice(const BufferInfo &bufferInfo, const QString &msg) { - QStringList nicks = msg.split(' ', QString::SkipEmptyParts); - QString m = "+"; for(int i = 0; i < nicks.count(); i++) m += 'v'; - QStringList params; - params << bufferInfo.bufferName() << m << nicks; - emit putCmd("MODE", serverEncode(params)); + +void CoreUserInputHandler::handleVoice(const BufferInfo &bufferInfo, const QString &msg) +{ + QStringList nicks = msg.split(' ', QString::SkipEmptyParts); + QString m = "+"; for (int i = 0; i < nicks.count(); i++) m += 'v'; + QStringList params; + params << bufferInfo.bufferName() << m << nicks; + emit putCmd("MODE", serverEncode(params)); } -void CoreUserInputHandler::handleWait(const BufferInfo &bufferInfo, const QString &msg) { - int splitPos = msg.indexOf(';'); - if(splitPos <= 0) - return; - bool ok; - int delay = msg.left(splitPos).trimmed().toInt(&ok); - if(!ok) - return; +void CoreUserInputHandler::handleWait(const BufferInfo &bufferInfo, const QString &msg) +{ + int splitPos = msg.indexOf(';'); + if (splitPos <= 0) + return; + + bool ok; + int delay = msg.left(splitPos).trimmed().toInt(&ok); + if (!ok) + return; - delay *= 1000; + delay *= 1000; - QString command = msg.mid(splitPos + 1).trimmed(); - if(command.isEmpty()) - return; + QString command = msg.mid(splitPos + 1).trimmed(); + if (command.isEmpty()) + return; - _delayedCommands[startTimer(delay)] = Command(bufferInfo, command); + _delayedCommands[startTimer(delay)] = Command(bufferInfo, command); } -void CoreUserInputHandler::handleWho(const BufferInfo &bufferInfo, const QString &msg) { - Q_UNUSED(bufferInfo) - emit putCmd("WHO", serverEncode(msg.split(' '))); -} -void CoreUserInputHandler::handleWhois(const BufferInfo &bufferInfo, const QString &msg) { - Q_UNUSED(bufferInfo) - emit putCmd("WHOIS", serverEncode(msg.split(' '))); +void CoreUserInputHandler::handleWho(const BufferInfo &bufferInfo, const QString &msg) +{ + Q_UNUSED(bufferInfo) + emit putCmd("WHO", serverEncode(msg.split(' '))); } -void CoreUserInputHandler::handleWhowas(const BufferInfo &bufferInfo, const QString &msg) { - Q_UNUSED(bufferInfo) - emit putCmd("WHOWAS", serverEncode(msg.split(' '))); + +void CoreUserInputHandler::handleWhois(const BufferInfo &bufferInfo, const QString &msg) +{ + Q_UNUSED(bufferInfo) + emit putCmd("WHOIS", serverEncode(msg.split(' '))); } -void CoreUserInputHandler::defaultHandler(QString cmd, const BufferInfo &bufferInfo, const QString &msg) { - Q_UNUSED(bufferInfo); - emit putCmd(serverEncode(cmd.toUpper()), serverEncode(msg.split(" "))); + +void CoreUserInputHandler::handleWhowas(const BufferInfo &bufferInfo, const QString &msg) +{ + Q_UNUSED(bufferInfo) + emit putCmd("WHOWAS", serverEncode(msg.split(' '))); } -void CoreUserInputHandler::putPrivmsg(const QByteArray &target, const QByteArray &message, Cipher *cipher) { - // Encrypted messages need special care. There's no clear relation between cleartext and encrypted message length, - // so we can't just compute the maxSplitPos. Instead, we need to loop through the splitpoints until the crypted - // version is short enough... - // TODO: check out how the various possible encryption methods behave length-wise and make - // this clean by predicting the length of the crypted msg. - // For example, blowfish-ebc seems to create 8-char chunks. - static const char *cmd = "PRIVMSG"; - static const char *splitter = " .,-"; +void CoreUserInputHandler::defaultHandler(QString cmd, const BufferInfo &bufferInfo, const QString &msg) +{ + Q_UNUSED(bufferInfo); + emit putCmd(serverEncode(cmd.toUpper()), serverEncode(msg.split(" "))); +} + - int maxSplitPos = message.count(); - int splitPos = maxSplitPos; - forever { - QByteArray crypted = message.left(splitPos); - bool isEncrypted = false; +void CoreUserInputHandler::putPrivmsg(const QByteArray &target, const QByteArray &message, Cipher *cipher) +{ + // Encrypted messages need special care. There's no clear relation between cleartext and encrypted message length, + // so we can't just compute the maxSplitPos. Instead, we need to loop through the splitpoints until the crypted + // version is short enough... + // TODO: check out how the various possible encryption methods behave length-wise and make + // this clean by predicting the length of the crypted msg. + // For example, blowfish-ebc seems to create 8-char chunks. + + static const char *cmd = "PRIVMSG"; + static const char *splitter = " .,-"; + + int maxSplitPos = message.count(); + int splitPos = maxSplitPos; + forever { + QByteArray crypted = message.left(splitPos); + bool isEncrypted = false; #ifdef HAVE_QCA2 - if(cipher && !message.isEmpty()) { - isEncrypted = cipher->encrypt(crypted); - } + if (cipher && !message.isEmpty()) { + isEncrypted = cipher->encrypt(crypted); + } #endif - int overrun = lastParamOverrun(cmd, QList() << target << crypted); - if(overrun) { - // In case this is not an encrypted msg, we can just cut off at the end - if(!isEncrypted) - maxSplitPos = message.count() - overrun; - - splitPos = -1; - for(const char *splitChar = splitter; *splitChar != 0; splitChar++) { - splitPos = qMax(splitPos, message.lastIndexOf(*splitChar, maxSplitPos) + 1); // keep split char on old line - } - if(splitPos <= 0 || splitPos > maxSplitPos) - splitPos = maxSplitPos; - - maxSplitPos = splitPos - 1; - if(maxSplitPos <= 0) { // this should never happen, but who knows... - qWarning() << tr("[Error] Could not encrypt your message: %1").arg(message.data()); + int overrun = lastParamOverrun(cmd, QList() << target << crypted); + if (overrun) { + // In case this is not an encrypted msg, we can just cut off at the end + if (!isEncrypted) + maxSplitPos = message.count() - overrun; + + splitPos = -1; + for (const char *splitChar = splitter; *splitChar != 0; splitChar++) { + splitPos = qMax(splitPos, message.lastIndexOf(*splitChar, maxSplitPos) + 1); // keep split char on old line + } + if (splitPos <= 0 || splitPos > maxSplitPos) + splitPos = maxSplitPos; + + maxSplitPos = splitPos - 1; + if (maxSplitPos <= 0) { // this should never happen, but who knows... + qWarning() << tr("[Error] Could not encrypt your message: %1").arg(message.data()); + return; + } + continue; // we never come back here for !encrypted! + } + + // now we have found a valid splitpos (or didn't need to split to begin with) + putCmd(cmd, QList() << target << crypted); + if (splitPos < message.count()) + putPrivmsg(target, message.mid(splitPos), cipher); + return; - } - continue; // we never come back here for !encrypted! } - - // now we have found a valid splitpos (or didn't need to split to begin with) - putCmd(cmd, QList() << target << crypted); - if(splitPos < message.count()) - putPrivmsg(target, message.mid(splitPos), cipher); - - return; - } } + // returns 0 if the message will not be chopped by the irc server or number of chopped bytes if message is too long -int CoreUserInputHandler::lastParamOverrun(const QString &cmd, const QList ¶ms) { - // the server will pass our message truncated to 512 bytes including CRLF with the following format: - // ":prefix COMMAND param0 param1 :lastparam" - // where prefix = "nickname!user@host" - // that means that the last message can be as long as: - // 512 - nicklen - userlen - hostlen - commandlen - sum(param[0]..param[n-1])) - 2 (for CRLF) - 4 (":!@" + 1space between prefix and command) - max(paramcount - 1, 0) (space for simple params) - 2 (space and colon for last param) - IrcUser *me = network()->me(); - int maxLen = 480 - cmd.toAscii().count(); // educated guess in case we don't know us (yet?) - - if(me) - maxLen = 512 - serverEncode(me->nick()).count() - serverEncode(me->user()).count() - serverEncode(me->host()).count() - cmd.toAscii().count() - 6; - - if(!params.isEmpty()) { - for(int i = 0; i < params.count() - 1; i++) { - maxLen -= (params[i].count() + 1); +int CoreUserInputHandler::lastParamOverrun(const QString &cmd, const QList ¶ms) +{ + // the server will pass our message truncated to 512 bytes including CRLF with the following format: + // ":prefix COMMAND param0 param1 :lastparam" + // where prefix = "nickname!user@host" + // that means that the last message can be as long as: + // 512 - nicklen - userlen - hostlen - commandlen - sum(param[0]..param[n-1])) - 2 (for CRLF) - 4 (":!@" + 1space between prefix and command) - max(paramcount - 1, 0) (space for simple params) - 2 (space and colon for last param) + IrcUser *me = network()->me(); + int maxLen = 480 - cmd.toAscii().count(); // educated guess in case we don't know us (yet?) + + if (me) + maxLen = 512 - serverEncode(me->nick()).count() - serverEncode(me->user()).count() - serverEncode(me->host()).count() - cmd.toAscii().count() - 6; + + if (!params.isEmpty()) { + for (int i = 0; i < params.count() - 1; i++) { + maxLen -= (params[i].count() + 1); + } + maxLen -= 2; // " :" last param separator; + + if (params.last().count() > maxLen) { + return params.last().count() - maxLen; + } + else { + return 0; + } } - maxLen -= 2; // " :" last param separator; - - if(params.last().count() > maxLen) { - return params.last().count() - maxLen; - } else { - return 0; + else { + return 0; } - } else { - return 0; - } } + #ifdef HAVE_QCA2 -QByteArray CoreUserInputHandler::encrypt(const QString &target, const QByteArray &message_, bool *didEncrypt) const { - if(didEncrypt) - *didEncrypt = false; +QByteArray CoreUserInputHandler::encrypt(const QString &target, const QByteArray &message_, bool *didEncrypt) const +{ + if (didEncrypt) + *didEncrypt = false; - if(message_.isEmpty()) - return message_; + if (message_.isEmpty()) + return message_; - if(!Cipher::neededFeaturesAvailable()) - return message_; + if (!Cipher::neededFeaturesAvailable()) + return message_; - Cipher *cipher = network()->cipher(target); - if(!cipher) - return message_; + Cipher *cipher = network()->cipher(target); + if (!cipher) + return message_; - QByteArray message = message_; - bool result = cipher->encrypt(message); - if(didEncrypt) - *didEncrypt = result; + QByteArray message = message_; + bool result = cipher->encrypt(message); + if (didEncrypt) + *didEncrypt = result; - return message; + return message; } + + #endif -void CoreUserInputHandler::timerEvent(QTimerEvent *event) { - if(!_delayedCommands.contains(event->timerId())) { - QObject::timerEvent(event); - return; - } - BufferInfo bufferInfo = _delayedCommands[event->timerId()].bufferInfo; - QString rawCommand = _delayedCommands[event->timerId()].command; - _delayedCommands.remove(event->timerId()); - event->accept(); - - // the stored command might be the result of an alias expansion, so we need to split it up again - QStringList commands = rawCommand.split(QRegExp("; ?")); - foreach(QString command, commands) { - handleUserInput(bufferInfo, command); - } +void CoreUserInputHandler::timerEvent(QTimerEvent *event) +{ + if (!_delayedCommands.contains(event->timerId())) { + QObject::timerEvent(event); + return; + } + BufferInfo bufferInfo = _delayedCommands[event->timerId()].bufferInfo; + QString rawCommand = _delayedCommands[event->timerId()].command; + _delayedCommands.remove(event->timerId()); + event->accept(); + + // the stored command might be the result of an alias expansion, so we need to split it up again + QStringList commands = rawCommand.split(QRegExp("; ?")); + foreach(QString command, commands) { + handleUserInput(bufferInfo, command); + } } diff --git a/src/core/coreuserinputhandler.h b/src/core/coreuserinputhandler.h index 9db419b6..710a0851 100644 --- a/src/core/coreuserinputhandler.h +++ b/src/core/coreuserinputhandler.h @@ -27,77 +27,79 @@ class Cipher; class Server; -class CoreUserInputHandler : public CoreBasicHandler { - Q_OBJECT +class CoreUserInputHandler : public CoreBasicHandler +{ + Q_OBJECT public: - CoreUserInputHandler(CoreNetwork *parent = 0); - inline CoreNetwork *coreNetwork() const { return qobject_cast(parent()); } + CoreUserInputHandler(CoreNetwork *parent = 0); + inline CoreNetwork *coreNetwork() const { return qobject_cast(parent()); } - void handleUserInput(const BufferInfo &bufferInfo, const QString &text); + void handleUserInput(const BufferInfo &bufferInfo, const QString &text); public slots: - void handleAway(const BufferInfo &bufferInfo, const QString &text); - void handleBan(const BufferInfo &bufferInfo, const QString &text); - void handleUnban(const BufferInfo &bufferInfo, const QString &text); - void handleCtcp(const BufferInfo &bufferInfo, const QString &text); - void handleDelkey(const BufferInfo &bufferInfo, const QString &text); - void handleDeop(const BufferInfo &bufferInfo, const QString &text); - void handleDehalfop(const BufferInfo &bufferInfo, const QString &text); - void handleDevoice(const BufferInfo &bufferInfo, const QString &text); - void handleInvite(const BufferInfo &bufferInfo, const QString &text); - void handleJoin(const BufferInfo &bufferInfo, const QString &text); - void handleKick(const BufferInfo &bufferInfo, const QString &text); - void handleKill(const BufferInfo &bufferInfo, const QString &text); - void handleList(const BufferInfo &bufferInfo, const QString &text); - void handleMe(const BufferInfo &bufferInfo, const QString &text); - void handleMode(const BufferInfo &bufferInfo, const QString &text); - void handleMsg(const BufferInfo &bufferInfo, const QString &text); - void handleNick(const BufferInfo &bufferInfo, const QString &text); - void handleNotice(const BufferInfo &bufferInfo, const QString &text); - void handleOper(const BufferInfo &bufferInfo, const QString &text); - void handleOp(const BufferInfo &bufferInfo, const QString &text); - void handleHalfop(const BufferInfo &bufferInfo, const QString &text); - void handlePart(const BufferInfo &bufferInfo, const QString &text); - void handlePing(const BufferInfo &bufferInfo, const QString &text); - void handleQuery(const BufferInfo &bufferInfo, const QString &text); - void handleQuit(const BufferInfo &bufferInfo, const QString &text); - void handleQuote(const BufferInfo &bufferInfo, const QString &text); - void handleSay(const BufferInfo &bufferInfo, const QString &text); - void handleSetkey(const BufferInfo &bufferInfo, const QString &text); - void handleShowkey(const BufferInfo &bufferInfo, const QString &text); - void handleTopic(const BufferInfo &bufferInfo, const QString &text); - void handleVoice(const BufferInfo &bufferInfo, const QString &text); - void handleWait(const BufferInfo &bufferInfo, const QString &text); - void handleWho(const BufferInfo &bufferInfo, const QString &text); - void handleWhois(const BufferInfo &bufferInfo, const QString &text); - void handleWhowas(const BufferInfo &bufferInfo, const QString &text); - - void defaultHandler(QString cmd, const BufferInfo &bufferInfo, const QString &text); - - void issueQuit(const QString &reason); - void issueAway(const QString &msg, bool autoCheck = true); + void handleAway(const BufferInfo &bufferInfo, const QString &text); + void handleBan(const BufferInfo &bufferInfo, const QString &text); + void handleUnban(const BufferInfo &bufferInfo, const QString &text); + void handleCtcp(const BufferInfo &bufferInfo, const QString &text); + void handleDelkey(const BufferInfo &bufferInfo, const QString &text); + void handleDeop(const BufferInfo &bufferInfo, const QString &text); + void handleDehalfop(const BufferInfo &bufferInfo, const QString &text); + void handleDevoice(const BufferInfo &bufferInfo, const QString &text); + void handleInvite(const BufferInfo &bufferInfo, const QString &text); + void handleJoin(const BufferInfo &bufferInfo, const QString &text); + void handleKick(const BufferInfo &bufferInfo, const QString &text); + void handleKill(const BufferInfo &bufferInfo, const QString &text); + void handleList(const BufferInfo &bufferInfo, const QString &text); + void handleMe(const BufferInfo &bufferInfo, const QString &text); + void handleMode(const BufferInfo &bufferInfo, const QString &text); + void handleMsg(const BufferInfo &bufferInfo, const QString &text); + void handleNick(const BufferInfo &bufferInfo, const QString &text); + void handleNotice(const BufferInfo &bufferInfo, const QString &text); + void handleOper(const BufferInfo &bufferInfo, const QString &text); + void handleOp(const BufferInfo &bufferInfo, const QString &text); + void handleHalfop(const BufferInfo &bufferInfo, const QString &text); + void handlePart(const BufferInfo &bufferInfo, const QString &text); + void handlePing(const BufferInfo &bufferInfo, const QString &text); + void handleQuery(const BufferInfo &bufferInfo, const QString &text); + void handleQuit(const BufferInfo &bufferInfo, const QString &text); + void handleQuote(const BufferInfo &bufferInfo, const QString &text); + void handleSay(const BufferInfo &bufferInfo, const QString &text); + void handleSetkey(const BufferInfo &bufferInfo, const QString &text); + void handleShowkey(const BufferInfo &bufferInfo, const QString &text); + void handleTopic(const BufferInfo &bufferInfo, const QString &text); + void handleVoice(const BufferInfo &bufferInfo, const QString &text); + void handleWait(const BufferInfo &bufferInfo, const QString &text); + void handleWho(const BufferInfo &bufferInfo, const QString &text); + void handleWhois(const BufferInfo &bufferInfo, const QString &text); + void handleWhowas(const BufferInfo &bufferInfo, const QString &text); + + void defaultHandler(QString cmd, const BufferInfo &bufferInfo, const QString &text); + + void issueQuit(const QString &reason); + void issueAway(const QString &msg, bool autoCheck = true); protected: - void timerEvent(QTimerEvent *event); + void timerEvent(QTimerEvent *event); private: - void banOrUnban(const BufferInfo &bufferInfo, const QString &text, bool ban); - void putPrivmsg(const QByteArray &target, const QByteArray &message, Cipher *cipher = 0); - int lastParamOverrun(const QString &cmd, const QList ¶ms); + void banOrUnban(const BufferInfo &bufferInfo, const QString &text, bool ban); + void putPrivmsg(const QByteArray &target, const QByteArray &message, Cipher *cipher = 0); + int lastParamOverrun(const QString &cmd, const QList ¶ms); #ifdef HAVE_QCA2 - QByteArray encrypt(const QString &target, const QByteArray &message, bool *didEncrypt = 0) const; + QByteArray encrypt(const QString &target, const QByteArray &message, bool *didEncrypt = 0) const; #endif - struct Command { - BufferInfo bufferInfo; - QString command; - Command(const BufferInfo &info, const QString &command) : bufferInfo(info), command(command) {} - Command() {} - }; + struct Command { + BufferInfo bufferInfo; + QString command; + Command(const BufferInfo &info, const QString &command) : bufferInfo(info), command(command) {} + Command() {} + }; - QHash _delayedCommands; + QHash _delayedCommands; }; + #endif diff --git a/src/core/coreusersettings.cpp b/src/core/coreusersettings.cpp index 5f711c4a..5fbd15d5 100644 --- a/src/core/coreusersettings.cpp +++ b/src/core/coreusersettings.cpp @@ -20,56 +20,72 @@ #include "coreusersettings.h" -CoreUserSettings::CoreUserSettings(UserId uid) : CoreSettings(QString("CoreUser/%1").arg(uid.toInt())), user(uid) { +CoreUserSettings::CoreUserSettings(UserId uid) : CoreSettings(QString("CoreUser/%1").arg(uid.toInt())), user(uid) +{ +} +Identity CoreUserSettings::identity(IdentityId id) +{ + QVariant v = localValue(QString("Identities/%1").arg(id.toInt())); + if (qVariantCanConvert(v)) { + return v.value(); + } + return Identity(); } -Identity CoreUserSettings::identity(IdentityId id) { - QVariant v = localValue(QString("Identities/%1").arg(id.toInt())); - if(qVariantCanConvert(v)) { - return v.value(); - } - return Identity(); -} -QList CoreUserSettings::identityIds() { - QList res; - foreach(QString id, localChildKeys("Identities")) { - res << id.toInt(); - } - return res; +QList CoreUserSettings::identityIds() +{ + QList res; + foreach(QString id, localChildKeys("Identities")) { + res << id.toInt(); + } + return res; } -void CoreUserSettings::storeIdentity(const Identity &identity) { - setLocalValue(QString("Identities/%1").arg(identity.id().toInt()), qVariantFromValue(identity)); -} -void CoreUserSettings::removeIdentity(IdentityId id) { - removeLocalKey(QString("Identities/%1").arg(id.toInt())); +void CoreUserSettings::storeIdentity(const Identity &identity) +{ + setLocalValue(QString("Identities/%1").arg(identity.id().toInt()), qVariantFromValue(identity)); } -void CoreUserSettings::setSessionState(const QVariant &data) { - setLocalValue("SessionState", data); + +void CoreUserSettings::removeIdentity(IdentityId id) +{ + removeLocalKey(QString("Identities/%1").arg(id.toInt())); } -QVariant CoreUserSettings::sessionState(const QVariant &def) { - return localValue("SessionState", def); + +void CoreUserSettings::setSessionState(const QVariant &data) +{ + setLocalValue("SessionState", data); } -QVariantMap CoreUserSettings::sessionData() { - QVariantMap res; - foreach(QString key, localChildKeys(QString("SessionData"))) { - res[key] = localValue(QString("SessionData/%1").arg(key)); - } - return res; + +QVariant CoreUserSettings::sessionState(const QVariant &def) +{ + return localValue("SessionState", def); } -void CoreUserSettings::setSessionValue(const QString &key, const QVariant &data) { - setLocalValue(QString("SessionData/%1").arg(key), data); + +QVariantMap CoreUserSettings::sessionData() +{ + QVariantMap res; + foreach(QString key, localChildKeys(QString("SessionData"))) { + res[key] = localValue(QString("SessionData/%1").arg(key)); + } + return res; } -QVariant CoreUserSettings::sessionValue(const QString &key, const QVariant &def) { - return localValue(QString("SessionData/%1").arg(key), def); + +void CoreUserSettings::setSessionValue(const QString &key, const QVariant &data) +{ + setLocalValue(QString("SessionData/%1").arg(key), data); } + +QVariant CoreUserSettings::sessionValue(const QString &key, const QVariant &def) +{ + return localValue(QString("SessionData/%1").arg(key), def); +} diff --git a/src/core/coreusersettings.h b/src/core/coreusersettings.h index 8ee3a101..8220497d 100644 --- a/src/core/coreusersettings.h +++ b/src/core/coreusersettings.h @@ -28,9 +28,9 @@ #include -class CoreUserSettings : public CoreSettings { - - public: +class CoreUserSettings : public CoreSettings +{ +public: CoreUserSettings(UserId user); Identity identity(IdentityId id); @@ -41,7 +41,7 @@ class CoreUserSettings : public CoreSettings { void setSessionState(const QVariant &data); QVariant sessionState(const QVariant &def = QVariant()); - private: +private: // this stuff should only be accessed by CoreSession! QVariantMap sessionData(); QVariant sessionValue(const QString &key, const QVariant &def = QVariant()); @@ -52,4 +52,5 @@ class CoreUserSettings : public CoreSettings { friend class CoreSession; }; + #endif diff --git a/src/core/ctcpparser.cpp b/src/core/ctcpparser.cpp index 63c3dde9..b8ac4b35 100644 --- a/src/core/ctcpparser.cpp +++ b/src/core/ctcpparser.cpp @@ -27,236 +27,264 @@ const QByteArray XDELIM = "\001"; CtcpParser::CtcpParser(CoreSession *coreSession, QObject *parent) - : QObject(parent), + : QObject(parent), _coreSession(coreSession) { - QByteArray MQUOTE = QByteArray("\020"); - _ctcpMDequoteHash[MQUOTE + '0'] = QByteArray(1, '\000'); - _ctcpMDequoteHash[MQUOTE + 'n'] = QByteArray(1, '\n'); - _ctcpMDequoteHash[MQUOTE + 'r'] = QByteArray(1, '\r'); - _ctcpMDequoteHash[MQUOTE + MQUOTE] = MQUOTE; + QByteArray MQUOTE = QByteArray("\020"); + _ctcpMDequoteHash[MQUOTE + '0'] = QByteArray(1, '\000'); + _ctcpMDequoteHash[MQUOTE + 'n'] = QByteArray(1, '\n'); + _ctcpMDequoteHash[MQUOTE + 'r'] = QByteArray(1, '\r'); + _ctcpMDequoteHash[MQUOTE + MQUOTE] = MQUOTE; - QByteArray XQUOTE = QByteArray("\134"); - _ctcpXDelimDequoteHash[XQUOTE + XQUOTE] = XQUOTE; - _ctcpXDelimDequoteHash[XQUOTE + QByteArray("a")] = XDELIM; + QByteArray XQUOTE = QByteArray("\134"); + _ctcpXDelimDequoteHash[XQUOTE + XQUOTE] = XQUOTE; + _ctcpXDelimDequoteHash[XQUOTE + QByteArray("a")] = XDELIM; - connect(this, SIGNAL(newEvent(Event *)), _coreSession->eventManager(), SLOT(postEvent(Event *))); + connect(this, SIGNAL(newEvent(Event *)), _coreSession->eventManager(), SLOT(postEvent(Event *))); } + void CtcpParser::displayMsg(NetworkEvent *event, Message::Type msgType, const QString &msg, const QString &sender, - const QString &target, Message::Flags msgFlags) { - if(event->testFlag(EventManager::Silent)) - return; + const QString &target, Message::Flags msgFlags) +{ + if (event->testFlag(EventManager::Silent)) + return; - MessageEvent *msgEvent = new MessageEvent(msgType, event->network(), msg, sender, target, msgFlags); - msgEvent->setTimestamp(event->timestamp()); + MessageEvent *msgEvent = new MessageEvent(msgType, event->network(), msg, sender, target, msgFlags); + msgEvent->setTimestamp(event->timestamp()); - emit newEvent(msgEvent); + emit newEvent(msgEvent); } -QByteArray CtcpParser::lowLevelQuote(const QByteArray &message) { - QByteArray quotedMessage = message; - QHash quoteHash = _ctcpMDequoteHash; - QByteArray MQUOTE = QByteArray("\020"); - quoteHash.remove(MQUOTE + MQUOTE); - quotedMessage.replace(MQUOTE, MQUOTE + MQUOTE); +QByteArray CtcpParser::lowLevelQuote(const QByteArray &message) +{ + QByteArray quotedMessage = message; - QHash::const_iterator quoteIter = quoteHash.constBegin(); - while(quoteIter != quoteHash.constEnd()) { - quotedMessage.replace(quoteIter.value(), quoteIter.key()); - quoteIter++; - } - return quotedMessage; + QHash quoteHash = _ctcpMDequoteHash; + QByteArray MQUOTE = QByteArray("\020"); + quoteHash.remove(MQUOTE + MQUOTE); + quotedMessage.replace(MQUOTE, MQUOTE + MQUOTE); + + QHash::const_iterator quoteIter = quoteHash.constBegin(); + while (quoteIter != quoteHash.constEnd()) { + quotedMessage.replace(quoteIter.value(), quoteIter.key()); + quoteIter++; + } + return quotedMessage; } -QByteArray CtcpParser::lowLevelDequote(const QByteArray &message) { - QByteArray dequotedMessage; - QByteArray messagepart; - QHash::iterator ctcpquote; - - // copy dequote Message - for(int i = 0; i < message.size(); i++) { - messagepart = message.mid(i,1); - if(i+1 < message.size()) { - for(ctcpquote = _ctcpMDequoteHash.begin(); ctcpquote != _ctcpMDequoteHash.end(); ++ctcpquote) { - if(message.mid(i,2) == ctcpquote.key()) { - messagepart = ctcpquote.value(); - ++i; - break; + +QByteArray CtcpParser::lowLevelDequote(const QByteArray &message) +{ + QByteArray dequotedMessage; + QByteArray messagepart; + QHash::iterator ctcpquote; + + // copy dequote Message + for (int i = 0; i < message.size(); i++) { + messagepart = message.mid(i, 1); + if (i+1 < message.size()) { + for (ctcpquote = _ctcpMDequoteHash.begin(); ctcpquote != _ctcpMDequoteHash.end(); ++ctcpquote) { + if (message.mid(i, 2) == ctcpquote.key()) { + messagepart = ctcpquote.value(); + ++i; + break; + } + } } - } + dequotedMessage += messagepart; } - dequotedMessage += messagepart; - } - return dequotedMessage; + return dequotedMessage; } -QByteArray CtcpParser::xdelimQuote(const QByteArray &message) { - QByteArray quotedMessage = message; - QHash::const_iterator quoteIter = _ctcpXDelimDequoteHash.constBegin(); - while(quoteIter != _ctcpXDelimDequoteHash.constEnd()) { - quotedMessage.replace(quoteIter.value(), quoteIter.key()); - quoteIter++; - } - return quotedMessage; + +QByteArray CtcpParser::xdelimQuote(const QByteArray &message) +{ + QByteArray quotedMessage = message; + QHash::const_iterator quoteIter = _ctcpXDelimDequoteHash.constBegin(); + while (quoteIter != _ctcpXDelimDequoteHash.constEnd()) { + quotedMessage.replace(quoteIter.value(), quoteIter.key()); + quoteIter++; + } + return quotedMessage; } -QByteArray CtcpParser::xdelimDequote(const QByteArray &message) { - QByteArray dequotedMessage; - QByteArray messagepart; - QHash::iterator xdelimquote; - - for(int i = 0; i < message.size(); i++) { - messagepart = message.mid(i,1); - if(i+1 < message.size()) { - for(xdelimquote = _ctcpXDelimDequoteHash.begin(); xdelimquote != _ctcpXDelimDequoteHash.end(); ++xdelimquote) { - if(message.mid(i,2) == xdelimquote.key()) { - messagepart = xdelimquote.value(); - i++; - break; + +QByteArray CtcpParser::xdelimDequote(const QByteArray &message) +{ + QByteArray dequotedMessage; + QByteArray messagepart; + QHash::iterator xdelimquote; + + for (int i = 0; i < message.size(); i++) { + messagepart = message.mid(i, 1); + if (i+1 < message.size()) { + for (xdelimquote = _ctcpXDelimDequoteHash.begin(); xdelimquote != _ctcpXDelimDequoteHash.end(); ++xdelimquote) { + if (message.mid(i, 2) == xdelimquote.key()) { + messagepart = xdelimquote.value(); + i++; + break; + } + } } - } + dequotedMessage += messagepart; } - dequotedMessage += messagepart; - } - return dequotedMessage; + return dequotedMessage; } -void CtcpParser::processIrcEventRawNotice(IrcEventRawMessage *event) { - parse(event, Message::Notice); + +void CtcpParser::processIrcEventRawNotice(IrcEventRawMessage *event) +{ + parse(event, Message::Notice); } -void CtcpParser::processIrcEventRawPrivmsg(IrcEventRawMessage *event) { - parse(event, Message::Plain); + +void CtcpParser::processIrcEventRawPrivmsg(IrcEventRawMessage *event) +{ + parse(event, Message::Plain); } -void CtcpParser::parse(IrcEventRawMessage *e, Message::Type messagetype) { - QByteArray ctcp; - //lowlevel message dequote - QByteArray dequotedMessage = lowLevelDequote(e->rawMessage()); +void CtcpParser::parse(IrcEventRawMessage *e, Message::Type messagetype) +{ + QByteArray ctcp; + + //lowlevel message dequote + QByteArray dequotedMessage = lowLevelDequote(e->rawMessage()); + + CtcpEvent::CtcpType ctcptype = e->type() == EventManager::IrcEventRawNotice + ? CtcpEvent::Reply + : CtcpEvent::Query; + + Message::Flags flags = (ctcptype == CtcpEvent::Reply && !e->network()->isChannelName(e->target())) + ? Message::Redirected + : Message::None; + + QList ctcpEvents; + QUuid uuid; // needed to group all replies together + + // extract tagged / extended data + int xdelimPos = -1; + int xdelimEndPos = -1; + int spacePos = -1; + while ((xdelimPos = dequotedMessage.indexOf(XDELIM)) != -1) { + if (xdelimPos > 0) + displayMsg(e, messagetype, targetDecode(e, dequotedMessage.left(xdelimPos)), e->prefix(), e->target(), flags); + + xdelimEndPos = dequotedMessage.indexOf(XDELIM, xdelimPos + 1); + if (xdelimEndPos == -1) { + // no matching end delimiter found... treat rest of the message as ctcp + xdelimEndPos = dequotedMessage.count(); + } + ctcp = xdelimDequote(dequotedMessage.mid(xdelimPos + 1, xdelimEndPos - xdelimPos - 1)); + dequotedMessage = dequotedMessage.mid(xdelimEndPos + 1); - CtcpEvent::CtcpType ctcptype = e->type() == EventManager::IrcEventRawNotice - ? CtcpEvent::Reply - : CtcpEvent::Query; + //dispatch the ctcp command + QString ctcpcmd = targetDecode(e, ctcp.left(spacePos)); + QString ctcpparam = targetDecode(e, ctcp.mid(spacePos + 1)); - Message::Flags flags = (ctcptype == CtcpEvent::Reply && !e->network()->isChannelName(e->target())) - ? Message::Redirected - : Message::None; + spacePos = ctcp.indexOf(' '); + if (spacePos != -1) { + ctcpcmd = targetDecode(e, ctcp.left(spacePos)); + ctcpparam = targetDecode(e, ctcp.mid(spacePos + 1)); + } + else { + ctcpcmd = targetDecode(e, ctcp); + ctcpparam = QString(); + } - QList ctcpEvents; - QUuid uuid; // needed to group all replies together + ctcpcmd = ctcpcmd.toUpper(); - // extract tagged / extended data - int xdelimPos = -1; - int xdelimEndPos = -1; - int spacePos = -1; - while((xdelimPos = dequotedMessage.indexOf(XDELIM)) != -1) { - if(xdelimPos > 0) - displayMsg(e, messagetype, targetDecode(e, dequotedMessage.left(xdelimPos)), e->prefix(), e->target(), flags); + // we don't want to block /me messages by the CTCP ignore list + if (ctcpcmd == QLatin1String("ACTION") || !coreSession()->ignoreListManager()->ctcpMatch(e->prefix(), e->network()->networkName(), ctcpcmd)) { + if (uuid.isNull()) + uuid = QUuid::createUuid(); - xdelimEndPos = dequotedMessage.indexOf(XDELIM, xdelimPos + 1); - if(xdelimEndPos == -1) { - // no matching end delimiter found... treat rest of the message as ctcp - xdelimEndPos = dequotedMessage.count(); + CtcpEvent *event = new CtcpEvent(EventManager::CtcpEvent, e->network(), e->prefix(), e->target(), + ctcptype, ctcpcmd, ctcpparam, e->timestamp(), uuid); + ctcpEvents << event; + } } - ctcp = xdelimDequote(dequotedMessage.mid(xdelimPos + 1, xdelimEndPos - xdelimPos - 1)); - dequotedMessage = dequotedMessage.mid(xdelimEndPos + 1); - - //dispatch the ctcp command - QString ctcpcmd = targetDecode(e, ctcp.left(spacePos)); - QString ctcpparam = targetDecode(e, ctcp.mid(spacePos + 1)); - - spacePos = ctcp.indexOf(' '); - if(spacePos != -1) { - ctcpcmd = targetDecode(e, ctcp.left(spacePos)); - ctcpparam = targetDecode(e, ctcp.mid(spacePos + 1)); - } else { - ctcpcmd = targetDecode(e, ctcp); - ctcpparam = QString(); + if (!ctcpEvents.isEmpty()) { + _replies.insert(uuid, CtcpReply(coreNetwork(e), nickFromMask(e->prefix()))); + CtcpEvent *flushEvent = new CtcpEvent(EventManager::CtcpEventFlush, e->network(), e->prefix(), e->target(), + ctcptype, "INVALID", QString(), e->timestamp(), uuid); + ctcpEvents << flushEvent; + foreach(CtcpEvent *event, ctcpEvents) { + emit newEvent(event); + } } - ctcpcmd = ctcpcmd.toUpper(); + if (!dequotedMessage.isEmpty()) + displayMsg(e, messagetype, targetDecode(e, dequotedMessage), e->prefix(), e->target(), flags); +} - // we don't want to block /me messages by the CTCP ignore list - if(ctcpcmd == QLatin1String("ACTION") || !coreSession()->ignoreListManager()->ctcpMatch(e->prefix(), e->network()->networkName(), ctcpcmd)) { - if(uuid.isNull()) - uuid = QUuid::createUuid(); - CtcpEvent *event = new CtcpEvent(EventManager::CtcpEvent, e->network(), e->prefix(), e->target(), - ctcptype, ctcpcmd, ctcpparam, e->timestamp(), uuid); - ctcpEvents << event; +void CtcpParser::sendCtcpEvent(CtcpEvent *e) +{ + CoreNetwork *net = coreNetwork(e); + if (e->type() == EventManager::CtcpEvent) { + QByteArray quotedReply; + QString bufname = nickFromMask(e->prefix()); + if (e->ctcpType() == CtcpEvent::Query && !e->reply().isNull()) { + if (_replies.contains(e->uuid())) + _replies[e->uuid()].replies << lowLevelQuote(pack(net->serverEncode(e->ctcpCmd()), + net->userEncode(bufname, e->reply()))); + else + // reply not caused by a request processed in here, so send it off immediately + reply(net, bufname, e->ctcpCmd(), e->reply()); + } } - } - if(!ctcpEvents.isEmpty()) { - _replies.insert(uuid, CtcpReply(coreNetwork(e), nickFromMask(e->prefix()))); - CtcpEvent *flushEvent = new CtcpEvent(EventManager::CtcpEventFlush, e->network(), e->prefix(), e->target(), - ctcptype, "INVALID", QString(), e->timestamp(), uuid); - ctcpEvents << flushEvent; - foreach(CtcpEvent *event, ctcpEvents) { - emit newEvent(event); + else if (e->type() == EventManager::CtcpEventFlush && _replies.contains(e->uuid())) { + CtcpReply reply = _replies.take(e->uuid()); + if (reply.replies.count()) + packedReply(net, reply.bufferName, reply.replies); } - } - - if(!dequotedMessage.isEmpty()) - displayMsg(e, messagetype, targetDecode(e, dequotedMessage), e->prefix(), e->target(), flags); } -void CtcpParser::sendCtcpEvent(CtcpEvent *e) { - CoreNetwork *net = coreNetwork(e); - if(e->type() == EventManager::CtcpEvent) { - QByteArray quotedReply; - QString bufname = nickFromMask(e->prefix()); - if(e->ctcpType() == CtcpEvent::Query && !e->reply().isNull()) { - if(_replies.contains(e->uuid())) - _replies[e->uuid()].replies << lowLevelQuote(pack(net->serverEncode(e->ctcpCmd()), - net->userEncode(bufname, e->reply()))); - else - // reply not caused by a request processed in here, so send it off immediately - reply(net, bufname, e->ctcpCmd(), e->reply()); - } - } else if(e->type() == EventManager::CtcpEventFlush && _replies.contains(e->uuid())) { - CtcpReply reply = _replies.take(e->uuid()); - if(reply.replies.count()) - packedReply(net, reply.bufferName, reply.replies); - } -} -QByteArray CtcpParser::pack(const QByteArray &ctcpTag, const QByteArray &message) { - if(message.isEmpty()) - return XDELIM + ctcpTag + XDELIM; +QByteArray CtcpParser::pack(const QByteArray &ctcpTag, const QByteArray &message) +{ + if (message.isEmpty()) + return XDELIM + ctcpTag + XDELIM; - return XDELIM + ctcpTag + ' ' + xdelimQuote(message) + XDELIM; + return XDELIM + ctcpTag + ' ' + xdelimQuote(message) + XDELIM; } -void CtcpParser::query(CoreNetwork *net, const QString &bufname, const QString &ctcpTag, const QString &message) { - QList params; - params << net->serverEncode(bufname) << lowLevelQuote(pack(net->serverEncode(ctcpTag), net->userEncode(bufname, message))); - net->putCmd("PRIVMSG", params); + +void CtcpParser::query(CoreNetwork *net, const QString &bufname, const QString &ctcpTag, const QString &message) +{ + QList params; + params << net->serverEncode(bufname) << lowLevelQuote(pack(net->serverEncode(ctcpTag), net->userEncode(bufname, message))); + net->putCmd("PRIVMSG", params); } -void CtcpParser::reply(CoreNetwork *net, const QString &bufname, const QString &ctcpTag, const QString &message) { - QList params; - params << net->serverEncode(bufname) << lowLevelQuote(pack(net->serverEncode(ctcpTag), net->userEncode(bufname, message))); - net->putCmd("NOTICE", params); + +void CtcpParser::reply(CoreNetwork *net, const QString &bufname, const QString &ctcpTag, const QString &message) +{ + QList params; + params << net->serverEncode(bufname) << lowLevelQuote(pack(net->serverEncode(ctcpTag), net->userEncode(bufname, message))); + net->putCmd("NOTICE", params); } -void CtcpParser::packedReply(CoreNetwork *net, const QString &bufname, const QList &replies) { - QList params; - int answerSize = 0; - for(int i = 0; i < replies.count(); i++) { - answerSize += replies.at(i).size(); - } +void CtcpParser::packedReply(CoreNetwork *net, const QString &bufname, const QList &replies) +{ + QList params; - QByteArray quotedReply; - quotedReply.reserve(answerSize); - for(int i = 0; i < replies.count(); i++) { - quotedReply.append(replies.at(i)); - } + int answerSize = 0; + for (int i = 0; i < replies.count(); i++) { + answerSize += replies.at(i).size(); + } + + QByteArray quotedReply; + quotedReply.reserve(answerSize); + for (int i = 0; i < replies.count(); i++) { + quotedReply.append(replies.at(i)); + } - params << net->serverEncode(bufname) << quotedReply; - // FIXME user proper event - net->putCmd("NOTICE", params); + params << net->serverEncode(bufname) << quotedReply; + // FIXME user proper event + net->putCmd("NOTICE", params); } diff --git a/src/core/ctcpparser.h b/src/core/ctcpparser.h index 634658c0..07a90954 100644 --- a/src/core/ctcpparser.h +++ b/src/core/ctcpparser.h @@ -30,65 +30,67 @@ class CoreSession; class CtcpEvent; -class CtcpParser : public QObject { - Q_OBJECT +class CtcpParser : public QObject +{ + Q_OBJECT public: - CtcpParser(CoreSession *coreSession, QObject *parent = 0); + CtcpParser(CoreSession *coreSession, QObject *parent = 0); - inline CoreSession *coreSession() const { return _coreSession; } + inline CoreSession *coreSession() const { return _coreSession; } - void query(CoreNetwork *network, const QString &bufname, const QString &ctcpTag, const QString &message); - void reply(CoreNetwork *network, const QString &bufname, const QString &ctcpTag, const QString &message); + void query(CoreNetwork *network, const QString &bufname, const QString &ctcpTag, const QString &message); + void reply(CoreNetwork *network, const QString &bufname, const QString &ctcpTag, const QString &message); - Q_INVOKABLE void processIrcEventRawNotice(IrcEventRawMessage *event); - Q_INVOKABLE void processIrcEventRawPrivmsg(IrcEventRawMessage *event); + Q_INVOKABLE void processIrcEventRawNotice(IrcEventRawMessage *event); + Q_INVOKABLE void processIrcEventRawPrivmsg(IrcEventRawMessage *event); - Q_INVOKABLE void sendCtcpEvent(CtcpEvent *event); + Q_INVOKABLE void sendCtcpEvent(CtcpEvent *event); signals: - void newEvent(Event *event); + void newEvent(Event *event); protected: - inline CoreNetwork *coreNetwork(NetworkEvent *e) const { return qobject_cast(e->network()); } + inline CoreNetwork *coreNetwork(NetworkEvent *e) const { return qobject_cast(e->network()); } - // FIXME duplicates functionality in EventStringifier, maybe want to put that in something common - //! Creates and sends a MessageEvent - void displayMsg(NetworkEvent *event, - Message::Type msgType, - const QString &msg, - const QString &sender = QString(), - const QString &target = QString(), - Message::Flags msgFlags = Message::None); + // FIXME duplicates functionality in EventStringifier, maybe want to put that in something common + //! Creates and sends a MessageEvent + void displayMsg(NetworkEvent *event, + Message::Type msgType, + const QString &msg, + const QString &sender = QString(), + const QString &target = QString(), + Message::Flags msgFlags = Message::None); - void parse(IrcEventRawMessage *event, Message::Type msgType); + void parse(IrcEventRawMessage *event, Message::Type msgType); - QByteArray lowLevelQuote(const QByteArray &); - QByteArray lowLevelDequote(const QByteArray &); - QByteArray xdelimQuote(const QByteArray &); - QByteArray xdelimDequote(const QByteArray &); + QByteArray lowLevelQuote(const QByteArray &); + QByteArray lowLevelDequote(const QByteArray &); + QByteArray xdelimQuote(const QByteArray &); + QByteArray xdelimDequote(const QByteArray &); - QByteArray pack(const QByteArray &ctcpTag, const QByteArray &message); - void packedReply(CoreNetwork *network, const QString &bufname, const QList &replies); + QByteArray pack(const QByteArray &ctcpTag, const QByteArray &message); + void packedReply(CoreNetwork *network, const QString &bufname, const QList &replies); private: - inline QString targetDecode(IrcEventRawMessage *e, const QByteArray &msg) { return coreNetwork(e)->userDecode(e->target(), msg); } + inline QString targetDecode(IrcEventRawMessage *e, const QByteArray &msg) { return coreNetwork(e)->userDecode(e->target(), msg); } - CoreSession *_coreSession; + CoreSession *_coreSession; - struct CtcpReply { - CoreNetwork *network; - QString bufferName; - QList replies; + struct CtcpReply { + CoreNetwork *network; + QString bufferName; + QList replies; - CtcpReply() : network(0) {} - CtcpReply(CoreNetwork *net, const QString &buf) : network(net), bufferName(buf) {} - }; + CtcpReply() : network(0) {} + CtcpReply(CoreNetwork *net, const QString &buf) : network(net), bufferName(buf) {} + }; - QHash _replies; + QHash _replies; - QHash _ctcpMDequoteHash; - QHash _ctcpXDelimDequoteHash; + QHash _ctcpMDequoteHash; + QHash _ctcpXDelimDequoteHash; }; + #endif diff --git a/src/core/eventstringifier.cpp b/src/core/eventstringifier.cpp index 77c7c526..947317a0 100644 --- a/src/core/eventstringifier.cpp +++ b/src/core/eventstringifier.cpp @@ -25,267 +25,371 @@ #include "messageevent.h" EventStringifier::EventStringifier(CoreSession *parent) : BasicHandler("handleCtcp", parent), - _coreSession(parent), - _whois(false) + _coreSession(parent), + _whois(false) { - connect(this, SIGNAL(newMessageEvent(Event *)), coreSession()->eventManager(), SLOT(postEvent(Event *))); + connect(this, SIGNAL(newMessageEvent(Event *)), coreSession()->eventManager(), SLOT(postEvent(Event *))); } + void EventStringifier::displayMsg(NetworkEvent *event, Message::Type msgType, const QString &msg, const QString &sender, - const QString &target, Message::Flags msgFlags) { - if(event->flags().testFlag(EventManager::Silent)) - return; + const QString &target, Message::Flags msgFlags) +{ + if (event->flags().testFlag(EventManager::Silent)) + return; - MessageEvent *msgEvent = createMessageEvent(event, msgType, msg, sender, target, msgFlags); - //sendMessageEvent(msgEvent); - emit newMessageEvent(msgEvent); + MessageEvent *msgEvent = createMessageEvent(event, msgType, msg, sender, target, msgFlags); + //sendMessageEvent(msgEvent); + emit newMessageEvent(msgEvent); } + MessageEvent *EventStringifier::createMessageEvent(NetworkEvent *event, Message::Type msgType, const QString &msg, const QString &sender, - const QString &target, Message::Flags msgFlags) { - MessageEvent *msgEvent = new MessageEvent(msgType, event->network(), msg, sender, target, msgFlags); - msgEvent->setTimestamp(event->timestamp()); - return msgEvent; -} - -bool EventStringifier::checkParamCount(IrcEvent *e, int minParams) { - if(e->params().count() < minParams) { - if(e->type() == EventManager::IrcEventNumeric) { - qWarning() << "Command " << static_cast(e)->number() << " requires " << minParams << "params, got: " << e->params(); - } else { - QString name = coreSession()->eventManager()->enumName(e->type()); - qWarning() << qPrintable(name) << "requires" << minParams << "params, got:" << e->params(); + const QString &target, Message::Flags msgFlags) +{ + MessageEvent *msgEvent = new MessageEvent(msgType, event->network(), msg, sender, target, msgFlags); + msgEvent->setTimestamp(event->timestamp()); + return msgEvent; +} + + +bool EventStringifier::checkParamCount(IrcEvent *e, int minParams) +{ + if (e->params().count() < minParams) { + if (e->type() == EventManager::IrcEventNumeric) { + qWarning() << "Command " << static_cast(e)->number() << " requires " << minParams << "params, got: " << e->params(); + } + else { + QString name = coreSession()->eventManager()->enumName(e->type()); + qWarning() << qPrintable(name) << "requires" << minParams << "params, got:" << e->params(); + } + e->stop(); + return false; } - e->stop(); - return false; - } - return true; + return true; } + /* These are only for legacy reasons; remove as soon as we handle NetworkSplitEvents properly */ -void EventStringifier::processNetworkSplitJoin(NetworkSplitEvent *e) { - QString msg = e->users().join("#:#") + "#:#" + e->quitMessage(); - displayMsg(e, Message::NetsplitJoin, msg, QString(), e->channel()); +void EventStringifier::processNetworkSplitJoin(NetworkSplitEvent *e) +{ + QString msg = e->users().join("#:#") + "#:#" + e->quitMessage(); + displayMsg(e, Message::NetsplitJoin, msg, QString(), e->channel()); } -void EventStringifier::processNetworkSplitQuit(NetworkSplitEvent *e) { - QString msg = e->users().join("#:#") + "#:#" + e->quitMessage(); - displayMsg(e, Message::NetsplitQuit, msg, QString(), e->channel()); + +void EventStringifier::processNetworkSplitQuit(NetworkSplitEvent *e) +{ + QString msg = e->users().join("#:#") + "#:#" + e->quitMessage(); + displayMsg(e, Message::NetsplitQuit, msg, QString(), e->channel()); } + /* End legacy */ -void EventStringifier::processIrcEventNumeric(IrcEventNumeric *e) { - //qDebug() << e->number(); - switch(e->number()) { - // Welcome, status, info messages. Just display these. - case 1: case 2: case 3: case 4: case 5: - case 221: case 250: case 251: case 252: case 253: case 254: case 255: case 265: case 266: - case 372: case 375: - displayMsg(e, Message::Server, e->params().join(" "), e->prefix()); - break; - - // Server error messages without param, just display them - case 409: case 411: case 412: case 422: case 424: case 445: case 446: case 451: case 462: - case 463: case 464: case 465: case 466: case 472: case 481: case 483: case 485: case 491: case 501: case 502: - case 431: // ERR_NONICKNAMEGIVEN - displayMsg(e, Message::Error, e->params().join(" "), e->prefix()); - break; - - // Server error messages, display them in red. Colon between first param and rest. - case 401: { - if(!checkParamCount(e, 1)) - return; - - QStringList params = e->params(); - QString target = params.takeFirst(); - displayMsg(e, Message::Error, target + ": " + params.join(" "), e->prefix(), target, Message::Redirected); - break; - } - - case 402: case 403: case 404: case 406: case 408: case 415: case 421: case 442: { - if(!checkParamCount(e, 1)) - return; - - QStringList params = e->params(); - QString channelName = params.takeFirst(); - displayMsg(e, Message::Error, channelName + ": " + params.join(" "), e->prefix()); - break; - } - - // Server error messages which will be displayed with a colon between the first param and the rest - case 413: case 414: case 423: case 441: case 444: case 461: // FIXME see below for the 47x codes - case 467: case 471: case 473: case 474: case 475: case 476: case 477: case 478: case 482: - case 436: // ERR_NICKCOLLISION - { - if(!checkParamCount(e, 1)) - return; - - QStringList params = e->params(); - QString p = params.takeFirst(); - displayMsg(e, Message::Error, p + ": " + params.join(" ")); - break; - } - - // Ignore these commands. - case 321: case 353: case 366: case 376: - break; - - // CAP stuff - case 900: case 903: case 904: case 905: case 906: case 907: - { - displayMsg(e, Message::Info, "CAP: " + e->params().join("")); - break; - } - - // Everything else will be marked in red, so we can add them somewhere. - default: - if(_whois) { - // many nets define their own WHOIS fields. we fetch those not in need of special attention here: - displayMsg(e, Message::Server, tr("[Whois] ") + e->params().join(" "), e->prefix()); - } else { - // FIXME figure out how/where to do this in the future - //if(coreSession()->ircListHelper()->requestInProgress(network()->networkId())) - // coreSession()->ircListHelper()->reportError(params.join(" ")); - //else - displayMsg(e, Message::Error, QString("%1 %2").arg(e->number(), 3, 10, QLatin1Char('0')).arg(e->params().join(" ")), e->prefix()); +void EventStringifier::processIrcEventNumeric(IrcEventNumeric *e) +{ + //qDebug() << e->number(); + switch (e->number()) { + // Welcome, status, info messages. Just display these. + case 1: + case 2: + case 3: + case 4: + case 5: + case 221: + case 250: + case 251: + case 252: + case 253: + case 254: + case 255: + case 265: + case 266: + case 372: + case 375: + displayMsg(e, Message::Server, e->params().join(" "), e->prefix()); + break; + + // Server error messages without param, just display them + case 409: + case 411: + case 412: + case 422: + case 424: + case 445: + case 446: + case 451: + case 462: + case 463: + case 464: + case 465: + case 466: + case 472: + case 481: + case 483: + case 485: + case 491: + case 501: + case 502: + case 431: // ERR_NONICKNAMEGIVEN + displayMsg(e, Message::Error, e->params().join(" "), e->prefix()); + break; + + // Server error messages, display them in red. Colon between first param and rest. + case 401: + { + if (!checkParamCount(e, 1)) + return; + + QStringList params = e->params(); + QString target = params.takeFirst(); + displayMsg(e, Message::Error, target + ": " + params.join(" "), e->prefix(), target, Message::Redirected); + break; + } + + case 402: + case 403: + case 404: + case 406: + case 408: + case 415: + case 421: + case 442: + { + if (!checkParamCount(e, 1)) + return; + + QStringList params = e->params(); + QString channelName = params.takeFirst(); + displayMsg(e, Message::Error, channelName + ": " + params.join(" "), e->prefix()); + break; + } + + // Server error messages which will be displayed with a colon between the first param and the rest + case 413: + case 414: + case 423: + case 441: + case 444: + case 461: // FIXME see below for the 47x codes + case 467: + case 471: + case 473: + case 474: + case 475: + case 476: + case 477: + case 478: + case 482: + case 436: // ERR_NICKCOLLISION + { + if (!checkParamCount(e, 1)) + return; + + QStringList params = e->params(); + QString p = params.takeFirst(); + displayMsg(e, Message::Error, p + ": " + params.join(" ")); + break; + } + + // Ignore these commands. + case 321: + case 353: + case 366: + case 376: + break; + + // CAP stuff + case 900: + case 903: + case 904: + case 905: + case 906: + case 907: + { + displayMsg(e, Message::Info, "CAP: " + e->params().join("")); + break; + } + + // Everything else will be marked in red, so we can add them somewhere. + default: + if (_whois) { + // many nets define their own WHOIS fields. we fetch those not in need of special attention here: + displayMsg(e, Message::Server, tr("[Whois] ") + e->params().join(" "), e->prefix()); + } + else { + // FIXME figure out how/where to do this in the future + //if(coreSession()->ircListHelper()->requestInProgress(network()->networkId())) + // coreSession()->ircListHelper()->reportError(params.join(" ")); + //else + displayMsg(e, Message::Error, QString("%1 %2").arg(e->number(), 3, 10, QLatin1Char('0')).arg(e->params().join(" ")), e->prefix()); + } } - } } -void EventStringifier::processIrcEventInvite(IrcEvent *e) { - displayMsg(e, Message::Invite, tr("%1 invited you to channel %2").arg(e->nick(), e->params().at(1))); + +void EventStringifier::processIrcEventInvite(IrcEvent *e) +{ + displayMsg(e, Message::Invite, tr("%1 invited you to channel %2").arg(e->nick(), e->params().at(1))); } -void EventStringifier::processIrcEventJoin(IrcEvent *e) { - if(e->testFlag(EventManager::Netsplit)) - return; - displayMsg(e, Message::Join, e->params()[0], e->prefix(), e->params()[0]); +void EventStringifier::processIrcEventJoin(IrcEvent *e) +{ + if (e->testFlag(EventManager::Netsplit)) + return; + + displayMsg(e, Message::Join, e->params()[0], e->prefix(), e->params()[0]); } -void EventStringifier::processIrcEventKick(IrcEvent *e) { - if(!checkParamCount(e, 2)) - return; - IrcUser *victim = e->network()->ircUser(e->params().at(1)); - if(victim) { - QString channel = e->params().at(0); - QString msg = victim->nick(); - if(e->params().count() > 2) - msg += " " + e->params().at(2); +void EventStringifier::processIrcEventKick(IrcEvent *e) +{ + if (!checkParamCount(e, 2)) + return; + + IrcUser *victim = e->network()->ircUser(e->params().at(1)); + if (victim) { + QString channel = e->params().at(0); + QString msg = victim->nick(); + if (e->params().count() > 2) + msg += " " + e->params().at(2); - displayMsg(e, Message::Kick, msg, e->prefix(), channel); - } + displayMsg(e, Message::Kick, msg, e->prefix(), channel); + } } -void EventStringifier::processIrcEventMode(IrcEvent *e) { - if(e->network()->isChannelName(e->params().first())) { - // Channel Modes - displayMsg(e, Message::Mode, e->params().join(" "), e->prefix(), e->params().first()); - } else { - // User Modes - // FIXME: redirect - displayMsg(e, Message::Mode, e->params().join(" "), e->prefix()); - } + +void EventStringifier::processIrcEventMode(IrcEvent *e) +{ + if (e->network()->isChannelName(e->params().first())) { + // Channel Modes + displayMsg(e, Message::Mode, e->params().join(" "), e->prefix(), e->params().first()); + } + else { + // User Modes + // FIXME: redirect + displayMsg(e, Message::Mode, e->params().join(" "), e->prefix()); + } } + // this needs to be called before the ircuser is renamed! -void EventStringifier::processIrcEventNick(IrcEvent *e) { - if(!checkParamCount(e, 1)) - return; +void EventStringifier::processIrcEventNick(IrcEvent *e) +{ + if (!checkParamCount(e, 1)) + return; - IrcUser *ircuser = e->network()->updateNickFromMask(e->prefix()); - if(!ircuser) { - qWarning() << Q_FUNC_INFO << "Unknown IrcUser!"; - return; - } + IrcUser *ircuser = e->network()->updateNickFromMask(e->prefix()); + if (!ircuser) { + qWarning() << Q_FUNC_INFO << "Unknown IrcUser!"; + return; + } - QString newnick = e->params().at(0); - QString oldnick = ircuser->nick(); + QString newnick = e->params().at(0); + QString oldnick = ircuser->nick(); - QString sender = e->network()->isMyNick(oldnick) ? newnick : e->prefix(); - foreach(const QString &channel, ircuser->channels()) + QString sender = e->network()->isMyNick(oldnick) ? newnick : e->prefix(); + foreach(const QString &channel, ircuser->channels()) displayMsg(e, Message::Nick, newnick, sender, channel); } -void EventStringifier::processIrcEventPart(IrcEvent *e) { - if(!checkParamCount(e, 1)) - return; - QString channel = e->params().at(0); - QString msg = e->params().count() > 1? e->params().at(1) : QString(); +void EventStringifier::processIrcEventPart(IrcEvent *e) +{ + if (!checkParamCount(e, 1)) + return; - displayMsg(e, Message::Part, msg, e->prefix(), channel); + QString channel = e->params().at(0); + QString msg = e->params().count() > 1 ? e->params().at(1) : QString(); + + displayMsg(e, Message::Part, msg, e->prefix(), channel); } -void EventStringifier::processIrcEventPong(IrcEvent *e) { - QString timestamp = e->params().at(1); - QTime sendTime = QTime::fromString(timestamp, "hh:mm:ss.zzz"); - if(!sendTime.isValid()) - displayMsg(e, Message::Server, "PONG " + e->params().join(" "), e->prefix()); + +void EventStringifier::processIrcEventPong(IrcEvent *e) +{ + QString timestamp = e->params().at(1); + QTime sendTime = QTime::fromString(timestamp, "hh:mm:ss.zzz"); + if (!sendTime.isValid()) + displayMsg(e, Message::Server, "PONG " + e->params().join(" "), e->prefix()); } -void EventStringifier::processIrcEventQuit(IrcEvent *e) { - if(e->testFlag(EventManager::Netsplit)) - return; - IrcUser *ircuser = e->network()->updateNickFromMask(e->prefix()); - if(!ircuser) - return; +void EventStringifier::processIrcEventQuit(IrcEvent *e) +{ + if (e->testFlag(EventManager::Netsplit)) + return; + + IrcUser *ircuser = e->network()->updateNickFromMask(e->prefix()); + if (!ircuser) + return; - foreach(const QString &channel, ircuser->channels()) - displayMsg(e, Message::Quit, e->params().count()? e->params().first() : QString(), e->prefix(), channel); + foreach(const QString &channel, ircuser->channels()) + displayMsg(e, Message::Quit, e->params().count() ? e->params().first() : QString(), e->prefix(), channel); } -void EventStringifier::processIrcEventTopic(IrcEvent *e) { - displayMsg(e, Message::Topic, tr("%1 has changed topic for %2 to: \"%3\"") - .arg(e->nick(), e->params().at(0), e->params().at(1)), QString(), e->params().at(0)); + +void EventStringifier::processIrcEventTopic(IrcEvent *e) +{ + displayMsg(e, Message::Topic, tr("%1 has changed topic for %2 to: \"%3\"") + .arg(e->nick(), e->params().at(0), e->params().at(1)), QString(), e->params().at(0)); } + /* RPL_ISUPPORT */ -void EventStringifier::processIrcEvent005(IrcEvent *e) { - if(!e->params().last().contains(QRegExp("are supported (by|on) this server"))) - displayMsg(e, Message::Error, tr("Received non-RFC-compliant RPL_ISUPPORT: this can lead to unexpected behavior!"), e->prefix()); - displayMsg(e, Message::Server, e->params().join(" "), e->prefix()); +void EventStringifier::processIrcEvent005(IrcEvent *e) +{ + if (!e->params().last().contains(QRegExp("are supported (by|on) this server"))) + displayMsg(e, Message::Error, tr("Received non-RFC-compliant RPL_ISUPPORT: this can lead to unexpected behavior!"), e->prefix()); + displayMsg(e, Message::Server, e->params().join(" "), e->prefix()); } + /* RPL_AWAY - " :" */ -void EventStringifier::processIrcEvent301(IrcEvent *e) { - QString nick = e->params().at(0); - QString awayMsg = e->params().at(1); - QString msg, target; - bool send = true; - - // FIXME: proper redirection needed - if(_whois) { - msg = tr("[Whois] "); - } else { - target = nick; - IrcUser *ircuser = e->network()->ircUser(nick); - if(ircuser) { - int now = QDateTime::currentDateTime().toTime_t(); - const int silenceTime = 60; - if(ircuser->lastAwayMessage() + silenceTime >= now) - send = false; - ircuser->setLastAwayMessage(now); +void EventStringifier::processIrcEvent301(IrcEvent *e) +{ + QString nick = e->params().at(0); + QString awayMsg = e->params().at(1); + QString msg, target; + bool send = true; + + // FIXME: proper redirection needed + if (_whois) { + msg = tr("[Whois] "); } - } - if(send) - displayMsg(e, Message::Server, msg + tr("%1 is away: \"%2\"").arg(nick, awayMsg), QString(), target); + else { + target = nick; + IrcUser *ircuser = e->network()->ircUser(nick); + if (ircuser) { + int now = QDateTime::currentDateTime().toTime_t(); + const int silenceTime = 60; + if (ircuser->lastAwayMessage() + silenceTime >= now) + send = false; + ircuser->setLastAwayMessage(now); + } + } + if (send) + displayMsg(e, Message::Server, msg + tr("%1 is away: \"%2\"").arg(nick, awayMsg), QString(), target); } + /* RPL_UNAWAY - ":You are no longer marked as being away" */ -void EventStringifier::processIrcEvent305(IrcEvent *e) { - displayMsg(e, Message::Server, tr("You are no longer marked as being away")); +void EventStringifier::processIrcEvent305(IrcEvent *e) +{ + displayMsg(e, Message::Server, tr("You are no longer marked as being away")); } + /* RPL_NOWAWAY - ":You have been marked as being away" */ -void EventStringifier::processIrcEvent306(IrcEvent *e) { - if(!e->network()->autoAwayActive()) - displayMsg(e, Message::Server, tr("You have been marked as being away")); +void EventStringifier::processIrcEvent306(IrcEvent *e) +{ + if (!e->network()->autoAwayActive()) + displayMsg(e, Message::Server, tr("You have been marked as being away")); } + /* WHOIS-Message: Replies 311 - 313, 317 - 319 are all replies generated in response to a WHOIS message. @@ -300,220 +404,265 @@ WHOWAS-Message: */ /* RPL_WHOISUSER - " * :" */ -void EventStringifier::processIrcEvent311(IrcEvent *e) { - _whois = true; +void EventStringifier::processIrcEvent311(IrcEvent *e) +{ + _whois = true; - const QString whoisUserString = tr("[Whois] %1 is %2 (%3)"); + const QString whoisUserString = tr("[Whois] %1 is %2 (%3)"); - IrcUser *ircuser = e->network()->ircUser(e->params().at(0)); - if(ircuser) - displayMsg(e, Message::Server, whoisUserString.arg(ircuser->nick(), ircuser->hostmask(), ircuser->realName())); - else { - QString host = QString("%1!%2@%3").arg(e->params().at(0), e->params().at(1), e->params().at(2)); - displayMsg(e, Message::Server, whoisUserString.arg(e->params().at(0), host, e->params().last())); - } + IrcUser *ircuser = e->network()->ircUser(e->params().at(0)); + if (ircuser) + displayMsg(e, Message::Server, whoisUserString.arg(ircuser->nick(), ircuser->hostmask(), ircuser->realName())); + else { + QString host = QString("%1!%2@%3").arg(e->params().at(0), e->params().at(1), e->params().at(2)); + displayMsg(e, Message::Server, whoisUserString.arg(e->params().at(0), host, e->params().last())); + } } + /* RPL_WHOISSERVER - " :" */ -void EventStringifier::processIrcEvent312(IrcEvent *e) { - if(_whois) - displayMsg(e, Message::Server, tr("[Whois] %1 is online via %2 (%3)").arg(e->params().at(0), e->params().at(1), e->params().last())); - else - displayMsg(e, Message::Server, tr("[Whowas] %1 was online via %2 (%3)").arg(e->params().at(0), e->params().at(1), e->params().last())); +void EventStringifier::processIrcEvent312(IrcEvent *e) +{ + if (_whois) + displayMsg(e, Message::Server, tr("[Whois] %1 is online via %2 (%3)").arg(e->params().at(0), e->params().at(1), e->params().last())); + else + displayMsg(e, Message::Server, tr("[Whowas] %1 was online via %2 (%3)").arg(e->params().at(0), e->params().at(1), e->params().last())); } + /* RPL_WHOWASUSER - " * :" */ -void EventStringifier::processIrcEvent314(IrcEvent *e) { - if(!checkParamCount(e, 3)) - return; +void EventStringifier::processIrcEvent314(IrcEvent *e) +{ + if (!checkParamCount(e, 3)) + return; - displayMsg(e, Message::Server, tr("[Whowas] %1 was %2@%3 (%4)").arg(e->params()[0], e->params()[1], e->params()[2], e->params().last())); + displayMsg(e, Message::Server, tr("[Whowas] %1 was %2@%3 (%4)").arg(e->params()[0], e->params()[1], e->params()[2], e->params().last())); } + /* RPL_ENDOFWHO: " :End of WHO list" */ -void EventStringifier::processIrcEvent315(IrcEvent *e) { - QStringList p = e->params(); - p.takeLast(); // should be "End of WHO list" - displayMsg(e, Message::Server, tr("[Who] End of /WHO list for %1").arg(p.join(" "))); +void EventStringifier::processIrcEvent315(IrcEvent *e) +{ + QStringList p = e->params(); + p.takeLast(); // should be "End of WHO list" + displayMsg(e, Message::Server, tr("[Who] End of /WHO list for %1").arg(p.join(" "))); } + /* RPL_WHOISIDLE - " :seconds idle" (real life: " :seconds idle, signon time) */ -void EventStringifier::processIrcEvent317(IrcEvent *e) { - int idleSecs = e->params()[1].toInt(); +void EventStringifier::processIrcEvent317(IrcEvent *e) +{ + int idleSecs = e->params()[1].toInt(); - if(e->params().count() > 3) { // if we have more then 3 params we have the above mentioned "real life" situation - QDateTime loginTime = QDateTime::fromTime_t(e->params()[2].toInt()); - displayMsg(e, Message::Server, tr("[Whois] %1 is logged in since %2").arg(e->params()[0], loginTime.toString())); - } - displayMsg(e, Message::Server, tr("[Whois] %1 is idling for %2 (since %3)") - .arg(e->params()[0], secondsToString(idleSecs), e->timestamp().toLocalTime().addSecs(-idleSecs).toString())); + if (e->params().count() > 3) { // if we have more then 3 params we have the above mentioned "real life" situation + QDateTime loginTime = QDateTime::fromTime_t(e->params()[2].toInt()); + displayMsg(e, Message::Server, tr("[Whois] %1 is logged in since %2").arg(e->params()[0], loginTime.toString())); + } + displayMsg(e, Message::Server, tr("[Whois] %1 is idling for %2 (since %3)") + .arg(e->params()[0], secondsToString(idleSecs), e->timestamp().toLocalTime().addSecs(-idleSecs).toString())); } + /* RPL_ENDOFWHOIS - " :End of WHOIS list" */ -void EventStringifier::processIrcEvent318(IrcEvent *e) { - _whois = false; - displayMsg(e, Message::Server, tr("[Whois] End of /WHOIS list")); +void EventStringifier::processIrcEvent318(IrcEvent *e) +{ + _whois = false; + displayMsg(e, Message::Server, tr("[Whois] End of /WHOIS list")); } + /* RPL_WHOISCHANNELS - " :*( ( "@" / "+" ) " " )" */ -void EventStringifier::processIrcEvent319(IrcEvent *e) { - if(!checkParamCount(e, 2)) - return; - - QString nick = e->params().first(); - QStringList op; - QStringList voice; - QStringList user; - foreach(QString channel, e->params().last().split(" ")) { - if(channel.startsWith("@")) - op.append(channel.remove(0,1)); - else if(channel.startsWith("+")) - voice.append(channel.remove(0,1)); - else - user.append(channel); - } - if(!user.isEmpty()) - displayMsg(e, Message::Server, tr("[Whois] %1 is a user on channels: %2").arg(nick, user.join(" "))); - if(!voice.isEmpty()) - displayMsg(e, Message::Server, tr("[Whois] %1 has voice on channels: %2").arg(nick, voice.join(" "))); - if(!op.isEmpty()) - displayMsg(e, Message::Server, tr("[Whois] %1 is an operator on channels: %2").arg(nick, op.join(" "))); +void EventStringifier::processIrcEvent319(IrcEvent *e) +{ + if (!checkParamCount(e, 2)) + return; + + QString nick = e->params().first(); + QStringList op; + QStringList voice; + QStringList user; + foreach(QString channel, e->params().last().split(" ")) { + if (channel.startsWith("@")) + op.append(channel.remove(0, 1)); + else if (channel.startsWith("+")) + voice.append(channel.remove(0, 1)); + else + user.append(channel); + } + if (!user.isEmpty()) + displayMsg(e, Message::Server, tr("[Whois] %1 is a user on channels: %2").arg(nick, user.join(" "))); + if (!voice.isEmpty()) + displayMsg(e, Message::Server, tr("[Whois] %1 has voice on channels: %2").arg(nick, voice.join(" "))); + if (!op.isEmpty()) + displayMsg(e, Message::Server, tr("[Whois] %1 is an operator on channels: %2").arg(nick, op.join(" "))); } + /* RPL_LIST - " <# visible> :" */ -void EventStringifier::processIrcEvent322(IrcEvent *e) { - QString channelName; - quint32 userCount = 0; - QString topic; - - switch(e->params().count()) { - case 3: - topic = e->params()[2]; - case 2: - userCount = e->params()[1].toUInt(); - case 1: - channelName = e->params()[0]; - default: - break; - } - displayMsg(e, Message::Server, tr("Channel %1 has %2 users. Topic is: \"%3\"") - .arg(channelName).arg(userCount).arg(topic)); +void EventStringifier::processIrcEvent322(IrcEvent *e) +{ + QString channelName; + quint32 userCount = 0; + QString topic; + + switch (e->params().count()) { + case 3: + topic = e->params()[2]; + case 2: + userCount = e->params()[1].toUInt(); + case 1: + channelName = e->params()[0]; + default: + break; + } + displayMsg(e, Message::Server, tr("Channel %1 has %2 users. Topic is: \"%3\"") + .arg(channelName).arg(userCount).arg(topic)); } + /* RPL_LISTEND ":End of LIST" */ -void EventStringifier::processIrcEvent323(IrcEvent *e) { - displayMsg(e, Message::Server, tr("End of channel list")); +void EventStringifier::processIrcEvent323(IrcEvent *e) +{ + displayMsg(e, Message::Server, tr("End of channel list")); } + /* RPL_CHANNELMODEIS - " " */ -void EventStringifier::processIrcEvent324(IrcEvent *e) { - processIrcEventMode(e); +void EventStringifier::processIrcEvent324(IrcEvent *e) +{ + processIrcEventMode(e); } + /* RPL_??? - " */ -void EventStringifier::processIrcEvent328(IrcEvent *e) { - if(!checkParamCount(e, 2)) - return; +void EventStringifier::processIrcEvent328(IrcEvent *e) +{ + if (!checkParamCount(e, 2)) + return; - QString channel = e->params()[0]; - displayMsg(e, Message::Topic, tr("Homepage for %1 is %2").arg(channel, e->params()[1]), QString(), channel); + QString channel = e->params()[0]; + displayMsg(e, Message::Topic, tr("Homepage for %1 is %2").arg(channel, e->params()[1]), QString(), channel); } -/* RPL_??? - " " */ -void EventStringifier::processIrcEvent329(IrcEvent *e) { - if(!checkParamCount(e, 2)) - return; - QString channel = e->params()[0]; - uint unixtime = e->params()[1].toUInt(); - if(!unixtime) { - qWarning() << Q_FUNC_INFO << "received invalid timestamp:" << e->params()[1]; - return; - } - QDateTime time = QDateTime::fromTime_t(unixtime); - displayMsg(e, Message::Topic, tr("Channel %1 created on %2").arg(channel, time.toString()), QString(), channel); +/* RPL_??? - " " */ +void EventStringifier::processIrcEvent329(IrcEvent *e) +{ + if (!checkParamCount(e, 2)) + return; + + QString channel = e->params()[0]; + uint unixtime = e->params()[1].toUInt(); + if (!unixtime) { + qWarning() << Q_FUNC_INFO << "received invalid timestamp:" << e->params()[1]; + return; + } + QDateTime time = QDateTime::fromTime_t(unixtime); + displayMsg(e, Message::Topic, tr("Channel %1 created on %2").arg(channel, time.toString()), QString(), channel); } + /* RPL_WHOISACCOUNT: " :is authed as */ -void EventStringifier::processIrcEvent330(IrcEvent *e) { - if(e->params().count() < 3) - return; +void EventStringifier::processIrcEvent330(IrcEvent *e) +{ + if (e->params().count() < 3) + return; - // check for whois or whowas - if (_whois) { - displayMsg(e, Message::Server, tr("[Whois] %1 is authed as %2").arg(e->params()[0], e->params()[1])); - } else { - displayMsg(e, Message::Server, tr("[Whowas] %1 was authed as %2").arg(e->params()[0], e->params()[1])); - } + // check for whois or whowas + if (_whois) { + displayMsg(e, Message::Server, tr("[Whois] %1 is authed as %2").arg(e->params()[0], e->params()[1])); + } + else { + displayMsg(e, Message::Server, tr("[Whowas] %1 was authed as %2").arg(e->params()[0], e->params()[1])); + } } + /* RPL_NOTOPIC */ -void EventStringifier::processIrcEvent331(IrcEvent *e) { - QString channel = e->params().first(); - displayMsg(e, Message::Topic, tr("No topic is set for %1.").arg(channel), QString(), channel); +void EventStringifier::processIrcEvent331(IrcEvent *e) +{ + QString channel = e->params().first(); + displayMsg(e, Message::Topic, tr("No topic is set for %1.").arg(channel), QString(), channel); } + /* RPL_TOPIC */ -void EventStringifier::processIrcEvent332(IrcEvent *e) { - QString channel = e->params().first(); - displayMsg(e, Message::Topic, tr("Topic for %1 is \"%2\"").arg(channel, e->params()[1]), QString(), channel); +void EventStringifier::processIrcEvent332(IrcEvent *e) +{ + QString channel = e->params().first(); + displayMsg(e, Message::Topic, tr("Topic for %1 is \"%2\"").arg(channel, e->params()[1]), QString(), channel); } + /* Topic set by... */ -void EventStringifier::processIrcEvent333(IrcEvent *e) { - if(!checkParamCount(e, 3)) - return; +void EventStringifier::processIrcEvent333(IrcEvent *e) +{ + if (!checkParamCount(e, 3)) + return; - QString channel = e->params().first(); - displayMsg(e, Message::Topic, tr("Topic set by %1 on %2") - .arg(e->params()[1], QDateTime::fromTime_t(e->params()[2].toInt()).toString()), QString(), channel); + QString channel = e->params().first(); + displayMsg(e, Message::Topic, tr("Topic set by %1 on %2") + .arg(e->params()[1], QDateTime::fromTime_t(e->params()[2].toInt()).toString()), QString(), channel); } + /* RPL_INVITING - " */ -void EventStringifier::processIrcEvent341(IrcEvent *e) { - if(!checkParamCount(e, 2)) - return; +void EventStringifier::processIrcEvent341(IrcEvent *e) +{ + if (!checkParamCount(e, 2)) + return; - QString channel = e->params()[1]; - displayMsg(e, Message::Server, tr("%1 has been invited to %2").arg(e->params().first(), channel), QString(), channel); + QString channel = e->params()[1]; + displayMsg(e, Message::Server, tr("%1 has been invited to %2").arg(e->params().first(), channel), QString(), channel); } + /* RPL_WHOREPLY: " ( "H" / "G" > ["*"] [ ( "@" / "+" ) ] : " */ -void EventStringifier::processIrcEvent352(IrcEvent *e) { - displayMsg(e, Message::Server, tr("[Who] %1").arg(e->params().join(" "))); +void EventStringifier::processIrcEvent352(IrcEvent *e) +{ + displayMsg(e, Message::Server, tr("[Who] %1").arg(e->params().join(" "))); } + /* RPL_ENDOFWHOWAS - " :End of WHOWAS" */ -void EventStringifier::processIrcEvent369(IrcEvent *e) { - displayMsg(e, Message::Server, tr("End of /WHOWAS")); +void EventStringifier::processIrcEvent369(IrcEvent *e) +{ + displayMsg(e, Message::Server, tr("End of /WHOWAS")); } + /* ERR_ERRONEUSNICKNAME */ -void EventStringifier::processIrcEvent432(IrcEvent *e) { - if(!checkParamCount(e, 1)) - return; +void EventStringifier::processIrcEvent432(IrcEvent *e) +{ + if (!checkParamCount(e, 1)) + return; - displayMsg(e, Message::Error, tr("Nick %1 contains illegal characters").arg(e->params()[0])); + displayMsg(e, Message::Error, tr("Nick %1 contains illegal characters").arg(e->params()[0])); } + /* ERR_NICKNAMEINUSE */ -void EventStringifier::processIrcEvent433(IrcEvent *e) { - if(!checkParamCount(e, 1)) - return; +void EventStringifier::processIrcEvent433(IrcEvent *e) +{ + if (!checkParamCount(e, 1)) + return; - displayMsg(e, Message::Error, tr("Nick already in use: %1").arg(e->params()[0])); + displayMsg(e, Message::Error, tr("Nick already in use: %1").arg(e->params()[0])); } + /* ERR_UNAVAILRESOURCE */ -void EventStringifier::processIrcEvent437(IrcEvent *e) { - if(!checkParamCount(e, 1)) - return; +void EventStringifier::processIrcEvent437(IrcEvent *e) +{ + if (!checkParamCount(e, 1)) + return; - displayMsg(e, Message::Error, tr("Nick/channel is temporarily unavailable: %1").arg(e->params()[0])); + displayMsg(e, Message::Error, tr("Nick/channel is temporarily unavailable: %1").arg(e->params()[0])); } + // template /* @@ -527,40 +676,47 @@ void EventStringifier::processIrcEvent(IrcEvent *e) { /******** CTCP HANDLING ********/ /*******************************/ -void EventStringifier::processCtcpEvent(CtcpEvent *e) { - if(e->type() != EventManager::CtcpEvent) - return; +void EventStringifier::processCtcpEvent(CtcpEvent *e) +{ + if (e->type() != EventManager::CtcpEvent) + return; - if(e->testFlag(EventManager::Self)) { - displayMsg(e, Message::Action, tr("sending CTCP-%1 request to %2").arg(e->ctcpCmd(), e->target()), e->network()->myNick()); - return; - } + if (e->testFlag(EventManager::Self)) { + displayMsg(e, Message::Action, tr("sending CTCP-%1 request to %2").arg(e->ctcpCmd(), e->target()), e->network()->myNick()); + return; + } - handle(e->ctcpCmd(), Q_ARG(CtcpEvent *, e)); + handle(e->ctcpCmd(), Q_ARG(CtcpEvent *, e)); } -void EventStringifier::defaultHandler(const QString &ctcpCmd, CtcpEvent *e) { - Q_UNUSED(ctcpCmd); - if(e->ctcpType() == CtcpEvent::Query) { - QString unknown; - if(e->reply().isNull()) // all known core-side handlers (except for ACTION) set a reply! - //: Optional "unknown" in "Received unknown CTCP-FOO request by bar" - unknown = tr("unknown") + ' '; - displayMsg(e, Message::Server, tr("Received %1CTCP-%2 request by %3").arg(unknown, e->ctcpCmd(), e->prefix())); - return; - } - displayMsg(e, Message::Server, tr("Received CTCP-%1 answer from %2: %3").arg(e->ctcpCmd(), nickFromMask(e->prefix()), e->param())); + +void EventStringifier::defaultHandler(const QString &ctcpCmd, CtcpEvent *e) +{ + Q_UNUSED(ctcpCmd); + if (e->ctcpType() == CtcpEvent::Query) { + QString unknown; + if (e->reply().isNull()) // all known core-side handlers (except for ACTION) set a reply! + //: Optional "unknown" in "Received unknown CTCP-FOO request by bar" + unknown = tr("unknown") + ' '; + displayMsg(e, Message::Server, tr("Received %1CTCP-%2 request by %3").arg(unknown, e->ctcpCmd(), e->prefix())); + return; + } + displayMsg(e, Message::Server, tr("Received CTCP-%1 answer from %2: %3").arg(e->ctcpCmd(), nickFromMask(e->prefix()), e->param())); } -void EventStringifier::handleCtcpAction(CtcpEvent *e) { - displayMsg(e, Message::Action, e->param(), e->prefix(), e->target()); + +void EventStringifier::handleCtcpAction(CtcpEvent *e) +{ + displayMsg(e, Message::Action, e->param(), e->prefix(), e->target()); } -void EventStringifier::handleCtcpPing(CtcpEvent *e) { - if(e->ctcpType() == CtcpEvent::Query) - defaultHandler(e->ctcpCmd(), e); - else { - displayMsg(e, Message::Server, tr("Received CTCP-PING answer from %1 with %2 seconds round trip time") - .arg(nickFromMask(e->prefix())).arg(QDateTime::fromTime_t(e->param().toInt()).secsTo(e->timestamp()))); - } + +void EventStringifier::handleCtcpPing(CtcpEvent *e) +{ + if (e->ctcpType() == CtcpEvent::Query) + defaultHandler(e->ctcpCmd(), e); + else { + displayMsg(e, Message::Server, tr("Received CTCP-PING answer from %1 with %2 seconds round trip time") + .arg(nickFromMask(e->prefix())).arg(QDateTime::fromTime_t(e->param().toInt()).secsTo(e->timestamp()))); + } } diff --git a/src/core/eventstringifier.h b/src/core/eventstringifier.h index 14fd29e1..5731161a 100644 --- a/src/core/eventstringifier.h +++ b/src/core/eventstringifier.h @@ -32,92 +32,93 @@ class MessageEvent; //! Generates user-visible MessageEvents from incoming IrcEvents /* replaces the string-generating parts of the old IrcServerHandler */ -class EventStringifier : public BasicHandler { - Q_OBJECT +class EventStringifier : public BasicHandler +{ + Q_OBJECT public: - explicit EventStringifier(CoreSession *parent); - - inline CoreSession *coreSession() const { return _coreSession; } - - MessageEvent *createMessageEvent(NetworkEvent *event, - Message::Type msgType, - const QString &msg, - const QString &sender = QString(), - const QString &target = QString(), - Message::Flags msgFlags = Message::None); - - // legacy handlers - Q_INVOKABLE void processNetworkSplitJoin(NetworkSplitEvent *event); - Q_INVOKABLE void processNetworkSplitQuit(NetworkSplitEvent *event); - - //! Handle generic numeric events - Q_INVOKABLE void processIrcEventNumeric(IrcEventNumeric *event); - - Q_INVOKABLE void processIrcEventInvite(IrcEvent *event); - Q_INVOKABLE void processIrcEventJoin(IrcEvent *event); - Q_INVOKABLE void processIrcEventKick(IrcEvent *event); - Q_INVOKABLE void processIrcEventMode(IrcEvent *event); - Q_INVOKABLE void processIrcEventNick(IrcEvent *event); - Q_INVOKABLE void processIrcEventPart(IrcEvent *event); - Q_INVOKABLE void processIrcEventPong(IrcEvent *event); - Q_INVOKABLE void processIrcEventQuit(IrcEvent *event); - Q_INVOKABLE void processIrcEventTopic(IrcEvent *event); - - Q_INVOKABLE void processIrcEvent005(IrcEvent *event); // RPL_ISUPPORT - Q_INVOKABLE void processIrcEvent301(IrcEvent *event); // RPL_AWAY - Q_INVOKABLE void processIrcEvent305(IrcEvent *event); // RPL_UNAWAY - Q_INVOKABLE void processIrcEvent306(IrcEvent *event); // RPL_NOWAWAY - Q_INVOKABLE void processIrcEvent311(IrcEvent *event); // RPL_WHOISUSER - Q_INVOKABLE void processIrcEvent312(IrcEvent *event); // RPL_WHOISSERVER - Q_INVOKABLE void processIrcEvent314(IrcEvent *event); // RPL_WHOWASUSER - Q_INVOKABLE void processIrcEvent315(IrcEvent *event); // RPL_ENDOFWHO - Q_INVOKABLE void processIrcEvent317(IrcEvent *event); // RPL_WHOISIDLE - Q_INVOKABLE void processIrcEvent318(IrcEvent *event); // RPL_ENDOFWHOIS - Q_INVOKABLE void processIrcEvent319(IrcEvent *event); // RPL_WHOISCHANNELS - Q_INVOKABLE void processIrcEvent322(IrcEvent *event); // RPL_LIST - Q_INVOKABLE void processIrcEvent323(IrcEvent *event); // RPL_LISTEND - Q_INVOKABLE void processIrcEvent324(IrcEvent *event); // RPL_CHANNELMODEIS - Q_INVOKABLE void processIrcEvent328(IrcEvent *event); // RPL_??? (channel creation time) - Q_INVOKABLE void processIrcEvent329(IrcEvent *event); // RPL_??? (channel homepage) - Q_INVOKABLE void processIrcEvent330(IrcEvent *event); // RPL_WHOISACCOUNT (quakenet/snircd/undernet) - Q_INVOKABLE void processIrcEvent331(IrcEvent *event); // RPL_NOTOPIC - Q_INVOKABLE void processIrcEvent332(IrcEvent *event); // RPL_TOPIC - Q_INVOKABLE void processIrcEvent333(IrcEvent *event); // RPL_??? (topic set by) - Q_INVOKABLE void processIrcEvent341(IrcEvent *event); // RPL_INVITING - Q_INVOKABLE void processIrcEvent352(IrcEvent *event); // RPL_WHOREPLY - Q_INVOKABLE void processIrcEvent369(IrcEvent *event); // RPL_ENDOFWHOWAS - Q_INVOKABLE void processIrcEvent432(IrcEvent *event); // ERR_ERRONEUSNICKNAME - Q_INVOKABLE void processIrcEvent433(IrcEvent *event); // ERR_NICKNAMEINUSE - Q_INVOKABLE void processIrcEvent437(IrcEvent *event); // ERR_UNAVAILRESOURCE - - // Q_INVOKABLE void processIrcEvent(IrcEvent *event); - - /* CTCP handlers */ - Q_INVOKABLE void processCtcpEvent(CtcpEvent *event); - - Q_INVOKABLE void handleCtcpAction(CtcpEvent *event); - Q_INVOKABLE void handleCtcpPing(CtcpEvent *event); - Q_INVOKABLE void defaultHandler(const QString &cmd, CtcpEvent *event); + explicit EventStringifier(CoreSession *parent); + + inline CoreSession *coreSession() const { return _coreSession; } + + MessageEvent *createMessageEvent(NetworkEvent *event, + Message::Type msgType, + const QString &msg, + const QString &sender = QString(), + const QString &target = QString(), + Message::Flags msgFlags = Message::None); + + // legacy handlers + Q_INVOKABLE void processNetworkSplitJoin(NetworkSplitEvent *event); + Q_INVOKABLE void processNetworkSplitQuit(NetworkSplitEvent *event); + + //! Handle generic numeric events + Q_INVOKABLE void processIrcEventNumeric(IrcEventNumeric *event); + + Q_INVOKABLE void processIrcEventInvite(IrcEvent *event); + Q_INVOKABLE void processIrcEventJoin(IrcEvent *event); + Q_INVOKABLE void processIrcEventKick(IrcEvent *event); + Q_INVOKABLE void processIrcEventMode(IrcEvent *event); + Q_INVOKABLE void processIrcEventNick(IrcEvent *event); + Q_INVOKABLE void processIrcEventPart(IrcEvent *event); + Q_INVOKABLE void processIrcEventPong(IrcEvent *event); + Q_INVOKABLE void processIrcEventQuit(IrcEvent *event); + Q_INVOKABLE void processIrcEventTopic(IrcEvent *event); + + Q_INVOKABLE void processIrcEvent005(IrcEvent *event); // RPL_ISUPPORT + Q_INVOKABLE void processIrcEvent301(IrcEvent *event); // RPL_AWAY + Q_INVOKABLE void processIrcEvent305(IrcEvent *event); // RPL_UNAWAY + Q_INVOKABLE void processIrcEvent306(IrcEvent *event); // RPL_NOWAWAY + Q_INVOKABLE void processIrcEvent311(IrcEvent *event); // RPL_WHOISUSER + Q_INVOKABLE void processIrcEvent312(IrcEvent *event); // RPL_WHOISSERVER + Q_INVOKABLE void processIrcEvent314(IrcEvent *event); // RPL_WHOWASUSER + Q_INVOKABLE void processIrcEvent315(IrcEvent *event); // RPL_ENDOFWHO + Q_INVOKABLE void processIrcEvent317(IrcEvent *event); // RPL_WHOISIDLE + Q_INVOKABLE void processIrcEvent318(IrcEvent *event); // RPL_ENDOFWHOIS + Q_INVOKABLE void processIrcEvent319(IrcEvent *event); // RPL_WHOISCHANNELS + Q_INVOKABLE void processIrcEvent322(IrcEvent *event); // RPL_LIST + Q_INVOKABLE void processIrcEvent323(IrcEvent *event); // RPL_LISTEND + Q_INVOKABLE void processIrcEvent324(IrcEvent *event); // RPL_CHANNELMODEIS + Q_INVOKABLE void processIrcEvent328(IrcEvent *event); // RPL_??? (channel creation time) + Q_INVOKABLE void processIrcEvent329(IrcEvent *event); // RPL_??? (channel homepage) + Q_INVOKABLE void processIrcEvent330(IrcEvent *event); // RPL_WHOISACCOUNT (quakenet/snircd/undernet) + Q_INVOKABLE void processIrcEvent331(IrcEvent *event); // RPL_NOTOPIC + Q_INVOKABLE void processIrcEvent332(IrcEvent *event); // RPL_TOPIC + Q_INVOKABLE void processIrcEvent333(IrcEvent *event); // RPL_??? (topic set by) + Q_INVOKABLE void processIrcEvent341(IrcEvent *event); // RPL_INVITING + Q_INVOKABLE void processIrcEvent352(IrcEvent *event); // RPL_WHOREPLY + Q_INVOKABLE void processIrcEvent369(IrcEvent *event); // RPL_ENDOFWHOWAS + Q_INVOKABLE void processIrcEvent432(IrcEvent *event); // ERR_ERRONEUSNICKNAME + Q_INVOKABLE void processIrcEvent433(IrcEvent *event); // ERR_NICKNAMEINUSE + Q_INVOKABLE void processIrcEvent437(IrcEvent *event); // ERR_UNAVAILRESOURCE + + // Q_INVOKABLE void processIrcEvent(IrcEvent *event); + + /* CTCP handlers */ + Q_INVOKABLE void processCtcpEvent(CtcpEvent *event); + + Q_INVOKABLE void handleCtcpAction(CtcpEvent *event); + Q_INVOKABLE void handleCtcpPing(CtcpEvent *event); + Q_INVOKABLE void defaultHandler(const QString &cmd, CtcpEvent *event); public slots: - //! Creates and sends a MessageEvent - void displayMsg(NetworkEvent *event, - Message::Type msgType, - const QString &msg, - const QString &sender = QString(), - const QString &target = QString(), - Message::Flags msgFlags = Message::None); + //! Creates and sends a MessageEvent + void displayMsg(NetworkEvent *event, + Message::Type msgType, + const QString &msg, + const QString &sender = QString(), + const QString &target = QString(), + Message::Flags msgFlags = Message::None); signals: - void newMessageEvent(Event *event); + void newMessageEvent(Event *event); private: - bool checkParamCount(IrcEvent *event, int minParams); - - CoreSession *_coreSession; - bool _whois; + bool checkParamCount(IrcEvent *event, int minParams); + CoreSession *_coreSession; + bool _whois; }; + #endif diff --git a/src/core/ircparser.cpp b/src/core/ircparser.cpp index cd59e53d..f558f5f2 100644 --- a/src/core/ircparser.cpp +++ b/src/core/ircparser.cpp @@ -31,277 +31,284 @@ #endif IrcParser::IrcParser(CoreSession *session) : - QObject(session), - _coreSession(session) + QObject(session), + _coreSession(session) { - connect(this, SIGNAL(newEvent(Event *)), coreSession()->eventManager(), SLOT(postEvent(Event *))); + connect(this, SIGNAL(newEvent(Event *)), coreSession()->eventManager(), SLOT(postEvent(Event *))); } -bool IrcParser::checkParamCount(const QString &cmd, const QList ¶ms, int minParams) { - if(params.count() < minParams) { - qWarning() << "Expected" << minParams << "params for IRC command" << cmd << ", got:" << params; - return false; - } - return true; + +bool IrcParser::checkParamCount(const QString &cmd, const QList ¶ms, int minParams) +{ + if (params.count() < minParams) { + qWarning() << "Expected" << minParams << "params for IRC command" << cmd << ", got:" << params; + return false; + } + return true; } -QByteArray IrcParser::decrypt(Network *network, const QString &bufferName, const QByteArray &message, bool isTopic) { + +QByteArray IrcParser::decrypt(Network *network, const QString &bufferName, const QByteArray &message, bool isTopic) +{ #ifdef HAVE_QCA2 - if(message.isEmpty()) - return message; + if (message.isEmpty()) + return message; - if(!Cipher::neededFeaturesAvailable()) - return message; + if (!Cipher::neededFeaturesAvailable()) + return message; - Cipher *cipher = qobject_cast(network)->cipher(bufferName); - if(!cipher) - return message; + Cipher *cipher = qobject_cast(network)->cipher(bufferName); + if (!cipher) + return message; - return isTopic? cipher->decryptTopic(message) : cipher->decrypt(message); + return isTopic ? cipher->decryptTopic(message) : cipher->decrypt(message); #else - Q_UNUSED(network); - Q_UNUSED(bufferName); - Q_UNUSED(isTopic); - return message; + Q_UNUSED(network); + Q_UNUSED(bufferName); + Q_UNUSED(isTopic); + return message; #endif } + /* parse the raw server string and generate an appropriate event */ /* used to be handleServerMsg() */ -void IrcParser::processNetworkIncoming(NetworkDataEvent *e) { - CoreNetwork *net = qobject_cast(e->network()); - if(!net) { - qWarning() << "Received network event without valid network pointer!"; - return; - } - - // note that the IRC server is still alive - net->resetPingTimeout(); - - QByteArray msg = e->data(); - if(msg.isEmpty()) { - qWarning() << "Received empty string from server!"; - return; - } - - // Now we split the raw message into its various parts... - QString prefix; - QByteArray trailing; - QString cmd, target; - - // First, check for a trailing parameter introduced by " :", since this might screw up splitting the msg - // NOTE: This assumes that this is true in raw encoding, but well, hopefully there are no servers running in japanese on protocol level... - int idx = msg.indexOf(" :"); - if(idx >= 0) { - if(msg.length() > idx + 2) - trailing = msg.mid(idx + 2); - msg = msg.left(idx); - } - // OK, now it is safe to split... - QList params = msg.split(' '); - - // This could still contain empty elements due to (faulty?) ircds sending multiple spaces in a row - // Also, QByteArray is not nearly as convenient to work with as QString for such things :) - QList::iterator iter = params.begin(); - while(iter != params.end()) { - if(iter->isEmpty()) - iter = params.erase(iter); - else - ++iter; - } - - if(!trailing.isEmpty()) - params << trailing; - if(params.count() < 1) { - qWarning() << "Received invalid string from server!"; - return; - } - - QString foo = net->serverDecode(params.takeFirst()); - - // a colon as the first chars indicates the existence of a prefix - if(foo[0] == ':') { - foo.remove(0, 1); - prefix = foo; - if(params.count() < 1) { - qWarning() << "Received invalid string from server!"; - return; +void IrcParser::processNetworkIncoming(NetworkDataEvent *e) +{ + CoreNetwork *net = qobject_cast(e->network()); + if (!net) { + qWarning() << "Received network event without valid network pointer!"; + return; } - foo = net->serverDecode(params.takeFirst()); - } - // next string without a whitespace is the command - cmd = foo.trimmed(); + // note that the IRC server is still alive + net->resetPingTimeout(); - QList events; - EventManager::EventType type = EventManager::Invalid; + QByteArray msg = e->data(); + if (msg.isEmpty()) { + qWarning() << "Received empty string from server!"; + return; + } - uint num = cmd.toUInt(); - if(num > 0) { - // numeric reply - if(params.count() == 0) { - qWarning() << "Message received from server violates RFC and is ignored!" << msg; - return; + // Now we split the raw message into its various parts... + QString prefix; + QByteArray trailing; + QString cmd, target; + + // First, check for a trailing parameter introduced by " :", since this might screw up splitting the msg + // NOTE: This assumes that this is true in raw encoding, but well, hopefully there are no servers running in japanese on protocol level... + int idx = msg.indexOf(" :"); + if (idx >= 0) { + if (msg.length() > idx + 2) + trailing = msg.mid(idx + 2); + msg = msg.left(idx); } - // numeric replies have the target as first param (RFC 2812 - 2.4). this is usually our own nick. Remove this! - target = net->serverDecode(params.takeFirst()); - type = EventManager::IrcEventNumeric; - } else { - // any other irc command - QString typeName = QLatin1String("IrcEvent") + cmd.at(0).toUpper() + cmd.mid(1).toLower(); - type = eventManager()->eventTypeByName(typeName); - if(type == EventManager::Invalid) { - type = eventManager()->eventTypeByName("IrcEventUnknown"); - Q_ASSERT(type != EventManager::Invalid); + // OK, now it is safe to split... + QList params = msg.split(' '); + + // This could still contain empty elements due to (faulty?) ircds sending multiple spaces in a row + // Also, QByteArray is not nearly as convenient to work with as QString for such things :) + QList::iterator iter = params.begin(); + while (iter != params.end()) { + if (iter->isEmpty()) + iter = params.erase(iter); + else + ++iter; } - target = QString(); - } - // Almost always, all params are server-encoded. There's a few exceptions, let's catch them here! - // Possibly not the best option, we might want something more generic? Maybe yet another layer of - // unencoded events with event handlers for the exceptions... - // Also, PRIVMSG and NOTICE need some special handling, we put this in here as well, so we get out - // nice pre-parsed events that the CTCP handler can consume. + if (!trailing.isEmpty()) + params << trailing; + if (params.count() < 1) { + qWarning() << "Received invalid string from server!"; + return; + } - QStringList decParams; - bool defaultHandling = true; // whether to automatically copy the remaining params and send the event + QString foo = net->serverDecode(params.takeFirst()); - switch(type) { + // a colon as the first chars indicates the existence of a prefix + if (foo[0] == ':') { + foo.remove(0, 1); + prefix = foo; + if (params.count() < 1) { + qWarning() << "Received invalid string from server!"; + return; + } + foo = net->serverDecode(params.takeFirst()); + } - case EventManager::IrcEventPrivmsg: - defaultHandling = false; // this might create a list of events + // next string without a whitespace is the command + cmd = foo.trimmed(); - if(checkParamCount(cmd, params, 1)) { - QString senderNick = nickFromMask(prefix); - QByteArray msg = params.count() < 2 ? QByteArray() : params.at(1); + QList events; + EventManager::EventType type = EventManager::Invalid; - QStringList targets = net->serverDecode(params.at(0)).split(',', QString::SkipEmptyParts); - QStringList::const_iterator targetIter; - for(targetIter = targets.constBegin(); targetIter != targets.constEnd(); ++targetIter) { - QString target = net->isChannelName(*targetIter) ? *targetIter : senderNick; + uint num = cmd.toUInt(); + if (num > 0) { + // numeric reply + if (params.count() == 0) { + qWarning() << "Message received from server violates RFC and is ignored!" << msg; + return; + } + // numeric replies have the target as first param (RFC 2812 - 2.4). this is usually our own nick. Remove this! + target = net->serverDecode(params.takeFirst()); + type = EventManager::IrcEventNumeric; + } + else { + // any other irc command + QString typeName = QLatin1String("IrcEvent") + cmd.at(0).toUpper() + cmd.mid(1).toLower(); + type = eventManager()->eventTypeByName(typeName); + if (type == EventManager::Invalid) { + type = eventManager()->eventTypeByName("IrcEventUnknown"); + Q_ASSERT(type != EventManager::Invalid); + } + target = QString(); + } - msg = decrypt(net, target, msg); + // Almost always, all params are server-encoded. There's a few exceptions, let's catch them here! + // Possibly not the best option, we might want something more generic? Maybe yet another layer of + // unencoded events with event handlers for the exceptions... + // Also, PRIVMSG and NOTICE need some special handling, we put this in here as well, so we get out + // nice pre-parsed events that the CTCP handler can consume. - events << new IrcEventRawMessage(EventManager::IrcEventRawPrivmsg, net, msg, prefix, target, e->timestamp()); - } - } - break; - - case EventManager::IrcEventNotice: - defaultHandling = false; - - if(checkParamCount(cmd, params, 2)) { - QStringList targets = net->serverDecode(params.at(0)).split(',', QString::SkipEmptyParts); - QStringList::const_iterator targetIter; - for(targetIter = targets.constBegin(); targetIter != targets.constEnd(); ++targetIter) { - QString target = *targetIter; - - // special treatment for welcome messages like: - // :ChanServ!ChanServ@services. NOTICE egst :[#apache] Welcome, this is #apache. Please read the in-channel topic message. This channel is being logged by IRSeekBot. If you have any question please see http://blog.freenode.net/?p=68 - if(!net->isChannelName(target)) { - QString decMsg = net->serverDecode(params.at(1)); - QRegExp welcomeRegExp("^\\[([^\\]]+)\\] "); - if(welcomeRegExp.indexIn(decMsg) != -1) { - QString channelname = welcomeRegExp.cap(1); - decMsg = decMsg.mid(welcomeRegExp.matchedLength()); - CoreIrcChannel *chan = static_cast(net->ircChannel(channelname)); // we only have CoreIrcChannels in the core, so this cast is safe - if(chan && !chan->receivedWelcomeMsg()) { - chan->setReceivedWelcomeMsg(); - events << new MessageEvent(Message::Notice, net, decMsg, prefix, channelname, Message::None, e->timestamp()); - continue; + QStringList decParams; + bool defaultHandling = true; // whether to automatically copy the remaining params and send the event + + switch (type) { + case EventManager::IrcEventPrivmsg: + defaultHandling = false; // this might create a list of events + + if (checkParamCount(cmd, params, 1)) { + QString senderNick = nickFromMask(prefix); + QByteArray msg = params.count() < 2 ? QByteArray() : params.at(1); + + QStringList targets = net->serverDecode(params.at(0)).split(',', QString::SkipEmptyParts); + QStringList::const_iterator targetIter; + for (targetIter = targets.constBegin(); targetIter != targets.constEnd(); ++targetIter) { + QString target = net->isChannelName(*targetIter) ? *targetIter : senderNick; + + msg = decrypt(net, target, msg); + + events << new IrcEventRawMessage(EventManager::IrcEventRawPrivmsg, net, msg, prefix, target, e->timestamp()); } - } } - - if(prefix.isEmpty() || target == "AUTH") { - target = QString(); - } else { - if(!target.isEmpty() && net->prefixes().contains(target.at(0))) - target = target.mid(1); - if(!net->isChannelName(target)) - target = nickFromMask(prefix); + break; + + case EventManager::IrcEventNotice: + defaultHandling = false; + + if (checkParamCount(cmd, params, 2)) { + QStringList targets = net->serverDecode(params.at(0)).split(',', QString::SkipEmptyParts); + QStringList::const_iterator targetIter; + for (targetIter = targets.constBegin(); targetIter != targets.constEnd(); ++targetIter) { + QString target = *targetIter; + + // special treatment for welcome messages like: + // :ChanServ!ChanServ@services. NOTICE egst :[#apache] Welcome, this is #apache. Please read the in-channel topic message. This channel is being logged by IRSeekBot. If you have any question please see http://blog.freenode.net/?p=68 + if (!net->isChannelName(target)) { + QString decMsg = net->serverDecode(params.at(1)); + QRegExp welcomeRegExp("^\\[([^\\]]+)\\] "); + if (welcomeRegExp.indexIn(decMsg) != -1) { + QString channelname = welcomeRegExp.cap(1); + decMsg = decMsg.mid(welcomeRegExp.matchedLength()); + CoreIrcChannel *chan = static_cast(net->ircChannel(channelname)); // we only have CoreIrcChannels in the core, so this cast is safe + if (chan && !chan->receivedWelcomeMsg()) { + chan->setReceivedWelcomeMsg(); + events << new MessageEvent(Message::Notice, net, decMsg, prefix, channelname, Message::None, e->timestamp()); + continue; + } + } + } + + if (prefix.isEmpty() || target == "AUTH") { + target = QString(); + } + else { + if (!target.isEmpty() && net->prefixes().contains(target.at(0))) + target = target.mid(1); + if (!net->isChannelName(target)) + target = nickFromMask(prefix); + } + events << new IrcEventRawMessage(EventManager::IrcEventRawNotice, net, params[1], prefix, target, e->timestamp()); + } } - events << new IrcEventRawMessage(EventManager::IrcEventRawNotice, net, params[1], prefix, target, e->timestamp()); - } - } - break; + break; // the following events need only special casing for param decoding - case EventManager::IrcEventKick: - if(params.count() >= 3) { // we have a reason - decParams << net->serverDecode(params.at(0)) << net->serverDecode(params.at(1)); - decParams << net->channelDecode(decParams.first(), params.at(2)); // kick reason - } - break; + case EventManager::IrcEventKick: + if (params.count() >= 3) { // we have a reason + decParams << net->serverDecode(params.at(0)) << net->serverDecode(params.at(1)); + decParams << net->channelDecode(decParams.first(), params.at(2)); // kick reason + } + break; - case EventManager::IrcEventPart: - if(params.count() >= 2) { - QString channel = net->serverDecode(params.at(0)); - decParams << channel; - decParams << net->userDecode(nickFromMask(prefix), params.at(1)); - } - break; + case EventManager::IrcEventPart: + if (params.count() >= 2) { + QString channel = net->serverDecode(params.at(0)); + decParams << channel; + decParams << net->userDecode(nickFromMask(prefix), params.at(1)); + } + break; - case EventManager::IrcEventQuit: - if(params.count() >= 1) { - decParams << net->userDecode(nickFromMask(prefix), params.at(0)); - } - break; + case EventManager::IrcEventQuit: + if (params.count() >= 1) { + decParams << net->userDecode(nickFromMask(prefix), params.at(0)); + } + break; + + case EventManager::IrcEventTopic: + if (params.count() >= 1) { + QString channel = net->serverDecode(params.at(0)); + decParams << channel; + decParams << (params.count() >= 2 ? net->channelDecode(channel, decrypt(net, channel, params.at(1), true)) : QString()); + } + break; + + case EventManager::IrcEventNumeric: + switch (num) { + case 301: /* RPL_AWAY */ + if (params.count() >= 2) { + QString nick = net->serverDecode(params.at(0)); + decParams << nick; + decParams << net->userDecode(nick, params.at(1)); + } + break; + + case 332: /* RPL_TOPIC */ + if (params.count() >= 2) { + QString channel = net->serverDecode(params.at(0)); + decParams << channel; + decParams << net->channelDecode(channel, decrypt(net, channel, params.at(1), true)); + } + break; - case EventManager::IrcEventTopic: - if(params.count() >= 1) { - QString channel = net->serverDecode(params.at(0)); - decParams << channel; - decParams << (params.count() >= 2? net->channelDecode(channel, decrypt(net, channel, params.at(1), true)) : QString()); + case 333: /* Topic set by... */ + if (params.count() >= 3) { + QString channel = net->serverDecode(params.at(0)); + decParams << channel << net->serverDecode(params.at(1)); + decParams << net->channelDecode(channel, params.at(2)); + } + break; + } + + default: + break; } - break; - - case EventManager::IrcEventNumeric: - switch(num) { - case 301: /* RPL_AWAY */ - if(params.count() >= 2) { - QString nick = net->serverDecode(params.at(0)); - decParams << nick; - decParams << net->userDecode(nick, params.at(1)); - } - break; - - case 332: /* RPL_TOPIC */ - if(params.count() >= 2) { - QString channel = net->serverDecode(params.at(0)); - decParams << channel; - decParams << net->channelDecode(channel, decrypt(net, channel, params.at(1), true)); - } - break; - - case 333: /* Topic set by... */ - if(params.count() >= 3) { - QString channel = net->serverDecode(params.at(0)); - decParams << channel << net->serverDecode(params.at(1)); - decParams << net->channelDecode(channel, params.at(2)); - } - break; + + if (defaultHandling && type != EventManager::Invalid) { + for (int i = decParams.count(); i < params.count(); i++) + decParams << net->serverDecode(params.at(i)); + + IrcEvent *event; + if (type == EventManager::IrcEventNumeric) + event = new IrcEventNumeric(num, net, prefix, target); + else + event = new IrcEvent(type, net, prefix); + event->setParams(decParams); + event->setTimestamp(e->timestamp()); + events << event; } - default: - break; - } - - if(defaultHandling && type != EventManager::Invalid) { - for(int i = decParams.count(); i < params.count(); i++) - decParams << net->serverDecode(params.at(i)); - - IrcEvent *event; - if(type == EventManager::IrcEventNumeric) - event = new IrcEventNumeric(num, net, prefix, target); - else - event = new IrcEvent(type, net, prefix); - event->setParams(decParams); - event->setTimestamp(e->timestamp()); - events << event; - } - - foreach(Event *event, events) { - emit newEvent(event); - } + foreach(Event *event, events) { + emit newEvent(event); + } } diff --git a/src/core/ircparser.h b/src/core/ircparser.h index 2a1543c2..bddccf46 100644 --- a/src/core/ircparser.h +++ b/src/core/ircparser.h @@ -28,28 +28,30 @@ class EventManager; class IrcEvent; class NetworkDataEvent; -class IrcParser : public QObject { - Q_OBJECT +class IrcParser : public QObject +{ + Q_OBJECT public: - IrcParser(CoreSession *session); + IrcParser(CoreSession *session); - inline CoreSession *coreSession() const { return _coreSession; } - inline EventManager *eventManager() const { return coreSession()->eventManager(); } + inline CoreSession *coreSession() const { return _coreSession; } + inline EventManager *eventManager() const { return coreSession()->eventManager(); } signals: - void newEvent(Event *); + void newEvent(Event *); protected: - Q_INVOKABLE void processNetworkIncoming(NetworkDataEvent *e); + Q_INVOKABLE void processNetworkIncoming(NetworkDataEvent *e); - bool checkParamCount(const QString &cmd, const QList ¶ms, int minParams); + bool checkParamCount(const QString &cmd, const QList ¶ms, int minParams); - // no-op if we don't have crypto support! - QByteArray decrypt(Network *network, const QString &target, const QByteArray &message, bool isTopic = false); + // no-op if we don't have crypto support! + QByteArray decrypt(Network *network, const QString &target, const QByteArray &message, bool isTopic = false); private: - CoreSession *_coreSession; + CoreSession *_coreSession; }; + #endif diff --git a/src/core/netsplit.cpp b/src/core/netsplit.cpp index c84297f3..dc44d02e 100644 --- a/src/core/netsplit.cpp +++ b/src/core/netsplit.cpp @@ -25,154 +25,163 @@ #include Netsplit::Netsplit(Network *network, QObject *parent) - : QObject(parent), + : QObject(parent), _network(network), _quitMsg(""), _sentQuit(false), _joinCounter(0), _quitCounter(0) { - _discardTimer.setSingleShot(true); - _joinTimer.setSingleShot(true); - _quitTimer.setSingleShot(true); + _discardTimer.setSingleShot(true); + _joinTimer.setSingleShot(true); + _quitTimer.setSingleShot(true); - connect(&_discardTimer, SIGNAL(timeout()), this, SIGNAL(finished())); + connect(&_discardTimer, SIGNAL(timeout()), this, SIGNAL(finished())); - connect(&_joinTimer, SIGNAL(timeout()), this, SLOT(joinTimeout())); - connect(&_quitTimer, SIGNAL(timeout()), this, SLOT(quitTimeout())); + connect(&_joinTimer, SIGNAL(timeout()), this, SLOT(joinTimeout())); + connect(&_quitTimer, SIGNAL(timeout()), this, SLOT(quitTimeout())); - // wait for a maximum of 1 hour until we discard the netsplit - _discardTimer.start(3600000); + // wait for a maximum of 1 hour until we discard the netsplit + _discardTimer.start(3600000); } + void Netsplit::userQuit(const QString &sender, const QStringList &channels, const QString &msg) { - if(_quitMsg.isEmpty()) - _quitMsg = msg; - foreach(QString channel, channels) { - _quits[channel].append(sender); - } - _quitCounter++; - // now let's wait 10s to finish the netsplit-quit - _quitTimer.start(10000); + if (_quitMsg.isEmpty()) + _quitMsg = msg; + foreach(QString channel, channels) { + _quits[channel].append(sender); + } + _quitCounter++; + // now let's wait 10s to finish the netsplit-quit + _quitTimer.start(10000); } -bool Netsplit::userJoined(const QString &sender, const QString &channel) { - if(!_quits.contains(channel)) - return false; - QStringList &users = _quits[channel]; +bool Netsplit::userJoined(const QString &sender, const QString &channel) +{ + if (!_quits.contains(channel)) + return false; - QStringList::iterator userIter; - const QString senderNick = nickFromMask(sender); - for(userIter = users.begin(); userIter != users.end(); ++userIter) { - if(nickFromMask(*userIter) == senderNick) - break; - } - if(userIter == users.end()) - return false; + QStringList &users = _quits[channel]; - _joins[channel].first.append(*userIter); - _joins[channel].second.append(QString()); + QStringList::iterator userIter; + const QString senderNick = nickFromMask(sender); + for (userIter = users.begin(); userIter != users.end(); ++userIter) { + if (nickFromMask(*userIter) == senderNick) + break; + } + if (userIter == users.end()) + return false; - users.erase(userIter); + _joins[channel].first.append(*userIter); + _joins[channel].second.append(QString()); - if(users.empty()) - _quits.remove(channel); + users.erase(userIter); - _joinCounter++; + if (users.empty()) + _quits.remove(channel); - if(_quits.empty()) // all users joined already - no need to wait - _joinTimer.start(0); - else // wait 30s to finish the netsplit-join - _joinTimer.start(30000); + _joinCounter++; - return true; -} + if (_quits.empty()) // all users joined already - no need to wait + _joinTimer.start(0); + else // wait 30s to finish the netsplit-join + _joinTimer.start(30000); -bool Netsplit::userAlreadyJoined(const QString &sender, const QString &channel) { - if(_joins.value(channel).first.contains(sender)) return true; - return false; } -void Netsplit::addMode(const QString &sender, const QString &channel, const QString &mode) { - if(!_joins.contains(channel)) - return; - int idx = _joins.value(channel).first.indexOf(sender); - if(idx == -1) - return; - _joins[channel].second[idx].append(mode); + +bool Netsplit::userAlreadyJoined(const QString &sender, const QString &channel) +{ + if (_joins.value(channel).first.contains(sender)) + return true; + return false; +} + + +void Netsplit::addMode(const QString &sender, const QString &channel, const QString &mode) +{ + if (!_joins.contains(channel)) + return; + int idx = _joins.value(channel).first.indexOf(sender); + if (idx == -1) + return; + _joins[channel].second[idx].append(mode); } + bool Netsplit::isNetsplit(const QString &quitMessage) { - // check if we find some common chars that disqualify the netsplit as such - if(quitMessage.contains(':') || quitMessage.contains('/')) - return false; + // check if we find some common chars that disqualify the netsplit as such + if (quitMessage.contains(':') || quitMessage.contains('/')) + return false; - // now test if message consists only of two dns names as the RFC requests - // but also allow the commonly used "*.net *.split" - QRegExp hostRx("^(?:[\\w\\d-.]+|\\*)\\.[\\w\\d-]+\\s(?:[\\w\\d-.]+|\\*)\\.[\\w\\d-]+$"); - if(hostRx.exactMatch(quitMessage)) - return true; + // now test if message consists only of two dns names as the RFC requests + // but also allow the commonly used "*.net *.split" + QRegExp hostRx("^(?:[\\w\\d-.]+|\\*)\\.[\\w\\d-]+\\s(?:[\\w\\d-.]+|\\*)\\.[\\w\\d-]+$"); + if (hostRx.exactMatch(quitMessage)) + return true; - return false; + return false; } + void Netsplit::joinTimeout() { - if(!_sentQuit) { - _quitTimer.stop(); - quitTimeout(); - } - - QHash >::iterator it; - - /* - Try to catch server jumpers. - If we have too few joins for a netsplit-quit, - we assume that the users manually changed servers and join them - without ending the netsplit. - A netsplit is assumed over only if at least 1/3 of all quits had their corresponding - join again. - */ - if(_joinCounter < _quitCounter/3) { - for(it = _joins.begin(); it != _joins.end(); ++it) - emit earlyJoin(network(), it.key(), it.value().first, it.value().second); - - // we don't care about those anymore - _joins.clear(); + if (!_sentQuit) { + _quitTimer.stop(); + quitTimeout(); + } - // restart the timer with 5min timeout - // This might happen a few times if netsplit lasts longer. - // As soon as another user joins, the timer is set to a shorter timeout again. - _joinTimer.start(300000); - return; - } - - // send netsplitJoin for every recorded channel - for(it = _joins.begin(); it != _joins.end(); ++it) - emit netsplitJoin(network(), it.key(), it.value().first, it.value().second ,_quitMsg); - _joins.clear(); - _discardTimer.stop(); - emit finished(); + QHash >::iterator it; + + /* + Try to catch server jumpers. + If we have too few joins for a netsplit-quit, + we assume that the users manually changed servers and join them + without ending the netsplit. + A netsplit is assumed over only if at least 1/3 of all quits had their corresponding + join again. + */ + if (_joinCounter < _quitCounter/3) { + for (it = _joins.begin(); it != _joins.end(); ++it) + emit earlyJoin(network(), it.key(), it.value().first, it.value().second); + + // we don't care about those anymore + _joins.clear(); + + // restart the timer with 5min timeout + // This might happen a few times if netsplit lasts longer. + // As soon as another user joins, the timer is set to a shorter timeout again. + _joinTimer.start(300000); + return; + } + + // send netsplitJoin for every recorded channel + for (it = _joins.begin(); it != _joins.end(); ++it) + emit netsplitJoin(network(), it.key(), it.value().first, it.value().second, _quitMsg); + _joins.clear(); + _discardTimer.stop(); + emit finished(); } + void Netsplit::quitTimeout() { - // send netsplitQuit for every recorded channel - QHash::iterator channelIter; - for(channelIter = _quits.begin(); channelIter != _quits.end(); ++channelIter) { - - QStringList usersToSend; - - foreach(QString user, channelIter.value()) { - if(!_quitsWithMessageSent.value(channelIter.key()).contains(user)) { - usersToSend << user; - _quitsWithMessageSent[channelIter.key()].append(user); - } + // send netsplitQuit for every recorded channel + QHash::iterator channelIter; + for (channelIter = _quits.begin(); channelIter != _quits.end(); ++channelIter) { + QStringList usersToSend; + + foreach(QString user, channelIter.value()) { + if (!_quitsWithMessageSent.value(channelIter.key()).contains(user)) { + usersToSend << user; + _quitsWithMessageSent[channelIter.key()].append(user); + } + } + // not yet sure how that could happen, but never send empty netsplit-quits + // anyway. + if (!usersToSend.isEmpty()) + emit netsplitQuit(network(), channelIter.key(), usersToSend, _quitMsg); } - // not yet sure how that could happen, but never send empty netsplit-quits - // anyway. - if(!usersToSend.isEmpty()) - emit netsplitQuit(network(), channelIter.key(), usersToSend, _quitMsg); - } - _sentQuit = true; + _sentQuit = true; } diff --git a/src/core/netsplit.h b/src/core/netsplit.h index 4b6b1600..b68cb8fc 100644 --- a/src/core/netsplit.h +++ b/src/core/netsplit.h @@ -30,113 +30,114 @@ class Network; class Netsplit : public QObject { - Q_OBJECT + Q_OBJECT public: - Netsplit(Network *network, QObject *parent = 0); - - inline Network *network() const { return _network; } - - //! Add a user to the netsplit - /** Call this method if you noticed a netsplit. - * \note This method doesn't check if it really is a netsplit. - * \note Check with isNetsplit(const QString &quitMessage) before calling it! - * - * \param sender The sender string of the quitting user - * \param channels The channels that user shared with us - * \param msg The quit message - */ - void userQuit(const QString &sender, const QStringList &channels, const QString &msg); - - //! Remove a user from the netsplit - /** Call this method if a user joined after a netsplit occured. - * - * \param sender The sender string of the joined user - * \param channel The channel that user shares with us - * \return true if user was found in the netsplit - */ - bool userJoined(const QString &sender, const QString &channel); - - //! Check if user has joined since netsplit - /** This method shows if a user has already joined after being hit by netsplit - * \note The method doesn't check if the user was recorded in the netsplit! - * - * \param sender The sender string of the user - * \param channel The channel the user shares with us - * \return true if user joined after a netsplit - */ - bool userAlreadyJoined(const QString &sender, const QString &channel); - - //! Add mode to user - /** Use this method to buffer userspecific channel modes until netsplitJoin is emitted. - * - * \param sender The sender string of the user - * \param channel The channel the user shares with us - * \return true if user joined after a netsplit - */ - void addMode(const QString &sender, const QString &channel, const QString &mode); - - //! Check if a string matches the criteria for a netsplit - /** \param quitMessage The message to be checked - * \return true if the message is a netsplit - */ - static bool isNetsplit(const QString &quitMessage); + Netsplit(Network *network, QObject *parent = 0); + + inline Network *network() const { return _network; } + + //! Add a user to the netsplit + /** Call this method if you noticed a netsplit. + * \note This method doesn't check if it really is a netsplit. + * \note Check with isNetsplit(const QString &quitMessage) before calling it! + * + * \param sender The sender string of the quitting user + * \param channels The channels that user shared with us + * \param msg The quit message + */ + void userQuit(const QString &sender, const QStringList &channels, const QString &msg); + + //! Remove a user from the netsplit + /** Call this method if a user joined after a netsplit occured. + * + * \param sender The sender string of the joined user + * \param channel The channel that user shares with us + * \return true if user was found in the netsplit + */ + bool userJoined(const QString &sender, const QString &channel); + + //! Check if user has joined since netsplit + /** This method shows if a user has already joined after being hit by netsplit + * \note The method doesn't check if the user was recorded in the netsplit! + * + * \param sender The sender string of the user + * \param channel The channel the user shares with us + * \return true if user joined after a netsplit + */ + bool userAlreadyJoined(const QString &sender, const QString &channel); + + //! Add mode to user + /** Use this method to buffer userspecific channel modes until netsplitJoin is emitted. + * + * \param sender The sender string of the user + * \param channel The channel the user shares with us + * \return true if user joined after a netsplit + */ + void addMode(const QString &sender, const QString &channel, const QString &mode); + + //! Check if a string matches the criteria for a netsplit + /** \param quitMessage The message to be checked + * \return true if the message is a netsplit + */ + static bool isNetsplit(const QString &quitMessage); signals: - //! A bulk-join of netsplitted users timed out - /** Whenever the internal join-timer times out, we consider the bulk-join to be finished and emit that signal - * for every channel. This is the end of a netsplit. - * \param net The network - * \param channel The IRC channel - * \param users A list of all users that joined that channel - * \param modes A list of all modes the users got set after joining again - * \param quitMessage The Quitmessage and thus the servers that got split - */ - void netsplitJoin(Network *net, const QString &channel, const QStringList &users, const QStringList &modes, const QString &quitMessage); - - //! A (probably bulk-) join of netsplitted users. - /** If users hit by the split joined before the netsplit is considered over, join the users with a normal join. - * \param net The network - * \param channel The IRC channel - * \param users A list of all users that joined that channel - * \param modes A list of all modes the users got set after joining again - */ - void earlyJoin(Network *net, const QString &channel, const QStringList &users, const QStringList &modes); - - //! A bulk-quit of netsplitted users timed out - /** Whenever the internal quit-timer times out, we consider the bulk-quit to be finished and emit that signal - * for every channel. - * \param net The network - * \param channel The IRC channel - * \param users A list of all users that quitted in that channel - * \param quitMessage The Quitmessage and thus the servers that got split - */ - void netsplitQuit(Network *net, const QString &channel, const QStringList &users, const QString &quitMessage); - - //! The Netsplit is considered finished - /** This signal is emitted right after all netsplitJoin signals have been sent or whenever the - * internal timer signals a timeout. - * Simply delete the object and remove it from structures when you receive that signal. - */ - void finished(); + //! A bulk-join of netsplitted users timed out + /** Whenever the internal join-timer times out, we consider the bulk-join to be finished and emit that signal + * for every channel. This is the end of a netsplit. + * \param net The network + * \param channel The IRC channel + * \param users A list of all users that joined that channel + * \param modes A list of all modes the users got set after joining again + * \param quitMessage The Quitmessage and thus the servers that got split + */ + void netsplitJoin(Network *net, const QString &channel, const QStringList &users, const QStringList &modes, const QString &quitMessage); + + //! A (probably bulk-) join of netsplitted users. + /** If users hit by the split joined before the netsplit is considered over, join the users with a normal join. + * \param net The network + * \param channel The IRC channel + * \param users A list of all users that joined that channel + * \param modes A list of all modes the users got set after joining again + */ + void earlyJoin(Network *net, const QString &channel, const QStringList &users, const QStringList &modes); + + //! A bulk-quit of netsplitted users timed out + /** Whenever the internal quit-timer times out, we consider the bulk-quit to be finished and emit that signal + * for every channel. + * \param net The network + * \param channel The IRC channel + * \param users A list of all users that quitted in that channel + * \param quitMessage The Quitmessage and thus the servers that got split + */ + void netsplitQuit(Network *net, const QString &channel, const QStringList &users, const QString &quitMessage); + + //! The Netsplit is considered finished + /** This signal is emitted right after all netsplitJoin signals have been sent or whenever the + * internal timer signals a timeout. + * Simply delete the object and remove it from structures when you receive that signal. + */ + void finished(); private slots: - void joinTimeout(); - void quitTimeout(); + void joinTimeout(); + void quitTimeout(); private: - Network *_network; - QString _quitMsg; - // key: channel name - // value: senderstring, list of modes - QHash > _joins; - QHash _quits; - QHash _quitsWithMessageSent; - bool _sentQuit; - QTimer _joinTimer; - QTimer _quitTimer; - QTimer _discardTimer; - int _joinCounter; - int _quitCounter; + Network *_network; + QString _quitMsg; + // key: channel name + // value: senderstring, list of modes + QHash > _joins; + QHash _quits; + QHash _quitsWithMessageSent; + bool _sentQuit; + QTimer _joinTimer; + QTimer _quitTimer; + QTimer _discardTimer; + int _joinCounter; + int _quitCounter; }; + #endif // NETSPLIT_H diff --git a/src/core/oidentdconfiggenerator.cpp b/src/core/oidentdconfiggenerator.cpp index 8f65f50b..06ff272f 100644 --- a/src/core/oidentdconfiggenerator.cpp +++ b/src/core/oidentdconfiggenerator.cpp @@ -21,111 +21,125 @@ #include "oidentdconfiggenerator.h" OidentdConfigGenerator::OidentdConfigGenerator(QObject *parent) : - QObject(parent), - _initialized(false) + QObject(parent), + _initialized(false) { - if (!_initialized) - init(); + if (!_initialized) + init(); } -OidentdConfigGenerator::~OidentdConfigGenerator() { - _quasselConfig.clear(); - writeConfig(); - _configFile->deleteLater(); + +OidentdConfigGenerator::~OidentdConfigGenerator() +{ + _quasselConfig.clear(); + writeConfig(); + _configFile->deleteLater(); } -bool OidentdConfigGenerator::init() { - _configDir = QDir::homePath(); - _configFileName = ".oidentd.conf"; - if(Quassel::isOptionSet("oidentd-conffile")) - _configPath = Quassel::optionValue("oidentd-conffile"); - else - _configPath = _configDir.absoluteFilePath(_configFileName); +bool OidentdConfigGenerator::init() +{ + _configDir = QDir::homePath(); + _configFileName = ".oidentd.conf"; - _configTag = " stanza created by Quassel"; + if (Quassel::isOptionSet("oidentd-conffile")) + _configPath = Quassel::optionValue("oidentd-conffile"); + else + _configPath = _configDir.absoluteFilePath(_configFileName); - _configFile = new QFile(_configPath); + _configTag = " stanza created by Quassel"; - // Rx has to match Template in order for cleanup to work. - // Template should be enhanced with the "from" parameter as soon as Quassel gains - // the ability to bind to an IP on client sockets. + _configFile = new QFile(_configPath); - _quasselStanzaTemplate = QString("lport %1 { reply \"%2\" } #%3\n"); - _quasselStanzaRx = QRegExp(QString("^lport .* \\{ .* \\} #%1\\r?\\n").arg(_configTag)); + // Rx has to match Template in order for cleanup to work. + // Template should be enhanced with the "from" parameter as soon as Quassel gains + // the ability to bind to an IP on client sockets. - // initially remove all Quassel stanzas that might be present - if (parseConfig(false) && writeConfig()) - _initialized = true; + _quasselStanzaTemplate = QString("lport %1 { reply \"%2\" } #%3\n"); + _quasselStanzaRx = QRegExp(QString("^lport .* \\{ .* \\} #%1\\r?\\n").arg(_configTag)); - return _initialized; + // initially remove all Quassel stanzas that might be present + if (parseConfig(false) && writeConfig()) + _initialized = true; + + return _initialized; } -bool OidentdConfigGenerator::addSocket(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, const QHostAddress &peerAddress, quint16 peerPort) { - Q_UNUSED(localAddress) Q_UNUSED(peerAddress) Q_UNUSED(peerPort) - QString ident = identity->ident(); - _quasselConfig.append(_quasselStanzaTemplate.arg(localPort).arg(ident).arg(_configTag).toAscii()); +bool OidentdConfigGenerator::addSocket(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, const QHostAddress &peerAddress, quint16 peerPort) +{ + Q_UNUSED(localAddress) Q_UNUSED(peerAddress) Q_UNUSED(peerPort) + QString ident = identity->ident(); - bool ret = writeConfig(); + _quasselConfig.append(_quasselStanzaTemplate.arg(localPort).arg(ident).arg(_configTag).toAscii()); - return ret; -} + bool ret = writeConfig(); -//! not yet implemented -bool OidentdConfigGenerator::removeSocket(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, const QHostAddress &peerAddress, quint16 peerPort) { - Q_UNUSED(identity) Q_UNUSED(localAddress) Q_UNUSED(localPort) Q_UNUSED(peerAddress) Q_UNUSED(peerPort) - return true; + return ret; } -bool OidentdConfigGenerator::parseConfig(bool readQuasselStanzas) { - if (!_configFile->exists()) - return true; - if (!_configFile->isOpen() && !_configFile->open(QIODevice::ReadOnly)) - return false; - _mutex.lock(); - - _parsedConfig.clear(); - _configFile->seek(0); - while (!_configFile->atEnd()) { - QByteArray line = _configFile->readLine(); +//! not yet implemented +bool OidentdConfigGenerator::removeSocket(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, const QHostAddress &peerAddress, quint16 peerPort) +{ + Q_UNUSED(identity) Q_UNUSED(localAddress) Q_UNUSED(localPort) Q_UNUSED(peerAddress) Q_UNUSED(peerPort) + return true; +} - if (!lineByUs(line)) - _parsedConfig.append(line); - else if (readQuasselStanzas) - _quasselConfig.append(line); - } - _configFile->close(); - _mutex.unlock(); - return true; +bool OidentdConfigGenerator::parseConfig(bool readQuasselStanzas) +{ + if (!_configFile->exists()) + return true; + + if (!_configFile->isOpen() && !_configFile->open(QIODevice::ReadOnly)) + return false; + _mutex.lock(); + + _parsedConfig.clear(); + _configFile->seek(0); + while (!_configFile->atEnd()) { + QByteArray line = _configFile->readLine(); + + if (!lineByUs(line)) + _parsedConfig.append(line); + else if (readQuasselStanzas) + _quasselConfig.append(line); + } + + _configFile->close(); + _mutex.unlock(); + return true; } -bool OidentdConfigGenerator::writeConfig() { + +bool OidentdConfigGenerator::writeConfig() +{ #ifdef HAVE_UMASK - mode_t prev_umask = umask(S_IXUSR | S_IWGRP | S_IXGRP | S_IWOTH | S_IXOTH); // == 0133, rw-r--r-- + mode_t prev_umask = umask(S_IXUSR | S_IWGRP | S_IXGRP | S_IWOTH | S_IXOTH); // == 0133, rw-r--r-- #endif - bool not_open = (!_configFile->isOpen() && !_configFile->open(QIODevice::ReadWrite | QIODevice::Text)); + bool not_open = (!_configFile->isOpen() && !_configFile->open(QIODevice::ReadWrite | QIODevice::Text)); #ifdef HAVE_UMASK - umask(prev_umask); + umask(prev_umask); #endif - if (not_open) - return false; + if (not_open) + return false; - _mutex.lock(); + _mutex.lock(); - _configFile->seek(0); - _configFile->resize(0); - _configFile->write(_parsedConfig); - _configFile->write(_quasselConfig); + _configFile->seek(0); + _configFile->resize(0); + _configFile->write(_parsedConfig); + _configFile->write(_quasselConfig); - _configFile->close(); - _mutex.unlock(); - return true; + _configFile->close(); + _mutex.unlock(); + return true; } -bool OidentdConfigGenerator::lineByUs(const QByteArray &line) { - return _quasselStanzaRx.exactMatch(line); + +bool OidentdConfigGenerator::lineByUs(const QByteArray &line) +{ + return _quasselStanzaRx.exactMatch(line); } diff --git a/src/core/oidentdconfiggenerator.h b/src/core/oidentdconfiggenerator.h index 0636a514..4026e553 100644 --- a/src/core/oidentdconfiggenerator.h +++ b/src/core/oidentdconfiggenerator.h @@ -56,35 +56,36 @@ class OidentdConfigGenerator : public QObject { - Q_OBJECT + Q_OBJECT public: - explicit OidentdConfigGenerator(QObject *parent = 0); - ~OidentdConfigGenerator(); + explicit OidentdConfigGenerator(QObject *parent = 0); + ~OidentdConfigGenerator(); public slots: - bool addSocket(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, const QHostAddress &peerAddress, quint16 peerPort); - bool removeSocket(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, const QHostAddress &peerAddress, quint16 peerPort); + bool addSocket(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, const QHostAddress &peerAddress, quint16 peerPort); + bool removeSocket(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, const QHostAddress &peerAddress, quint16 peerPort); private: - bool init(); - bool writeConfig(); - bool parseConfig(bool readQuasselStanzas = false); - bool lineByUs(const QByteArray &line); - - bool _initialized; - QDateTime _lastSync; - QFile *_configFile; - QByteArray _parsedConfig; - QByteArray _quasselConfig; - // Mutex isn't strictly necessary at the moment, since with the current invocation in Core only one instance at a time exists - QMutex _mutex; - - QDir _configDir; - QString _configFileName; - QString _configPath; - QString _configTag; - QRegExp _quasselStanzaRx; - QString _quasselStanzaTemplate; + bool init(); + bool writeConfig(); + bool parseConfig(bool readQuasselStanzas = false); + bool lineByUs(const QByteArray &line); + + bool _initialized; + QDateTime _lastSync; + QFile *_configFile; + QByteArray _parsedConfig; + QByteArray _quasselConfig; + // Mutex isn't strictly necessary at the moment, since with the current invocation in Core only one instance at a time exists + QMutex _mutex; + + QDir _configDir; + QString _configFileName; + QString _configPath; + QString _configTag; + QRegExp _quasselStanzaRx; + QString _quasselStanzaTemplate; }; + #endif // OIDENTDCONFIGGENERATOR_H diff --git a/src/core/postgresqlstorage.cpp b/src/core/postgresqlstorage.cpp index 2de29604..d1959d58 100644 --- a/src/core/postgresqlstorage.cpp +++ b/src/core/postgresqlstorage.cpp @@ -27,1409 +27,1535 @@ #include "quassel.h" PostgreSqlStorage::PostgreSqlStorage(QObject *parent) - : AbstractSqlStorage(parent), + : AbstractSqlStorage(parent), _port(-1) { } -PostgreSqlStorage::~PostgreSqlStorage() { + +PostgreSqlStorage::~PostgreSqlStorage() +{ } -AbstractSqlMigrationWriter *PostgreSqlStorage::createMigrationWriter() { - PostgreSqlMigrationWriter *writer = new PostgreSqlMigrationWriter(); - QVariantMap properties; - properties["Username"] = _userName; - properties["Password"] = _password; - properties["Hostname"] = _hostName; - properties["Port"] = _port; - properties["Database"] = _databaseName; - writer->setConnectionProperties(properties); - return writer; + +AbstractSqlMigrationWriter *PostgreSqlStorage::createMigrationWriter() +{ + PostgreSqlMigrationWriter *writer = new PostgreSqlMigrationWriter(); + QVariantMap properties; + properties["Username"] = _userName; + properties["Password"] = _password; + properties["Hostname"] = _hostName; + properties["Port"] = _port; + properties["Database"] = _databaseName; + writer->setConnectionProperties(properties); + return writer; } -bool PostgreSqlStorage::isAvailable() const { - qDebug() << QSqlDatabase::drivers(); - if(!QSqlDatabase::isDriverAvailable("QPSQL")) return false; - return true; + +bool PostgreSqlStorage::isAvailable() const +{ + qDebug() << QSqlDatabase::drivers(); + if (!QSqlDatabase::isDriverAvailable("QPSQL")) return false; + return true; } -QString PostgreSqlStorage::displayName() const { - return QString("PostgreSQL"); + +QString PostgreSqlStorage::displayName() const +{ + return QString("PostgreSQL"); } -QString PostgreSqlStorage::description() const { - // FIXME: proper description - return tr("PostgreSQL Turbo Bomber HD!"); + +QString PostgreSqlStorage::description() const +{ + // FIXME: proper description + return tr("PostgreSQL Turbo Bomber HD!"); } -QStringList PostgreSqlStorage::setupKeys() const { - QStringList keys; - keys << "Username" - << "Password" - << "Hostname" - << "Port" - << "Database"; - return keys; + +QStringList PostgreSqlStorage::setupKeys() const +{ + QStringList keys; + keys << "Username" + << "Password" + << "Hostname" + << "Port" + << "Database"; + return keys; } -QVariantMap PostgreSqlStorage::setupDefaults() const { - QVariantMap map; - map["Username"] = QVariant(QString("quassel")); - map["Hostname"] = QVariant(QString("localhost")); - map["Port"] = QVariant(5432); - map["Database"] = QVariant(QString("quassel")); - return map; + + +QVariantMap PostgreSqlStorage::setupDefaults() const +{ + QVariantMap map; + map["Username"] = QVariant(QString("quassel")); + map["Hostname"] = QVariant(QString("localhost")); + map["Port"] = QVariant(5432); + map["Database"] = QVariant(QString("quassel")); + return map; } -void PostgreSqlStorage::initDbSession(QSqlDatabase &db) { - // this blows... but unfortunately Qt's PG driver forces us to this... - db.exec("set standard_conforming_strings = off"); - db.exec("set escape_string_warning = off"); + +void PostgreSqlStorage::initDbSession(QSqlDatabase &db) +{ + // this blows... but unfortunately Qt's PG driver forces us to this... + db.exec("set standard_conforming_strings = off"); + db.exec("set escape_string_warning = off"); } -void PostgreSqlStorage::setConnectionProperties(const QVariantMap &properties) { - _userName = properties["Username"].toString(); - _password = properties["Password"].toString(); - _hostName = properties["Hostname"].toString(); - _port = properties["Port"].toInt(); - _databaseName = properties["Database"].toString(); + +void PostgreSqlStorage::setConnectionProperties(const QVariantMap &properties) +{ + _userName = properties["Username"].toString(); + _password = properties["Password"].toString(); + _hostName = properties["Hostname"].toString(); + _port = properties["Port"].toInt(); + _databaseName = properties["Database"].toString(); } -int PostgreSqlStorage::installedSchemaVersion() { - QSqlQuery query = logDb().exec("SELECT value FROM coreinfo WHERE key = 'schemaversion'"); - if(query.first()) - return query.value(0).toInt(); - // maybe it's really old... (schema version 0) - query = logDb().exec("SELECT MAX(version) FROM coreinfo"); - if(query.first()) - return query.value(0).toInt(); +int PostgreSqlStorage::installedSchemaVersion() +{ + QSqlQuery query = logDb().exec("SELECT value FROM coreinfo WHERE key = 'schemaversion'"); + if (query.first()) + return query.value(0).toInt(); + + // maybe it's really old... (schema version 0) + query = logDb().exec("SELECT MAX(version) FROM coreinfo"); + if (query.first()) + return query.value(0).toInt(); - return AbstractSqlStorage::installedSchemaVersion(); + return AbstractSqlStorage::installedSchemaVersion(); } -bool PostgreSqlStorage::updateSchemaVersion(int newVersion) { - QSqlQuery query(logDb()); - query.prepare("UPDATE coreinfo SET value = :version WHERE key = 'schemaversion'"); - query.bindValue(":version", newVersion); - query.exec(); - bool success = true; - if(query.lastError().isValid()) { - qCritical() << "PostgreSqlStorage::updateSchemaVersion(int): Updating schema version failed!"; - success = false; - } - return success; +bool PostgreSqlStorage::updateSchemaVersion(int newVersion) +{ + QSqlQuery query(logDb()); + query.prepare("UPDATE coreinfo SET value = :version WHERE key = 'schemaversion'"); + query.bindValue(":version", newVersion); + query.exec(); + + bool success = true; + if (query.lastError().isValid()) { + qCritical() << "PostgreSqlStorage::updateSchemaVersion(int): Updating schema version failed!"; + success = false; + } + return success; } - -bool PostgreSqlStorage::setupSchemaVersion(int version) { - QSqlQuery query(logDb()); - query.prepare("INSERT INTO coreinfo (key, value) VALUES ('schemaversion', :version)"); - query.bindValue(":version", version); - query.exec(); - - bool success = true; - if(query.lastError().isValid()) { - qCritical() << "PostgreSqlStorage::setupSchemaVersion(int): Updating schema version failed!"; - success = false; - } - return success; -} - -UserId PostgreSqlStorage::addUser(const QString &user, const QString &password) { - QSqlQuery query(logDb()); - query.prepare(queryString("insert_quasseluser")); - query.bindValue(":username", user); - query.bindValue(":password", cryptedPassword(password)); - safeExec(query); - if(!watchQuery(query)) - return 0; - - query.first(); - UserId uid = query.value(0).toInt(); - emit userAdded(uid, user); - return uid; -} - -bool PostgreSqlStorage::updateUser(UserId user, const QString &password) { - QSqlQuery query(logDb()); - query.prepare(queryString("update_userpassword")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":password", cryptedPassword(password)); - safeExec(query); - return query.numRowsAffected() != 0; -} - -void PostgreSqlStorage::renameUser(UserId user, const QString &newName) { - QSqlQuery query(logDb()); - query.prepare(queryString("update_username")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":username", newName); - safeExec(query); - emit userRenamed(user, newName); -} - -UserId PostgreSqlStorage::validateUser(const QString &user, const QString &password) { - QSqlQuery query(logDb()); - query.prepare(queryString("select_authuser")); - query.bindValue(":username", user); - query.bindValue(":password", cryptedPassword(password)); - safeExec(query); - - if(query.first()) { - return query.value(0).toInt(); - } else { - return 0; - } -} - -UserId PostgreSqlStorage::getUserId(const QString &user) { - QSqlQuery query(logDb()); - query.prepare(queryString("select_userid")); - query.bindValue(":username", user); - safeExec(query); - - if(query.first()) { - return query.value(0).toInt(); - } else { - return 0; - } -} - -UserId PostgreSqlStorage::internalUser() { - QSqlQuery query(logDb()); - query.prepare(queryString("select_internaluser")); - safeExec(query); - - if(query.first()) { - return query.value(0).toInt(); - } else { - return 0; - } -} - -void PostgreSqlStorage::delUser(UserId user) { - QSqlDatabase db = logDb(); - if(!db.transaction()) { - qWarning() << "PostgreSqlStorage::delUser(): cannot start transaction!"; - return; - } - - QSqlQuery query(db); - query.prepare(queryString("delete_quasseluser")); - query.bindValue(":userid", user.toInt()); - safeExec(query); - if(!watchQuery(query)) { - db.rollback(); - return; - } else { - db.commit(); - emit userRemoved(user); - } + + +bool PostgreSqlStorage::setupSchemaVersion(int version) +{ + QSqlQuery query(logDb()); + query.prepare("INSERT INTO coreinfo (key, value) VALUES ('schemaversion', :version)"); + query.bindValue(":version", version); + query.exec(); + + bool success = true; + if (query.lastError().isValid()) { + qCritical() << "PostgreSqlStorage::setupSchemaVersion(int): Updating schema version failed!"; + success = false; + } + return success; } -void PostgreSqlStorage::setUserSetting(UserId userId, const QString &settingName, const QVariant &data) { - QByteArray rawData; - QDataStream out(&rawData, QIODevice::WriteOnly); - out.setVersion(QDataStream::Qt_4_2); - out << data; - QSqlDatabase db = logDb(); - QSqlQuery query(db); - query.prepare(queryString("insert_user_setting")); - query.bindValue(":userid", userId.toInt()); - query.bindValue(":settingname", settingName); - query.bindValue(":settingvalue", rawData); - safeExec(query); +UserId PostgreSqlStorage::addUser(const QString &user, const QString &password) +{ + QSqlQuery query(logDb()); + query.prepare(queryString("insert_quasseluser")); + query.bindValue(":username", user); + query.bindValue(":password", cryptedPassword(password)); + safeExec(query); + if (!watchQuery(query)) + return 0; + + query.first(); + UserId uid = query.value(0).toInt(); + emit userAdded(uid, user); + return uid; +} - if(query.lastError().isValid()) { - QSqlQuery updateQuery(db); - updateQuery.prepare(queryString("update_user_setting")); - updateQuery.bindValue(":userid", userId.toInt()); - updateQuery.bindValue(":settingname", settingName); - updateQuery.bindValue(":settingvalue", rawData); - safeExec(updateQuery); - } +bool PostgreSqlStorage::updateUser(UserId user, const QString &password) +{ + QSqlQuery query(logDb()); + query.prepare(queryString("update_userpassword")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":password", cryptedPassword(password)); + safeExec(query); + return query.numRowsAffected() != 0; } -QVariant PostgreSqlStorage::getUserSetting(UserId userId, const QString &settingName, const QVariant &defaultData) { - QSqlQuery query(logDb()); - query.prepare(queryString("select_user_setting")); - query.bindValue(":userid", userId.toInt()); - query.bindValue(":settingname", settingName); - safeExec(query); - if(query.first()) { - QVariant data; - QByteArray rawData = query.value(0).toByteArray(); - QDataStream in(&rawData, QIODevice::ReadOnly); - in.setVersion(QDataStream::Qt_4_2); - in >> data; - return data; - } else { - return defaultData; - } +void PostgreSqlStorage::renameUser(UserId user, const QString &newName) +{ + QSqlQuery query(logDb()); + query.prepare(queryString("update_username")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":username", newName); + safeExec(query); + emit userRenamed(user, newName); } -IdentityId PostgreSqlStorage::createIdentity(UserId user, CoreIdentity &identity) { - IdentityId identityId; - QSqlDatabase db = logDb(); - if(!db.transaction()) { - qWarning() << "PostgreSqlStorage::createIdentity(): Unable to start Transaction!"; - qWarning() << " -" << qPrintable(db.lastError().text()); - return identityId; - } - - QSqlQuery query(db); - query.prepare(queryString("insert_identity")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":identityname", identity.identityName()); - query.bindValue(":realname", identity.realName()); - query.bindValue(":awaynick", identity.awayNick()); - query.bindValue(":awaynickenabled", identity.awayNickEnabled()); - query.bindValue(":awayreason", identity.awayReason()); - query.bindValue(":awayreasonenabled", identity.awayReasonEnabled()); - query.bindValue(":autoawayenabled", identity.awayReasonEnabled()); - query.bindValue(":autoawaytime", identity.autoAwayTime()); - query.bindValue(":autoawayreason", identity.autoAwayReason()); - query.bindValue(":autoawayreasonenabled", identity.autoAwayReasonEnabled()); - query.bindValue(":detachawayenabled", identity.detachAwayEnabled()); - query.bindValue(":detachawayreason", identity.detachAwayReason()); - query.bindValue(":detachawayreasonenabled", identity.detachAwayReasonEnabled()); - query.bindValue(":ident", identity.ident()); - query.bindValue(":kickreason", identity.kickReason()); - query.bindValue(":partreason", identity.partReason()); - query.bindValue(":quitreason", identity.quitReason()); +UserId PostgreSqlStorage::validateUser(const QString &user, const QString &password) +{ + QSqlQuery query(logDb()); + query.prepare(queryString("select_authuser")); + query.bindValue(":username", user); + query.bindValue(":password", cryptedPassword(password)); + safeExec(query); + + if (query.first()) { + return query.value(0).toInt(); + } + else { + return 0; + } +} + + +UserId PostgreSqlStorage::getUserId(const QString &user) +{ + QSqlQuery query(logDb()); + query.prepare(queryString("select_userid")); + query.bindValue(":username", user); + safeExec(query); + + if (query.first()) { + return query.value(0).toInt(); + } + else { + return 0; + } +} + + +UserId PostgreSqlStorage::internalUser() +{ + QSqlQuery query(logDb()); + query.prepare(queryString("select_internaluser")); + safeExec(query); + + if (query.first()) { + return query.value(0).toInt(); + } + else { + return 0; + } +} + + +void PostgreSqlStorage::delUser(UserId user) +{ + QSqlDatabase db = logDb(); + if (!db.transaction()) { + qWarning() << "PostgreSqlStorage::delUser(): cannot start transaction!"; + return; + } + + QSqlQuery query(db); + query.prepare(queryString("delete_quasseluser")); + query.bindValue(":userid", user.toInt()); + safeExec(query); + if (!watchQuery(query)) { + db.rollback(); + return; + } + else { + db.commit(); + emit userRemoved(user); + } +} + + +void PostgreSqlStorage::setUserSetting(UserId userId, const QString &settingName, const QVariant &data) +{ + QByteArray rawData; + QDataStream out(&rawData, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_2); + out << data; + + QSqlDatabase db = logDb(); + QSqlQuery query(db); + query.prepare(queryString("insert_user_setting")); + query.bindValue(":userid", userId.toInt()); + query.bindValue(":settingname", settingName); + query.bindValue(":settingvalue", rawData); + safeExec(query); + + if (query.lastError().isValid()) { + QSqlQuery updateQuery(db); + updateQuery.prepare(queryString("update_user_setting")); + updateQuery.bindValue(":userid", userId.toInt()); + updateQuery.bindValue(":settingname", settingName); + updateQuery.bindValue(":settingvalue", rawData); + safeExec(updateQuery); + } +} + + +QVariant PostgreSqlStorage::getUserSetting(UserId userId, const QString &settingName, const QVariant &defaultData) +{ + QSqlQuery query(logDb()); + query.prepare(queryString("select_user_setting")); + query.bindValue(":userid", userId.toInt()); + query.bindValue(":settingname", settingName); + safeExec(query); + + if (query.first()) { + QVariant data; + QByteArray rawData = query.value(0).toByteArray(); + QDataStream in(&rawData, QIODevice::ReadOnly); + in.setVersion(QDataStream::Qt_4_2); + in >> data; + return data; + } + else { + return defaultData; + } +} + + +IdentityId PostgreSqlStorage::createIdentity(UserId user, CoreIdentity &identity) +{ + IdentityId identityId; + + QSqlDatabase db = logDb(); + if (!db.transaction()) { + qWarning() << "PostgreSqlStorage::createIdentity(): Unable to start Transaction!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return identityId; + } + + QSqlQuery query(db); + query.prepare(queryString("insert_identity")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":identityname", identity.identityName()); + query.bindValue(":realname", identity.realName()); + query.bindValue(":awaynick", identity.awayNick()); + query.bindValue(":awaynickenabled", identity.awayNickEnabled()); + query.bindValue(":awayreason", identity.awayReason()); + query.bindValue(":awayreasonenabled", identity.awayReasonEnabled()); + query.bindValue(":autoawayenabled", identity.awayReasonEnabled()); + query.bindValue(":autoawaytime", identity.autoAwayTime()); + query.bindValue(":autoawayreason", identity.autoAwayReason()); + query.bindValue(":autoawayreasonenabled", identity.autoAwayReasonEnabled()); + query.bindValue(":detachawayenabled", identity.detachAwayEnabled()); + query.bindValue(":detachawayreason", identity.detachAwayReason()); + query.bindValue(":detachawayreasonenabled", identity.detachAwayReasonEnabled()); + query.bindValue(":ident", identity.ident()); + query.bindValue(":kickreason", identity.kickReason()); + query.bindValue(":partreason", identity.partReason()); + query.bindValue(":quitreason", identity.quitReason()); #ifdef HAVE_SSL - query.bindValue(":sslcert", identity.sslCert().toPem()); - query.bindValue(":sslkey", identity.sslKey().toPem()); + query.bindValue(":sslcert", identity.sslCert().toPem()); + query.bindValue(":sslkey", identity.sslKey().toPem()); #else - query.bindValue(":sslcert", QByteArray()); - query.bindValue(":sslkey", QByteArray()); + query.bindValue(":sslcert", QByteArray()); + query.bindValue(":sslkey", QByteArray()); #endif - safeExec(query); - if(query.lastError().isValid()) { - watchQuery(query); - db.rollback(); - return IdentityId(); - } + safeExec(query); + if (query.lastError().isValid()) { + watchQuery(query); + db.rollback(); + return IdentityId(); + } - query.first(); - identityId = query.value(0).toInt(); - identity.setId(identityId); + query.first(); + identityId = query.value(0).toInt(); + identity.setId(identityId); - if(!identityId.isValid()) { - watchQuery(query); - db.rollback(); - return IdentityId(); - } - - QSqlQuery insertNickQuery(db); - insertNickQuery.prepare(queryString("insert_nick")); - foreach(QString nick, identity.nicks()) { - insertNickQuery.bindValue(":identityid", identityId.toInt()); - insertNickQuery.bindValue(":nick", nick); - safeExec(insertNickQuery); - if(!watchQuery(insertNickQuery)) { - db.rollback(); - return IdentityId(); - } - } - - if(!db.commit()) { - qWarning() << "PostgreSqlStorage::createIdentity(): committing data failed!"; - qWarning() << " -" << qPrintable(db.lastError().text()); - return IdentityId(); - } - return identityId; -} - -bool PostgreSqlStorage::updateIdentity(UserId user, const CoreIdentity &identity) { - QSqlDatabase db = logDb(); - if(!db.transaction()) { - qWarning() << "PostgreSqlStorage::updateIdentity(): Unable to start Transaction!"; - qWarning() << " -" << qPrintable(db.lastError().text()); - return false; - } - - QSqlQuery checkQuery(db); - checkQuery.prepare(queryString("select_checkidentity")); - checkQuery.bindValue(":identityid", identity.id().toInt()); - checkQuery.bindValue(":userid", user.toInt()); - safeExec(checkQuery); - - // there should be exactly one identity for the given id and user - if(!checkQuery.first() || checkQuery.value(0).toInt() != 1) { - db.rollback(); - return false; - } - - QSqlQuery query(db); - query.prepare(queryString("update_identity")); - query.bindValue(":identityname", identity.identityName()); - query.bindValue(":realname", identity.realName()); - query.bindValue(":awaynick", identity.awayNick()); - query.bindValue(":awaynickenabled", identity.awayNickEnabled()); - query.bindValue(":awayreason", identity.awayReason()); - query.bindValue(":awayreasonenabled", identity.awayReasonEnabled()); - query.bindValue(":autoawayenabled", identity.awayReasonEnabled()); - query.bindValue(":autoawaytime", identity.autoAwayTime()); - query.bindValue(":autoawayreason", identity.autoAwayReason()); - query.bindValue(":autoawayreasonenabled", identity.autoAwayReasonEnabled()); - query.bindValue(":detachawayenabled", identity.detachAwayEnabled()); - query.bindValue(":detachawayreason", identity.detachAwayReason()); - query.bindValue(":detachawayreasonenabled", identity.detachAwayReasonEnabled()); - query.bindValue(":ident", identity.ident()); - query.bindValue(":kickreason", identity.kickReason()); - query.bindValue(":partreason", identity.partReason()); - query.bindValue(":quitreason", identity.quitReason()); + if (!identityId.isValid()) { + watchQuery(query); + db.rollback(); + return IdentityId(); + } + + QSqlQuery insertNickQuery(db); + insertNickQuery.prepare(queryString("insert_nick")); + foreach(QString nick, identity.nicks()) { + insertNickQuery.bindValue(":identityid", identityId.toInt()); + insertNickQuery.bindValue(":nick", nick); + safeExec(insertNickQuery); + if (!watchQuery(insertNickQuery)) { + db.rollback(); + return IdentityId(); + } + } + + if (!db.commit()) { + qWarning() << "PostgreSqlStorage::createIdentity(): committing data failed!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return IdentityId(); + } + return identityId; +} + + +bool PostgreSqlStorage::updateIdentity(UserId user, const CoreIdentity &identity) +{ + QSqlDatabase db = logDb(); + if (!db.transaction()) { + qWarning() << "PostgreSqlStorage::updateIdentity(): Unable to start Transaction!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return false; + } + + QSqlQuery checkQuery(db); + checkQuery.prepare(queryString("select_checkidentity")); + checkQuery.bindValue(":identityid", identity.id().toInt()); + checkQuery.bindValue(":userid", user.toInt()); + safeExec(checkQuery); + + // there should be exactly one identity for the given id and user + if (!checkQuery.first() || checkQuery.value(0).toInt() != 1) { + db.rollback(); + return false; + } + + QSqlQuery query(db); + query.prepare(queryString("update_identity")); + query.bindValue(":identityname", identity.identityName()); + query.bindValue(":realname", identity.realName()); + query.bindValue(":awaynick", identity.awayNick()); + query.bindValue(":awaynickenabled", identity.awayNickEnabled()); + query.bindValue(":awayreason", identity.awayReason()); + query.bindValue(":awayreasonenabled", identity.awayReasonEnabled()); + query.bindValue(":autoawayenabled", identity.awayReasonEnabled()); + query.bindValue(":autoawaytime", identity.autoAwayTime()); + query.bindValue(":autoawayreason", identity.autoAwayReason()); + query.bindValue(":autoawayreasonenabled", identity.autoAwayReasonEnabled()); + query.bindValue(":detachawayenabled", identity.detachAwayEnabled()); + query.bindValue(":detachawayreason", identity.detachAwayReason()); + query.bindValue(":detachawayreasonenabled", identity.detachAwayReasonEnabled()); + query.bindValue(":ident", identity.ident()); + query.bindValue(":kickreason", identity.kickReason()); + query.bindValue(":partreason", identity.partReason()); + query.bindValue(":quitreason", identity.quitReason()); #ifdef HAVE_SSL - query.bindValue(":sslcert", identity.sslCert().toPem()); - query.bindValue(":sslkey", identity.sslKey().toPem()); + query.bindValue(":sslcert", identity.sslCert().toPem()); + query.bindValue(":sslkey", identity.sslKey().toPem()); #else - query.bindValue(":sslcert", QByteArray()); - query.bindValue(":sslkey", QByteArray()); + query.bindValue(":sslcert", QByteArray()); + query.bindValue(":sslkey", QByteArray()); #endif - query.bindValue(":identityid", identity.id().toInt()); - - safeExec(query); - if(!watchQuery(query)) { - db.rollback(); - return false; - } - - QSqlQuery deleteNickQuery(db); - deleteNickQuery.prepare(queryString("delete_nicks")); - deleteNickQuery.bindValue(":identityid", identity.id().toInt()); - safeExec(deleteNickQuery); - if(!watchQuery(deleteNickQuery)) { - db.rollback(); - return false; - } - - QSqlQuery insertNickQuery(db); - insertNickQuery.prepare(queryString("insert_nick")); - foreach(QString nick, identity.nicks()) { - insertNickQuery.bindValue(":identityid", identity.id().toInt()); - insertNickQuery.bindValue(":nick", nick); - safeExec(insertNickQuery); - if(!watchQuery(insertNickQuery)) { - db.rollback(); - return false; - } - } - - if(!db.commit()) { - qWarning() << "PostgreSqlStorage::updateIdentity(): committing data failed!"; - qWarning() << " -" << qPrintable(db.lastError().text()); - return false; - } - return true; -} - -void PostgreSqlStorage::removeIdentity(UserId user, IdentityId identityId) { - QSqlDatabase db = logDb(); - if(!db.transaction()) { - qWarning() << "PostgreSqlStorage::removeIdentity(): Unable to start Transaction!"; - qWarning() << " -" << qPrintable(db.lastError().text()); - return; - } - - QSqlQuery query(db); - query.prepare(queryString("delete_identity")); - query.bindValue(":identityid", identityId.toInt()); - query.bindValue(":userid", user.toInt()); - safeExec(query); - if(!watchQuery(query)) { - db.rollback(); - } else { - db.commit(); - } + query.bindValue(":identityid", identity.id().toInt()); + + safeExec(query); + if (!watchQuery(query)) { + db.rollback(); + return false; + } + + QSqlQuery deleteNickQuery(db); + deleteNickQuery.prepare(queryString("delete_nicks")); + deleteNickQuery.bindValue(":identityid", identity.id().toInt()); + safeExec(deleteNickQuery); + if (!watchQuery(deleteNickQuery)) { + db.rollback(); + return false; + } + + QSqlQuery insertNickQuery(db); + insertNickQuery.prepare(queryString("insert_nick")); + foreach(QString nick, identity.nicks()) { + insertNickQuery.bindValue(":identityid", identity.id().toInt()); + insertNickQuery.bindValue(":nick", nick); + safeExec(insertNickQuery); + if (!watchQuery(insertNickQuery)) { + db.rollback(); + return false; + } + } + + if (!db.commit()) { + qWarning() << "PostgreSqlStorage::updateIdentity(): committing data failed!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return false; + } + return true; } -QList PostgreSqlStorage::identities(UserId user) { - QList identities; - QSqlDatabase db = logDb(); - if(!beginReadOnlyTransaction(db)) { - qWarning() << "PostgreSqlStorage::identites(): cannot start read only transaction!"; - qWarning() << " -" << qPrintable(db.lastError().text()); - return identities; - } - - QSqlQuery query(db); - query.prepare(queryString("select_identities")); - query.bindValue(":userid", user.toInt()); - - QSqlQuery nickQuery(db); - nickQuery.prepare(queryString("select_nicks")); - - safeExec(query); - - while(query.next()) { - CoreIdentity identity(IdentityId(query.value(0).toInt())); - - identity.setIdentityName(query.value(1).toString()); - identity.setRealName(query.value(2).toString()); - identity.setAwayNick(query.value(3).toString()); - identity.setAwayNickEnabled(!!query.value(4).toInt()); - identity.setAwayReason(query.value(5).toString()); - identity.setAwayReasonEnabled(!!query.value(6).toInt()); - identity.setAutoAwayEnabled(!!query.value(7).toInt()); - identity.setAutoAwayTime(query.value(8).toInt()); - identity.setAutoAwayReason(query.value(9).toString()); - identity.setAutoAwayReasonEnabled(!!query.value(10).toInt()); - identity.setDetachAwayEnabled(!!query.value(11).toInt()); - identity.setDetachAwayReason(query.value(12).toString()); - identity.setDetachAwayReasonEnabled(!!query.value(13).toInt()); - identity.setIdent(query.value(14).toString()); - identity.setKickReason(query.value(15).toString()); - identity.setPartReason(query.value(16).toString()); - identity.setQuitReason(query.value(17).toString()); +void PostgreSqlStorage::removeIdentity(UserId user, IdentityId identityId) +{ + QSqlDatabase db = logDb(); + if (!db.transaction()) { + qWarning() << "PostgreSqlStorage::removeIdentity(): Unable to start Transaction!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return; + } + + QSqlQuery query(db); + query.prepare(queryString("delete_identity")); + query.bindValue(":identityid", identityId.toInt()); + query.bindValue(":userid", user.toInt()); + safeExec(query); + if (!watchQuery(query)) { + db.rollback(); + } + else { + db.commit(); + } +} + + +QList PostgreSqlStorage::identities(UserId user) +{ + QList identities; + + QSqlDatabase db = logDb(); + if (!beginReadOnlyTransaction(db)) { + qWarning() << "PostgreSqlStorage::identites(): cannot start read only transaction!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return identities; + } + + QSqlQuery query(db); + query.prepare(queryString("select_identities")); + query.bindValue(":userid", user.toInt()); + + QSqlQuery nickQuery(db); + nickQuery.prepare(queryString("select_nicks")); + + safeExec(query); + + while (query.next()) { + CoreIdentity identity(IdentityId(query.value(0).toInt())); + + identity.setIdentityName(query.value(1).toString()); + identity.setRealName(query.value(2).toString()); + identity.setAwayNick(query.value(3).toString()); + identity.setAwayNickEnabled(!!query.value(4).toInt()); + identity.setAwayReason(query.value(5).toString()); + identity.setAwayReasonEnabled(!!query.value(6).toInt()); + identity.setAutoAwayEnabled(!!query.value(7).toInt()); + identity.setAutoAwayTime(query.value(8).toInt()); + identity.setAutoAwayReason(query.value(9).toString()); + identity.setAutoAwayReasonEnabled(!!query.value(10).toInt()); + identity.setDetachAwayEnabled(!!query.value(11).toInt()); + identity.setDetachAwayReason(query.value(12).toString()); + identity.setDetachAwayReasonEnabled(!!query.value(13).toInt()); + identity.setIdent(query.value(14).toString()); + identity.setKickReason(query.value(15).toString()); + identity.setPartReason(query.value(16).toString()); + identity.setQuitReason(query.value(17).toString()); #ifdef HAVE_SSL - identity.setSslCert(query.value(18).toByteArray()); - identity.setSslKey(query.value(19).toByteArray()); + identity.setSslCert(query.value(18).toByteArray()); + identity.setSslKey(query.value(19).toByteArray()); #endif - nickQuery.bindValue(":identityid", identity.id().toInt()); - QList nicks; - safeExec(nickQuery); - watchQuery(nickQuery); - while(nickQuery.next()) { - nicks << nickQuery.value(0).toString(); - } - identity.setNicks(nicks); - identities << identity; - } - db.commit(); - return identities; -} - -NetworkId PostgreSqlStorage::createNetwork(UserId user, const NetworkInfo &info) { - NetworkId networkId; - - QSqlDatabase db = logDb(); - if(!db.transaction()) { - qWarning() << "PostgreSqlStorage::createNetwork(): failed to begin transaction!"; - qWarning() << " -" << qPrintable(db.lastError().text()); - return false; - } - - QSqlQuery query(db); - query.prepare(queryString("insert_network")); - query.bindValue(":userid", user.toInt()); - bindNetworkInfo(query, info); - safeExec(query); - if(query.lastError().isValid()) { - watchQuery(query); - db.rollback(); - return NetworkId(); - } + nickQuery.bindValue(":identityid", identity.id().toInt()); + QList nicks; + safeExec(nickQuery); + watchQuery(nickQuery); + while (nickQuery.next()) { + nicks << nickQuery.value(0).toString(); + } + identity.setNicks(nicks); + identities << identity; + } + db.commit(); + return identities; +} - query.first(); - networkId = query.value(0).toInt(); - if(!networkId.isValid()) { - watchQuery(query); - db.rollback(); - return NetworkId(); - } - - QSqlQuery insertServersQuery(db); - insertServersQuery.prepare(queryString("insert_server")); - foreach(Network::Server server, info.serverList) { - insertServersQuery.bindValue(":userid", user.toInt()); - insertServersQuery.bindValue(":networkid", networkId.toInt()); - bindServerInfo(insertServersQuery, server); - safeExec(insertServersQuery); - if(!watchQuery(insertServersQuery)) { - db.rollback(); - return NetworkId(); - } - } - - if(!db.commit()) { - qWarning() << "PostgreSqlStorage::createNetwork(): committing data failed!"; - qWarning() << " -" << qPrintable(db.lastError().text()); - return NetworkId(); - } - return networkId; -} - -void PostgreSqlStorage::bindNetworkInfo(QSqlQuery &query, const NetworkInfo &info) { - query.bindValue(":networkname", info.networkName); - query.bindValue(":identityid", info.identity.isValid() ? info.identity.toInt() : QVariant()); - query.bindValue(":encodingcodec", QString(info.codecForEncoding)); - query.bindValue(":decodingcodec", QString(info.codecForDecoding)); - query.bindValue(":servercodec", QString(info.codecForServer)); - query.bindValue(":userandomserver", info.useRandomServer); - query.bindValue(":perform", info.perform.join("\n")); - query.bindValue(":useautoidentify", info.useAutoIdentify); - query.bindValue(":autoidentifyservice", info.autoIdentifyService); - query.bindValue(":autoidentifypassword", info.autoIdentifyPassword); - query.bindValue(":usesasl", info.useSasl); - query.bindValue(":saslaccount", info.saslAccount); - query.bindValue(":saslpassword", info.saslPassword); - query.bindValue(":useautoreconnect", info.useAutoReconnect); - query.bindValue(":autoreconnectinterval", info.autoReconnectInterval); - query.bindValue(":autoreconnectretries", info.autoReconnectRetries); - query.bindValue(":unlimitedconnectretries", info.unlimitedReconnectRetries); - query.bindValue(":rejoinchannels", info.rejoinChannels); - if(info.networkId.isValid()) - query.bindValue(":networkid", info.networkId.toInt()); -} - -void PostgreSqlStorage::bindServerInfo(QSqlQuery &query, const Network::Server &server) { - query.bindValue(":hostname", server.host); - query.bindValue(":port", server.port); - query.bindValue(":password", server.password); - query.bindValue(":ssl", server.useSsl); - query.bindValue(":sslversion", server.sslVersion); - query.bindValue(":useproxy", server.useProxy); - query.bindValue(":proxytype", server.proxyType); - query.bindValue(":proxyhost", server.proxyHost); - query.bindValue(":proxyport", server.proxyPort); - query.bindValue(":proxyuser", server.proxyUser); - query.bindValue(":proxypass", server.proxyPass); -} - -bool PostgreSqlStorage::updateNetwork(UserId user, const NetworkInfo &info) { - QSqlDatabase db = logDb(); - if(!db.transaction()) { - qWarning() << "PostgreSqlStorage::updateNetwork(): failed to begin transaction!"; - qWarning() << " -" << qPrintable(db.lastError().text()); - return false; - } - - QSqlQuery updateQuery(db); - updateQuery.prepare(queryString("update_network")); - updateQuery.bindValue(":userid", user.toInt()); - bindNetworkInfo(updateQuery, info); - safeExec(updateQuery); - if(!watchQuery(updateQuery)) { - db.rollback(); - return false; - } - if(updateQuery.numRowsAffected() != 1) { - // seems this is not our network... - db.rollback(); - return false; - } - - QSqlQuery dropServersQuery(db); - dropServersQuery.prepare("DELETE FROM ircserver WHERE networkid = :networkid"); - dropServersQuery.bindValue(":networkid", info.networkId.toInt()); - safeExec(dropServersQuery); - if(!watchQuery(dropServersQuery)) { - db.rollback(); - return false; - } - - QSqlQuery insertServersQuery(db); - insertServersQuery.prepare(queryString("insert_server")); - foreach(Network::Server server, info.serverList) { - insertServersQuery.bindValue(":userid", user.toInt()); - insertServersQuery.bindValue(":networkid", info.networkId.toInt()); - bindServerInfo(insertServersQuery, server); - safeExec(insertServersQuery); - if(!watchQuery(insertServersQuery)) { - db.rollback(); - return false; - } - } - - if(!db.commit()) { - qWarning() << "PostgreSqlStorage::updateNetwork(): committing data failed!"; - qWarning() << " -" << qPrintable(db.lastError().text()); - return false; - } - return true; -} - -bool PostgreSqlStorage::removeNetwork(UserId user, const NetworkId &networkId) { - QSqlDatabase db = logDb(); - if(!db.transaction()) { - qWarning() << "PostgreSqlStorage::removeNetwork(): cannot start transaction!"; - qWarning() << " -" << qPrintable(db.lastError().text()); - return false; - } - - QSqlQuery query(db); - query.prepare(queryString("delete_network")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":networkid", networkId.toInt()); - safeExec(query); - if(!watchQuery(query)) { - db.rollback(); - return false; - } - - db.commit(); - return true; -} - -QList PostgreSqlStorage::networks(UserId user) { - QList nets; - - QSqlDatabase db = logDb(); - if(!beginReadOnlyTransaction(db)) { - qWarning() << "PostgreSqlStorage::networks(): cannot start read only transaction!"; - qWarning() << " -" << qPrintable(db.lastError().text()); - return nets; - } +NetworkId PostgreSqlStorage::createNetwork(UserId user, const NetworkInfo &info) +{ + NetworkId networkId; + + QSqlDatabase db = logDb(); + if (!db.transaction()) { + qWarning() << "PostgreSqlStorage::createNetwork(): failed to begin transaction!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return false; + } + + QSqlQuery query(db); + query.prepare(queryString("insert_network")); + query.bindValue(":userid", user.toInt()); + bindNetworkInfo(query, info); + safeExec(query); + if (query.lastError().isValid()) { + watchQuery(query); + db.rollback(); + return NetworkId(); + } + + query.first(); + networkId = query.value(0).toInt(); + + if (!networkId.isValid()) { + watchQuery(query); + db.rollback(); + return NetworkId(); + } + + QSqlQuery insertServersQuery(db); + insertServersQuery.prepare(queryString("insert_server")); + foreach(Network::Server server, info.serverList) { + insertServersQuery.bindValue(":userid", user.toInt()); + insertServersQuery.bindValue(":networkid", networkId.toInt()); + bindServerInfo(insertServersQuery, server); + safeExec(insertServersQuery); + if (!watchQuery(insertServersQuery)) { + db.rollback(); + return NetworkId(); + } + } + + if (!db.commit()) { + qWarning() << "PostgreSqlStorage::createNetwork(): committing data failed!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return NetworkId(); + } + return networkId; +} + + +void PostgreSqlStorage::bindNetworkInfo(QSqlQuery &query, const NetworkInfo &info) +{ + query.bindValue(":networkname", info.networkName); + query.bindValue(":identityid", info.identity.isValid() ? info.identity.toInt() : QVariant()); + query.bindValue(":encodingcodec", QString(info.codecForEncoding)); + query.bindValue(":decodingcodec", QString(info.codecForDecoding)); + query.bindValue(":servercodec", QString(info.codecForServer)); + query.bindValue(":userandomserver", info.useRandomServer); + query.bindValue(":perform", info.perform.join("\n")); + query.bindValue(":useautoidentify", info.useAutoIdentify); + query.bindValue(":autoidentifyservice", info.autoIdentifyService); + query.bindValue(":autoidentifypassword", info.autoIdentifyPassword); + query.bindValue(":usesasl", info.useSasl); + query.bindValue(":saslaccount", info.saslAccount); + query.bindValue(":saslpassword", info.saslPassword); + query.bindValue(":useautoreconnect", info.useAutoReconnect); + query.bindValue(":autoreconnectinterval", info.autoReconnectInterval); + query.bindValue(":autoreconnectretries", info.autoReconnectRetries); + query.bindValue(":unlimitedconnectretries", info.unlimitedReconnectRetries); + query.bindValue(":rejoinchannels", info.rejoinChannels); + if (info.networkId.isValid()) + query.bindValue(":networkid", info.networkId.toInt()); +} + + +void PostgreSqlStorage::bindServerInfo(QSqlQuery &query, const Network::Server &server) +{ + query.bindValue(":hostname", server.host); + query.bindValue(":port", server.port); + query.bindValue(":password", server.password); + query.bindValue(":ssl", server.useSsl); + query.bindValue(":sslversion", server.sslVersion); + query.bindValue(":useproxy", server.useProxy); + query.bindValue(":proxytype", server.proxyType); + query.bindValue(":proxyhost", server.proxyHost); + query.bindValue(":proxyport", server.proxyPort); + query.bindValue(":proxyuser", server.proxyUser); + query.bindValue(":proxypass", server.proxyPass); +} + + +bool PostgreSqlStorage::updateNetwork(UserId user, const NetworkInfo &info) +{ + QSqlDatabase db = logDb(); + if (!db.transaction()) { + qWarning() << "PostgreSqlStorage::updateNetwork(): failed to begin transaction!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return false; + } + + QSqlQuery updateQuery(db); + updateQuery.prepare(queryString("update_network")); + updateQuery.bindValue(":userid", user.toInt()); + bindNetworkInfo(updateQuery, info); + safeExec(updateQuery); + if (!watchQuery(updateQuery)) { + db.rollback(); + return false; + } + if (updateQuery.numRowsAffected() != 1) { + // seems this is not our network... + db.rollback(); + return false; + } + + QSqlQuery dropServersQuery(db); + dropServersQuery.prepare("DELETE FROM ircserver WHERE networkid = :networkid"); + dropServersQuery.bindValue(":networkid", info.networkId.toInt()); + safeExec(dropServersQuery); + if (!watchQuery(dropServersQuery)) { + db.rollback(); + return false; + } + + QSqlQuery insertServersQuery(db); + insertServersQuery.prepare(queryString("insert_server")); + foreach(Network::Server server, info.serverList) { + insertServersQuery.bindValue(":userid", user.toInt()); + insertServersQuery.bindValue(":networkid", info.networkId.toInt()); + bindServerInfo(insertServersQuery, server); + safeExec(insertServersQuery); + if (!watchQuery(insertServersQuery)) { + db.rollback(); + return false; + } + } + + if (!db.commit()) { + qWarning() << "PostgreSqlStorage::updateNetwork(): committing data failed!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return false; + } + return true; +} + + +bool PostgreSqlStorage::removeNetwork(UserId user, const NetworkId &networkId) +{ + QSqlDatabase db = logDb(); + if (!db.transaction()) { + qWarning() << "PostgreSqlStorage::removeNetwork(): cannot start transaction!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return false; + } + + QSqlQuery query(db); + query.prepare(queryString("delete_network")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":networkid", networkId.toInt()); + safeExec(query); + if (!watchQuery(query)) { + db.rollback(); + return false; + } + + db.commit(); + return true; +} - QSqlQuery networksQuery(db); - networksQuery.prepare(queryString("select_networks_for_user")); - networksQuery.bindValue(":userid", user.toInt()); - QSqlQuery serversQuery(db); - serversQuery.prepare(queryString("select_servers_for_network")); +QList PostgreSqlStorage::networks(UserId user) +{ + QList nets; + + QSqlDatabase db = logDb(); + if (!beginReadOnlyTransaction(db)) { + qWarning() << "PostgreSqlStorage::networks(): cannot start read only transaction!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return nets; + } + + QSqlQuery networksQuery(db); + networksQuery.prepare(queryString("select_networks_for_user")); + networksQuery.bindValue(":userid", user.toInt()); + + QSqlQuery serversQuery(db); + serversQuery.prepare(queryString("select_servers_for_network")); + + safeExec(networksQuery); + if (!watchQuery(networksQuery)) { + db.rollback(); + return nets; + } - safeExec(networksQuery); - if(!watchQuery(networksQuery)) { - db.rollback(); + while (networksQuery.next()) { + NetworkInfo net; + net.networkId = networksQuery.value(0).toInt(); + net.networkName = networksQuery.value(1).toString(); + net.identity = networksQuery.value(2).toInt(); + net.codecForServer = networksQuery.value(3).toString().toAscii(); + net.codecForEncoding = networksQuery.value(4).toString().toAscii(); + net.codecForDecoding = networksQuery.value(5).toString().toAscii(); + net.useRandomServer = networksQuery.value(6).toBool(); + net.perform = networksQuery.value(7).toString().split("\n"); + net.useAutoIdentify = networksQuery.value(8).toBool(); + net.autoIdentifyService = networksQuery.value(9).toString(); + net.autoIdentifyPassword = networksQuery.value(10).toString(); + net.useAutoReconnect = networksQuery.value(11).toBool(); + net.autoReconnectInterval = networksQuery.value(12).toUInt(); + net.autoReconnectRetries = networksQuery.value(13).toInt(); + net.unlimitedReconnectRetries = networksQuery.value(14).toBool(); + net.rejoinChannels = networksQuery.value(15).toBool(); + net.useSasl = networksQuery.value(16).toBool(); + net.saslAccount = networksQuery.value(17).toString(); + net.saslPassword = networksQuery.value(18).toString(); + + serversQuery.bindValue(":networkid", net.networkId.toInt()); + safeExec(serversQuery); + if (!watchQuery(serversQuery)) { + db.rollback(); + return nets; + } + + Network::ServerList servers; + while (serversQuery.next()) { + Network::Server server; + server.host = serversQuery.value(0).toString(); + server.port = serversQuery.value(1).toUInt(); + server.password = serversQuery.value(2).toString(); + server.useSsl = serversQuery.value(3).toBool(); + server.sslVersion = serversQuery.value(4).toInt(); + server.useProxy = serversQuery.value(5).toBool(); + server.proxyType = serversQuery.value(6).toInt(); + server.proxyHost = serversQuery.value(7).toString(); + server.proxyPort = serversQuery.value(8).toUInt(); + server.proxyUser = serversQuery.value(9).toString(); + server.proxyPass = serversQuery.value(10).toString(); + servers << server; + } + net.serverList = servers; + nets << net; + } + db.commit(); return nets; - } - - while(networksQuery.next()) { - NetworkInfo net; - net.networkId = networksQuery.value(0).toInt(); - net.networkName = networksQuery.value(1).toString(); - net.identity = networksQuery.value(2).toInt(); - net.codecForServer = networksQuery.value(3).toString().toAscii(); - net.codecForEncoding = networksQuery.value(4).toString().toAscii(); - net.codecForDecoding = networksQuery.value(5).toString().toAscii(); - net.useRandomServer = networksQuery.value(6).toBool(); - net.perform = networksQuery.value(7).toString().split("\n"); - net.useAutoIdentify = networksQuery.value(8).toBool(); - net.autoIdentifyService = networksQuery.value(9).toString(); - net.autoIdentifyPassword = networksQuery.value(10).toString(); - net.useAutoReconnect = networksQuery.value(11).toBool(); - net.autoReconnectInterval = networksQuery.value(12).toUInt(); - net.autoReconnectRetries = networksQuery.value(13).toInt(); - net.unlimitedReconnectRetries = networksQuery.value(14).toBool(); - net.rejoinChannels = networksQuery.value(15).toBool(); - net.useSasl = networksQuery.value(16).toBool(); - net.saslAccount = networksQuery.value(17).toString(); - net.saslPassword = networksQuery.value(18).toString(); - - serversQuery.bindValue(":networkid", net.networkId.toInt()); - safeExec(serversQuery); - if(!watchQuery(serversQuery)) { - db.rollback(); - return nets; - } - - Network::ServerList servers; - while(serversQuery.next()) { - Network::Server server; - server.host = serversQuery.value(0).toString(); - server.port = serversQuery.value(1).toUInt(); - server.password = serversQuery.value(2).toString(); - server.useSsl = serversQuery.value(3).toBool(); - server.sslVersion = serversQuery.value(4).toInt(); - server.useProxy = serversQuery.value(5).toBool(); - server.proxyType = serversQuery.value(6).toInt(); - server.proxyHost = serversQuery.value(7).toString(); - server.proxyPort = serversQuery.value(8).toUInt(); - server.proxyUser = serversQuery.value(9).toString(); - server.proxyPass = serversQuery.value(10).toString(); - servers << server; - } - net.serverList = servers; - nets << net; - } - db.commit(); - return nets; -} - -QList PostgreSqlStorage::connectedNetworks(UserId user) { - QList connectedNets; - - QSqlDatabase db = logDb(); - if(!beginReadOnlyTransaction(db)) { - qWarning() << "PostgreSqlStorage::connectedNetworks(): cannot start read only transaction!"; - qWarning() << " -" << qPrintable(db.lastError().text()); - return connectedNets; - } +} + + +QList PostgreSqlStorage::connectedNetworks(UserId user) +{ + QList connectedNets; - QSqlQuery query(db); - query.prepare(queryString("select_connected_networks")); - query.bindValue(":userid", user.toInt()); - safeExec(query); - watchQuery(query); + QSqlDatabase db = logDb(); + if (!beginReadOnlyTransaction(db)) { + qWarning() << "PostgreSqlStorage::connectedNetworks(): cannot start read only transaction!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return connectedNets; + } + + QSqlQuery query(db); + query.prepare(queryString("select_connected_networks")); + query.bindValue(":userid", user.toInt()); + safeExec(query); + watchQuery(query); - while(query.next()) { - connectedNets << query.value(0).toInt(); - } + while (query.next()) { + connectedNets << query.value(0).toInt(); + } - db.commit(); - return connectedNets; + db.commit(); + return connectedNets; } -void PostgreSqlStorage::setNetworkConnected(UserId user, const NetworkId &networkId, bool isConnected) { - QSqlQuery query(logDb()); - query.prepare(queryString("update_network_connected")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":networkid", networkId.toInt()); - query.bindValue(":connected", isConnected); - safeExec(query); - watchQuery(query); + +void PostgreSqlStorage::setNetworkConnected(UserId user, const NetworkId &networkId, bool isConnected) +{ + QSqlQuery query(logDb()); + query.prepare(queryString("update_network_connected")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":networkid", networkId.toInt()); + query.bindValue(":connected", isConnected); + safeExec(query); + watchQuery(query); } -QHash PostgreSqlStorage::persistentChannels(UserId user, const NetworkId &networkId) { - QHash persistentChans; - QSqlDatabase db = logDb(); - if(!beginReadOnlyTransaction(db)) { - qWarning() << "PostgreSqlStorage::persistentChannels(): cannot start read only transaction!"; - qWarning() << " -" << qPrintable(db.lastError().text()); +QHash PostgreSqlStorage::persistentChannels(UserId user, const NetworkId &networkId) +{ + QHash persistentChans; + + QSqlDatabase db = logDb(); + if (!beginReadOnlyTransaction(db)) { + qWarning() << "PostgreSqlStorage::persistentChannels(): cannot start read only transaction!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return persistentChans; + } + + QSqlQuery query(db); + query.prepare(queryString("select_persistent_channels")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":networkid", networkId.toInt()); + safeExec(query); + watchQuery(query); + + while (query.next()) { + persistentChans[query.value(0).toString()] = query.value(1).toString(); + } + + db.commit(); return persistentChans; - } - - QSqlQuery query(db); - query.prepare(queryString("select_persistent_channels")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":networkid", networkId.toInt()); - safeExec(query); - watchQuery(query); - - while(query.next()) { - persistentChans[query.value(0).toString()] = query.value(1).toString(); - } - - db.commit(); - return persistentChans; -} - -void PostgreSqlStorage::setChannelPersistent(UserId user, const NetworkId &networkId, const QString &channel, bool isJoined) { - QSqlQuery query(logDb()); - query.prepare(queryString("update_buffer_persistent_channel")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":networkId", networkId.toInt()); - query.bindValue(":buffercname", channel.toLower()); - query.bindValue(":joined", isJoined); - safeExec(query); - watchQuery(query); -} - -void PostgreSqlStorage::setPersistentChannelKey(UserId user, const NetworkId &networkId, const QString &channel, const QString &key) { - QSqlQuery query(logDb()); - query.prepare(queryString("update_buffer_set_channel_key")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":networkId", networkId.toInt()); - query.bindValue(":buffercname", channel.toLower()); - query.bindValue(":key", key); - safeExec(query); - watchQuery(query); -} - -QString PostgreSqlStorage::awayMessage(UserId user, NetworkId networkId) { - QSqlQuery query(logDb()); - query.prepare(queryString("select_network_awaymsg")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":networkid", networkId.toInt()); - safeExec(query); - watchQuery(query); - QString awayMsg; - if(query.first()) - awayMsg = query.value(0).toString(); - return awayMsg; -} - -void PostgreSqlStorage::setAwayMessage(UserId user, NetworkId networkId, const QString &awayMsg) { - QSqlQuery query(logDb()); - query.prepare(queryString("update_network_set_awaymsg")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":networkid", networkId.toInt()); - query.bindValue(":awaymsg", awayMsg); - safeExec(query); - watchQuery(query); -} - -QString PostgreSqlStorage::userModes(UserId user, NetworkId networkId) { - QSqlQuery query(logDb()); - query.prepare(queryString("select_network_usermode")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":networkid", networkId.toInt()); - safeExec(query); - watchQuery(query); - QString modes; - if(query.first()) - modes = query.value(0).toString(); - return modes; -} - -void PostgreSqlStorage::setUserModes(UserId user, NetworkId networkId, const QString &userModes) { - QSqlQuery query(logDb()); - query.prepare(queryString("update_network_set_usermode")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":networkid", networkId.toInt()); - query.bindValue(":usermode", userModes); - safeExec(query); - watchQuery(query); -} - -BufferInfo PostgreSqlStorage::bufferInfo(UserId user, const NetworkId &networkId, BufferInfo::Type type, const QString &buffer, bool create) { - QSqlDatabase db = logDb(); - if(!db.transaction()) { - qWarning() << "PostgreSqlStorage::bufferInfo(): cannot start read only transaction!"; - qWarning() << " -" << qPrintable(db.lastError().text()); - return BufferInfo(); - } - - QSqlQuery query(db); - query.prepare(queryString("select_bufferByName")); - query.bindValue(":networkid", networkId.toInt()); - query.bindValue(":userid", user.toInt()); - query.bindValue(":buffercname", buffer.toLower()); - safeExec(query); - - if(query.first()) { - BufferInfo bufferInfo = BufferInfo(query.value(0).toInt(), networkId, (BufferInfo::Type)query.value(1).toInt(), 0, buffer); - if(query.next()) { - qCritical() << "PostgreSqlStorage::bufferInfo(): received more then one Buffer!"; - qCritical() << " Query:" << query.lastQuery(); - qCritical() << " bound Values:"; - QList list = query.boundValues().values(); - for (int i = 0; i < list.size(); ++i) - qCritical() << i << ":" << list.at(i).toString().toAscii().data(); - Q_ASSERT(false); +} + + +void PostgreSqlStorage::setChannelPersistent(UserId user, const NetworkId &networkId, const QString &channel, bool isJoined) +{ + QSqlQuery query(logDb()); + query.prepare(queryString("update_buffer_persistent_channel")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":networkId", networkId.toInt()); + query.bindValue(":buffercname", channel.toLower()); + query.bindValue(":joined", isJoined); + safeExec(query); + watchQuery(query); +} + + +void PostgreSqlStorage::setPersistentChannelKey(UserId user, const NetworkId &networkId, const QString &channel, const QString &key) +{ + QSqlQuery query(logDb()); + query.prepare(queryString("update_buffer_set_channel_key")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":networkId", networkId.toInt()); + query.bindValue(":buffercname", channel.toLower()); + query.bindValue(":key", key); + safeExec(query); + watchQuery(query); +} + + +QString PostgreSqlStorage::awayMessage(UserId user, NetworkId networkId) +{ + QSqlQuery query(logDb()); + query.prepare(queryString("select_network_awaymsg")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":networkid", networkId.toInt()); + safeExec(query); + watchQuery(query); + QString awayMsg; + if (query.first()) + awayMsg = query.value(0).toString(); + return awayMsg; +} + + +void PostgreSqlStorage::setAwayMessage(UserId user, NetworkId networkId, const QString &awayMsg) +{ + QSqlQuery query(logDb()); + query.prepare(queryString("update_network_set_awaymsg")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":networkid", networkId.toInt()); + query.bindValue(":awaymsg", awayMsg); + safeExec(query); + watchQuery(query); +} + + +QString PostgreSqlStorage::userModes(UserId user, NetworkId networkId) +{ + QSqlQuery query(logDb()); + query.prepare(queryString("select_network_usermode")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":networkid", networkId.toInt()); + safeExec(query); + watchQuery(query); + QString modes; + if (query.first()) + modes = query.value(0).toString(); + return modes; +} + + +void PostgreSqlStorage::setUserModes(UserId user, NetworkId networkId, const QString &userModes) +{ + QSqlQuery query(logDb()); + query.prepare(queryString("update_network_set_usermode")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":networkid", networkId.toInt()); + query.bindValue(":usermode", userModes); + safeExec(query); + watchQuery(query); +} + + +BufferInfo PostgreSqlStorage::bufferInfo(UserId user, const NetworkId &networkId, BufferInfo::Type type, const QString &buffer, bool create) +{ + QSqlDatabase db = logDb(); + if (!db.transaction()) { + qWarning() << "PostgreSqlStorage::bufferInfo(): cannot start read only transaction!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return BufferInfo(); + } + + QSqlQuery query(db); + query.prepare(queryString("select_bufferByName")); + query.bindValue(":networkid", networkId.toInt()); + query.bindValue(":userid", user.toInt()); + query.bindValue(":buffercname", buffer.toLower()); + safeExec(query); + + if (query.first()) { + BufferInfo bufferInfo = BufferInfo(query.value(0).toInt(), networkId, (BufferInfo::Type)query.value(1).toInt(), 0, buffer); + if (query.next()) { + qCritical() << "PostgreSqlStorage::bufferInfo(): received more then one Buffer!"; + qCritical() << " Query:" << query.lastQuery(); + qCritical() << " bound Values:"; + QList list = query.boundValues().values(); + for (int i = 0; i < list.size(); ++i) + qCritical() << i << ":" << list.at(i).toString().toAscii().data(); + Q_ASSERT(false); + } + db.commit(); + return bufferInfo; + } + + if (!create) { + db.rollback(); + return BufferInfo(); + } + + QSqlQuery createQuery(db); + createQuery.prepare(queryString("insert_buffer")); + createQuery.bindValue(":userid", user.toInt()); + createQuery.bindValue(":networkid", networkId.toInt()); + createQuery.bindValue(":buffertype", (int)type); + createQuery.bindValue(":buffername", buffer); + createQuery.bindValue(":buffercname", buffer.toLower()); + createQuery.bindValue(":joined", type & BufferInfo::ChannelBuffer ? true : false); + + safeExec(createQuery); + + if (createQuery.lastError().isValid()) { + qWarning() << "PostgreSqlStorage::bufferInfo(): unable to create buffer"; + watchQuery(createQuery); + db.rollback(); + return BufferInfo(); } + + createQuery.first(); + + BufferInfo bufferInfo = BufferInfo(createQuery.value(0).toInt(), networkId, type, 0, buffer); db.commit(); return bufferInfo; - } +} + - if(!create) { - db.rollback(); - return BufferInfo(); - } +BufferInfo PostgreSqlStorage::getBufferInfo(UserId user, const BufferId &bufferId) +{ + QSqlQuery query(logDb()); + query.prepare(queryString("select_buffer_by_id")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":bufferid", bufferId.toInt()); + safeExec(query); + if (!watchQuery(query)) + return BufferInfo(); + + if (!query.first()) + return BufferInfo(); - QSqlQuery createQuery(db); - createQuery.prepare(queryString("insert_buffer")); - createQuery.bindValue(":userid", user.toInt()); - createQuery.bindValue(":networkid", networkId.toInt()); - createQuery.bindValue(":buffertype", (int)type); - createQuery.bindValue(":buffername", buffer); - createQuery.bindValue(":buffercname", buffer.toLower()); - createQuery.bindValue(":joined", type & BufferInfo::ChannelBuffer ? true : false); + BufferInfo bufferInfo(query.value(0).toInt(), query.value(1).toInt(), (BufferInfo::Type)query.value(2).toInt(), 0, query.value(4).toString()); + Q_ASSERT(!query.next()); - safeExec(createQuery); + return bufferInfo; +} + + +QList PostgreSqlStorage::requestBuffers(UserId user) +{ + QList bufferlist; - if(createQuery.lastError().isValid()) { - qWarning() << "PostgreSqlStorage::bufferInfo(): unable to create buffer"; - watchQuery(createQuery); - db.rollback(); - return BufferInfo(); - } + QSqlDatabase db = logDb(); + if (!beginReadOnlyTransaction(db)) { + qWarning() << "PostgreSqlStorage::requestBuffers(): cannot start read only transaction!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return bufferlist; + } - createQuery.first(); + QSqlQuery query(db); + query.prepare(queryString("select_buffers")); + query.bindValue(":userid", user.toInt()); - BufferInfo bufferInfo = BufferInfo(createQuery.value(0).toInt(), networkId, type, 0, buffer); - db.commit(); - return bufferInfo; + safeExec(query); + watchQuery(query); + while (query.next()) { + bufferlist << BufferInfo(query.value(0).toInt(), query.value(1).toInt(), (BufferInfo::Type)query.value(2).toInt(), query.value(3).toInt(), query.value(4).toString()); + } + db.commit(); + return bufferlist; } -BufferInfo PostgreSqlStorage::getBufferInfo(UserId user, const BufferId &bufferId) { - QSqlQuery query(logDb()); - query.prepare(queryString("select_buffer_by_id")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":bufferid", bufferId.toInt()); - safeExec(query); - if(!watchQuery(query)) - return BufferInfo(); - if(!query.first()) - return BufferInfo(); +QList PostgreSqlStorage::requestBufferIdsForNetwork(UserId user, NetworkId networkId) +{ + QList bufferList; + + QSqlDatabase db = logDb(); + if (!beginReadOnlyTransaction(db)) { + qWarning() << "PostgreSqlStorage::requestBufferIdsForNetwork(): cannot start read only transaction!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return bufferList; + } - BufferInfo bufferInfo(query.value(0).toInt(), query.value(1).toInt(), (BufferInfo::Type)query.value(2).toInt(), 0, query.value(4).toString()); - Q_ASSERT(!query.next()); + QSqlQuery query(db); + query.prepare(queryString("select_buffers_for_network")); + query.bindValue(":networkid", networkId.toInt()); + query.bindValue(":userid", user.toInt()); - return bufferInfo; + safeExec(query); + watchQuery(query); + while (query.next()) { + bufferList << BufferId(query.value(0).toInt()); + } + db.commit(); + return bufferList; } -QList PostgreSqlStorage::requestBuffers(UserId user) { - QList bufferlist; - QSqlDatabase db = logDb(); - if(!beginReadOnlyTransaction(db)) { - qWarning() << "PostgreSqlStorage::requestBuffers(): cannot start read only transaction!"; - qWarning() << " -" << qPrintable(db.lastError().text()); - return bufferlist; - } +bool PostgreSqlStorage::removeBuffer(const UserId &user, const BufferId &bufferId) +{ + QSqlDatabase db = logDb(); + if (!db.transaction()) { + qWarning() << "PostgreSqlStorage::removeBuffer(): cannot start transaction!"; + return false; + } - QSqlQuery query(db); - query.prepare(queryString("select_buffers")); - query.bindValue(":userid", user.toInt()); + QSqlQuery query(db); + query.prepare(queryString("delete_buffer_for_bufferid")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":bufferid", bufferId.toInt()); + safeExec(query); + if (!watchQuery(query)) { + db.rollback(); + return false; + } - safeExec(query); - watchQuery(query); - while(query.next()) { - bufferlist << BufferInfo(query.value(0).toInt(), query.value(1).toInt(), (BufferInfo::Type)query.value(2).toInt(), query.value(3).toInt(), query.value(4).toString()); - } - db.commit(); - return bufferlist; + int numRows = query.numRowsAffected(); + switch (numRows) { + case 0: + db.commit(); + return false; + case 1: + db.commit(); + return true; + default: + // there was more then one buffer deleted... + qWarning() << "PostgreSqlStorage::removeBuffer(): Userid" << user << "BufferId" << "caused deletion of" << numRows << "Buffers! Rolling back transaction..."; + db.rollback(); + return false; + } } -QList PostgreSqlStorage::requestBufferIdsForNetwork(UserId user, NetworkId networkId) { - QList bufferList; - QSqlDatabase db = logDb(); - if(!beginReadOnlyTransaction(db)) { - qWarning() << "PostgreSqlStorage::requestBufferIdsForNetwork(): cannot start read only transaction!"; - qWarning() << " -" << qPrintable(db.lastError().text()); - return bufferList; - } - - QSqlQuery query(db); - query.prepare(queryString("select_buffers_for_network")); - query.bindValue(":networkid", networkId.toInt()); - query.bindValue(":userid", user.toInt()); - - safeExec(query); - watchQuery(query); - while(query.next()) { - bufferList << BufferId(query.value(0).toInt()); - } - db.commit(); - return bufferList; -} - -bool PostgreSqlStorage::removeBuffer(const UserId &user, const BufferId &bufferId) { - QSqlDatabase db = logDb(); - if(!db.transaction()) { - qWarning() << "PostgreSqlStorage::removeBuffer(): cannot start transaction!"; - return false; - } - - QSqlQuery query(db); - query.prepare(queryString("delete_buffer_for_bufferid")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":bufferid", bufferId.toInt()); - safeExec(query); - if(!watchQuery(query)) { - db.rollback(); - return false; - } - - int numRows = query.numRowsAffected(); - switch(numRows) { - case 0: - db.commit(); - return false; - case 1: +bool PostgreSqlStorage::renameBuffer(const UserId &user, const BufferId &bufferId, const QString &newName) +{ + QSqlDatabase db = logDb(); + if (!db.transaction()) { + qWarning() << "PostgreSqlStorage::renameBuffer(): cannot start transaction!"; + return false; + } + + QSqlQuery query(db); + query.prepare(queryString("update_buffer_name")); + query.bindValue(":buffername", newName); + query.bindValue(":buffercname", newName.toLower()); + query.bindValue(":userid", user.toInt()); + query.bindValue(":bufferid", bufferId.toInt()); + safeExec(query); + if (query.lastError().isValid()) { + watchQuery(query); + db.rollback(); + return false; + } + + int numRows = query.numRowsAffected(); + switch (numRows) { + case 0: + db.commit(); + return false; + case 1: + db.commit(); + return true; + default: + // there was more then one buffer deleted... + qWarning() << "PostgreSqlStorage::renameBuffer(): Userid" << user << "BufferId" << "affected" << numRows << "Buffers! Rolling back transaction..."; + db.rollback(); + return false; + } +} + + +bool PostgreSqlStorage::mergeBuffersPermanently(const UserId &user, const BufferId &bufferId1, const BufferId &bufferId2) +{ + QSqlDatabase db = logDb(); + if (!db.transaction()) { + qWarning() << "PostgreSqlStorage::mergeBuffersPermanently(): cannot start transaction!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return false; + } + + QSqlQuery checkQuery(db); + checkQuery.prepare("SELECT count(*) FROM buffer " + "WHERE userid = :userid AND bufferid IN (:buffer1, :buffer2)"); + checkQuery.bindValue(":userid", user.toInt()); + checkQuery.bindValue(":buffer1", bufferId1.toInt()); + checkQuery.bindValue(":buffer2", bufferId2.toInt()); + safeExec(checkQuery); + if (!watchQuery(checkQuery)) { + db.rollback(); + return false; + } + checkQuery.first(); + if (checkQuery.value(0).toInt() != 2) { + db.rollback(); + return false; + } + + QSqlQuery query(db); + query.prepare(queryString("update_backlog_bufferid")); + query.bindValue(":oldbufferid", bufferId2.toInt()); + query.bindValue(":newbufferid", bufferId1.toInt()); + safeExec(query); + if (!watchQuery(query)) { + db.rollback(); + return false; + } + + QSqlQuery delBufferQuery(logDb()); + delBufferQuery.prepare(queryString("delete_buffer_for_bufferid")); + delBufferQuery.bindValue(":userid", user.toInt()); + delBufferQuery.bindValue(":bufferid", bufferId2.toInt()); + safeExec(delBufferQuery); + if (!watchQuery(delBufferQuery)) { + db.rollback(); + return false; + } + db.commit(); return true; - default: - // there was more then one buffer deleted... - qWarning() << "PostgreSqlStorage::removeBuffer(): Userid" << user << "BufferId" << "caused deletion of" << numRows << "Buffers! Rolling back transaction..."; - db.rollback(); - return false; - } -} - -bool PostgreSqlStorage::renameBuffer(const UserId &user, const BufferId &bufferId, const QString &newName) { - QSqlDatabase db = logDb(); - if(!db.transaction()) { - qWarning() << "PostgreSqlStorage::renameBuffer(): cannot start transaction!"; - return false; - } - - QSqlQuery query(db); - query.prepare(queryString("update_buffer_name")); - query.bindValue(":buffername", newName); - query.bindValue(":buffercname", newName.toLower()); - query.bindValue(":userid", user.toInt()); - query.bindValue(":bufferid", bufferId.toInt()); - safeExec(query); - if(query.lastError().isValid()) { +} + + +void PostgreSqlStorage::setBufferLastSeenMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) +{ + QSqlQuery query(logDb()); + query.prepare(queryString("update_buffer_lastseen")); + + query.bindValue(":userid", user.toInt()); + query.bindValue(":bufferid", bufferId.toInt()); + query.bindValue(":lastseenmsgid", msgId.toInt()); + safeExec(query); watchQuery(query); - db.rollback(); - return false; - } +} + + +QHash PostgreSqlStorage::bufferLastSeenMsgIds(UserId user) +{ + QHash lastSeenHash; + + QSqlDatabase db = logDb(); + if (!beginReadOnlyTransaction(db)) { + qWarning() << "PostgreSqlStorage::bufferLastSeenMsgIds(): cannot start read only transaction!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return lastSeenHash; + } + + QSqlQuery query(db); + query.prepare(queryString("select_buffer_lastseen_messages")); + query.bindValue(":userid", user.toInt()); + safeExec(query); + if (!watchQuery(query)) { + db.rollback(); + return lastSeenHash; + } + + while (query.next()) { + lastSeenHash[query.value(0).toInt()] = query.value(1).toInt(); + } - int numRows = query.numRowsAffected(); - switch(numRows) { - case 0: - db.commit(); - return false; - case 1: db.commit(); - return true; - default: - // there was more then one buffer deleted... - qWarning() << "PostgreSqlStorage::renameBuffer(): Userid" << user << "BufferId" << "affected" << numRows << "Buffers! Rolling back transaction..."; - db.rollback(); - return false; - } -} - -bool PostgreSqlStorage::mergeBuffersPermanently(const UserId &user, const BufferId &bufferId1, const BufferId &bufferId2) { - QSqlDatabase db = logDb(); - if(!db.transaction()) { - qWarning() << "PostgreSqlStorage::mergeBuffersPermanently(): cannot start transaction!"; - qWarning() << " -" << qPrintable(db.lastError().text()); - return false; - } - - QSqlQuery checkQuery(db); - checkQuery.prepare("SELECT count(*) FROM buffer " - "WHERE userid = :userid AND bufferid IN (:buffer1, :buffer2)"); - checkQuery.bindValue(":userid", user.toInt()); - checkQuery.bindValue(":buffer1", bufferId1.toInt()); - checkQuery.bindValue(":buffer2", bufferId2.toInt()); - safeExec(checkQuery); - if(!watchQuery(checkQuery)) { - db.rollback(); - return false; - } - checkQuery.first(); - if(checkQuery.value(0).toInt() != 2) { - db.rollback(); - return false; - } - - QSqlQuery query(db); - query.prepare(queryString("update_backlog_bufferid")); - query.bindValue(":oldbufferid", bufferId2.toInt()); - query.bindValue(":newbufferid", bufferId1.toInt()); - safeExec(query); - if(!watchQuery(query)) { - db.rollback(); - return false; - } - - QSqlQuery delBufferQuery(logDb()); - delBufferQuery.prepare(queryString("delete_buffer_for_bufferid")); - delBufferQuery.bindValue(":userid", user.toInt()); - delBufferQuery.bindValue(":bufferid", bufferId2.toInt()); - safeExec(delBufferQuery); - if(!watchQuery(delBufferQuery)) { - db.rollback(); - return false; - } - - db.commit(); - return true; -} - -void PostgreSqlStorage::setBufferLastSeenMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) { - QSqlQuery query(logDb()); - query.prepare(queryString("update_buffer_lastseen")); - - query.bindValue(":userid", user.toInt()); - query.bindValue(":bufferid", bufferId.toInt()); - query.bindValue(":lastseenmsgid", msgId.toInt()); - safeExec(query); - watchQuery(query); -} - -QHash PostgreSqlStorage::bufferLastSeenMsgIds(UserId user) { - QHash lastSeenHash; - - QSqlDatabase db = logDb(); - if(!beginReadOnlyTransaction(db)) { - qWarning() << "PostgreSqlStorage::bufferLastSeenMsgIds(): cannot start read only transaction!"; - qWarning() << " -" << qPrintable(db.lastError().text()); return lastSeenHash; - } - - QSqlQuery query(db); - query.prepare(queryString("select_buffer_lastseen_messages")); - query.bindValue(":userid", user.toInt()); - safeExec(query); - if(!watchQuery(query)) { - db.rollback(); - return lastSeenHash; - } +} - while(query.next()) { - lastSeenHash[query.value(0).toInt()] = query.value(1).toInt(); - } - db.commit(); - return lastSeenHash; +void PostgreSqlStorage::setBufferMarkerLineMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) +{ + QSqlQuery query(logDb()); + query.prepare(queryString("update_buffer_markerlinemsgid")); + + query.bindValue(":userid", user.toInt()); + query.bindValue(":bufferid", bufferId.toInt()); + query.bindValue(":markerlinemsgid", msgId.toInt()); + safeExec(query); + watchQuery(query); } -void PostgreSqlStorage::setBufferMarkerLineMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) { - QSqlQuery query(logDb()); - query.prepare(queryString("update_buffer_markerlinemsgid")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":bufferid", bufferId.toInt()); - query.bindValue(":markerlinemsgid", msgId.toInt()); - safeExec(query); - watchQuery(query); -} +QHash PostgreSqlStorage::bufferMarkerLineMsgIds(UserId user) +{ + QHash markerLineHash; -QHash PostgreSqlStorage::bufferMarkerLineMsgIds(UserId user) { - QHash markerLineHash; + QSqlDatabase db = logDb(); + if (!beginReadOnlyTransaction(db)) { + qWarning() << "PostgreSqlStorage::bufferMarkerLineMsgIds(): cannot start read only transaction!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return markerLineHash; + } - QSqlDatabase db = logDb(); - if(!beginReadOnlyTransaction(db)) { - qWarning() << "PostgreSqlStorage::bufferMarkerLineMsgIds(): cannot start read only transaction!"; - qWarning() << " -" << qPrintable(db.lastError().text()); - return markerLineHash; - } - - QSqlQuery query(db); - query.prepare(queryString("select_buffer_markerlinemsgids")); - query.bindValue(":userid", user.toInt()); - safeExec(query); - if(!watchQuery(query)) { - db.rollback(); + QSqlQuery query(db); + query.prepare(queryString("select_buffer_markerlinemsgids")); + query.bindValue(":userid", user.toInt()); + safeExec(query); + if (!watchQuery(query)) { + db.rollback(); + return markerLineHash; + } + + while (query.next()) { + markerLineHash[query.value(0).toInt()] = query.value(1).toInt(); + } + + db.commit(); return markerLineHash; - } - - while(query.next()) { - markerLineHash[query.value(0).toInt()] = query.value(1).toInt(); - } - - db.commit(); - return markerLineHash; -} - -bool PostgreSqlStorage::logMessage(Message &msg) { - QSqlDatabase db = logDb(); - if(!db.transaction()) { - qWarning() << "PostgreSqlStorage::logMessage(): cannot start transaction!"; - qWarning() << " -" << qPrintable(db.lastError().text()); - return false; - } - - QSqlQuery getSenderIdQuery = executePreparedQuery("select_senderid", msg.sender(), db); - int senderId; - if(getSenderIdQuery.first()) { - senderId = getSenderIdQuery.value(0).toInt(); - } else { - // it's possible that the sender was already added by another thread - // since the insert might fail we're setting a savepoint - savePoint("sender_sp1", db); - QSqlQuery addSenderQuery = executePreparedQuery("insert_sender", msg.sender(), db); - - if(addSenderQuery.lastError().isValid()) { - rollbackSavePoint("sender_sp1", db); - getSenderIdQuery = db.exec(getSenderIdQuery.lastQuery()); - getSenderIdQuery.first(); - senderId = getSenderIdQuery.value(0).toInt(); - } else { - releaseSavePoint("sender_sp1", db); - addSenderQuery.first(); - senderId = addSenderQuery.value(0).toInt(); - } - } - - QVariantList params; - params << msg.timestamp() - << msg.bufferInfo().bufferId().toInt() - << msg.type() - << (int)msg.flags() - << senderId - << msg.contents(); - QSqlQuery logMessageQuery = executePreparedQuery("insert_message", params, db); - - if(!watchQuery(logMessageQuery)) { - db.rollback(); - return false; - } - - logMessageQuery.first(); - MsgId msgId = logMessageQuery.value(0).toInt(); - db.commit(); - if(msgId.isValid()) { - msg.setMsgId(msgId); - return true; - } else { - return false; - } -} - -bool PostgreSqlStorage::logMessages(MessageList &msgs) { - QSqlDatabase db = logDb(); - if(!db.transaction()) { - qWarning() << "PostgreSqlStorage::logMessage(): cannot start transaction!"; - qWarning() << " -" << qPrintable(db.lastError().text()); - return false; - } - - QList senderIdList; - QHash senderIds; - QSqlQuery addSenderQuery; - QSqlQuery selectSenderQuery;; - for(int i = 0; i < msgs.count(); i++) { - const QString &sender = msgs.at(i).sender(); - if(senderIds.contains(sender)) { - senderIdList << senderIds[sender]; - continue; - } - - selectSenderQuery = executePreparedQuery("select_senderid", sender, db); - if(selectSenderQuery.first()) { - senderIdList << selectSenderQuery.value(0).toInt(); - senderIds[sender] = selectSenderQuery.value(0).toInt(); - } else { - savePoint("sender_sp", db); - addSenderQuery= executePreparedQuery("insert_sender", sender, db); - if(addSenderQuery.lastError().isValid()) { - // seems it was inserted meanwhile... by a different thread - rollbackSavePoint("sender_sp", db); - selectSenderQuery = db.exec(selectSenderQuery.lastQuery()); - selectSenderQuery.first(); - senderIdList << selectSenderQuery.value(0).toInt(); - senderIds[sender] = selectSenderQuery.value(0).toInt(); - } else { - releaseSavePoint("sender_sp", db); - addSenderQuery.first(); - senderIdList << addSenderQuery.value(0).toInt(); - senderIds[sender] = addSenderQuery.value(0).toInt(); - } - } - } - - // yes we loop twice over the same list. This avoids alternating queries. - bool error = false; - for(int i = 0; i < msgs.count(); i++) { - Message &msg = msgs[i]; +} + + +bool PostgreSqlStorage::logMessage(Message &msg) +{ + QSqlDatabase db = logDb(); + if (!db.transaction()) { + qWarning() << "PostgreSqlStorage::logMessage(): cannot start transaction!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return false; + } + + QSqlQuery getSenderIdQuery = executePreparedQuery("select_senderid", msg.sender(), db); + int senderId; + if (getSenderIdQuery.first()) { + senderId = getSenderIdQuery.value(0).toInt(); + } + else { + // it's possible that the sender was already added by another thread + // since the insert might fail we're setting a savepoint + savePoint("sender_sp1", db); + QSqlQuery addSenderQuery = executePreparedQuery("insert_sender", msg.sender(), db); + + if (addSenderQuery.lastError().isValid()) { + rollbackSavePoint("sender_sp1", db); + getSenderIdQuery = db.exec(getSenderIdQuery.lastQuery()); + getSenderIdQuery.first(); + senderId = getSenderIdQuery.value(0).toInt(); + } + else { + releaseSavePoint("sender_sp1", db); + addSenderQuery.first(); + senderId = addSenderQuery.value(0).toInt(); + } + } + QVariantList params; params << msg.timestamp() - << msg.bufferInfo().bufferId().toInt() - << msg.type() - << (int)msg.flags() - << senderIdList.at(i) - << msg.contents(); + << msg.bufferInfo().bufferId().toInt() + << msg.type() + << (int)msg.flags() + << senderId + << msg.contents(); QSqlQuery logMessageQuery = executePreparedQuery("insert_message", params, db); - if(!watchQuery(logMessageQuery)) { - db.rollback(); - error = true; - break; - } else { - logMessageQuery.first(); - msg.setMsgId(logMessageQuery.value(0).toInt()); + + if (!watchQuery(logMessageQuery)) { + db.rollback(); + return false; + } + + logMessageQuery.first(); + MsgId msgId = logMessageQuery.value(0).toInt(); + db.commit(); + if (msgId.isValid()) { + msg.setMsgId(msgId); + return true; + } + else { + return false; + } +} + + +bool PostgreSqlStorage::logMessages(MessageList &msgs) +{ + QSqlDatabase db = logDb(); + if (!db.transaction()) { + qWarning() << "PostgreSqlStorage::logMessage(): cannot start transaction!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return false; } - } - if(error) { - // we had a rollback in the db so we need to reset all msgIds - for(int i = 0; i < msgs.count(); i++) { - msgs[i].setMsgId(MsgId()); + QList senderIdList; + QHash senderIds; + QSqlQuery addSenderQuery; + QSqlQuery selectSenderQuery;; + for (int i = 0; i < msgs.count(); i++) { + const QString &sender = msgs.at(i).sender(); + if (senderIds.contains(sender)) { + senderIdList << senderIds[sender]; + continue; + } + + selectSenderQuery = executePreparedQuery("select_senderid", sender, db); + if (selectSenderQuery.first()) { + senderIdList << selectSenderQuery.value(0).toInt(); + senderIds[sender] = selectSenderQuery.value(0).toInt(); + } + else { + savePoint("sender_sp", db); + addSenderQuery = executePreparedQuery("insert_sender", sender, db); + if (addSenderQuery.lastError().isValid()) { + // seems it was inserted meanwhile... by a different thread + rollbackSavePoint("sender_sp", db); + selectSenderQuery = db.exec(selectSenderQuery.lastQuery()); + selectSenderQuery.first(); + senderIdList << selectSenderQuery.value(0).toInt(); + senderIds[sender] = selectSenderQuery.value(0).toInt(); + } + else { + releaseSavePoint("sender_sp", db); + addSenderQuery.first(); + senderIdList << addSenderQuery.value(0).toInt(); + senderIds[sender] = addSenderQuery.value(0).toInt(); + } + } } - return false; - } - db.commit(); - return true; + // yes we loop twice over the same list. This avoids alternating queries. + bool error = false; + for (int i = 0; i < msgs.count(); i++) { + Message &msg = msgs[i]; + QVariantList params; + params << msg.timestamp() + << msg.bufferInfo().bufferId().toInt() + << msg.type() + << (int)msg.flags() + << senderIdList.at(i) + << msg.contents(); + QSqlQuery logMessageQuery = executePreparedQuery("insert_message", params, db); + if (!watchQuery(logMessageQuery)) { + db.rollback(); + error = true; + break; + } + else { + logMessageQuery.first(); + msg.setMsgId(logMessageQuery.value(0).toInt()); + } + } + + if (error) { + // we had a rollback in the db so we need to reset all msgIds + for (int i = 0; i < msgs.count(); i++) { + msgs[i].setMsgId(MsgId()); + } + return false; + } + + db.commit(); + return true; } -QList PostgreSqlStorage::requestMsgs(UserId user, BufferId bufferId, MsgId first, MsgId last, int limit) { - QList messagelist; - QSqlDatabase db = logDb(); - if(!beginReadOnlyTransaction(db)) { - qWarning() << "PostgreSqlStorage::requestMsgs(): cannot start read only transaction!"; - qWarning() << " -" << qPrintable(db.lastError().text()); - return messagelist; - } +QList PostgreSqlStorage::requestMsgs(UserId user, BufferId bufferId, MsgId first, MsgId last, int limit) +{ + QList messagelist; - BufferInfo bufferInfo = getBufferInfo(user, bufferId); - if(!bufferInfo.isValid()) { - db.rollback(); - return messagelist; - } - - QString queryName; - QVariantList params; - if(last == -1 && first == -1) { - queryName = "select_messages"; - } else if(last == -1) { - queryName = "select_messagesNewerThan"; - params << first.toInt(); - } else { - queryName = "select_messagesRange"; - params << first.toInt(); - params << last.toInt(); - } - params << bufferId.toInt(); - if(limit != -1) - params << limit; - else - params << "ALL"; - - QSqlQuery query = executePreparedQuery(queryName, params, db); - - if(!watchQuery(query)) { - qDebug() << "select_messages failed"; - db.rollback(); - return messagelist; - } - - QDateTime timestamp; - while(query.next()) { - timestamp = query.value(1).toDateTime(); - timestamp.setTimeSpec(Qt::UTC); - Message msg(timestamp, - bufferInfo, - (Message::Type)query.value(2).toUInt(), - query.value(5).toString(), - query.value(4).toString(), - (Message::Flags)query.value(3).toUInt()); - msg.setMsgId(query.value(0).toInt()); - messagelist << msg; - } - - db.commit(); - return messagelist; -} - -QList PostgreSqlStorage::requestAllMsgs(UserId user, MsgId first, MsgId last, int limit) { - QList messagelist; - - // requestBuffers uses it's own transaction. - QHash bufferInfoHash; - foreach(BufferInfo bufferInfo, requestBuffers(user)) { - bufferInfoHash[bufferInfo.bufferId()] = bufferInfo; - } - - QSqlDatabase db = logDb(); - if(!beginReadOnlyTransaction(db)) { - qWarning() << "PostgreSqlStorage::requestAllMsgs(): cannot start read only transaction!"; - qWarning() << " -" << qPrintable(db.lastError().text()); + QSqlDatabase db = logDb(); + if (!beginReadOnlyTransaction(db)) { + qWarning() << "PostgreSqlStorage::requestMsgs(): cannot start read only transaction!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return messagelist; + } + + BufferInfo bufferInfo = getBufferInfo(user, bufferId); + if (!bufferInfo.isValid()) { + db.rollback(); + return messagelist; + } + + QString queryName; + QVariantList params; + if (last == -1 && first == -1) { + queryName = "select_messages"; + } + else if (last == -1) { + queryName = "select_messagesNewerThan"; + params << first.toInt(); + } + else { + queryName = "select_messagesRange"; + params << first.toInt(); + params << last.toInt(); + } + params << bufferId.toInt(); + if (limit != -1) + params << limit; + else + params << "ALL"; + + QSqlQuery query = executePreparedQuery(queryName, params, db); + + if (!watchQuery(query)) { + qDebug() << "select_messages failed"; + db.rollback(); + return messagelist; + } + + QDateTime timestamp; + while (query.next()) { + timestamp = query.value(1).toDateTime(); + timestamp.setTimeSpec(Qt::UTC); + Message msg(timestamp, + bufferInfo, + (Message::Type)query.value(2).toUInt(), + query.value(5).toString(), + query.value(4).toString(), + (Message::Flags)query.value(3).toUInt()); + msg.setMsgId(query.value(0).toInt()); + messagelist << msg; + } + + db.commit(); return messagelist; - } - - QSqlQuery query(db); - if(last == -1) { - query.prepare(queryString("select_messagesAllNew")); - } else { - query.prepare(queryString("select_messagesAll")); - query.bindValue(":lastmsg", last.toInt()); - } - query.bindValue(":userid", user.toInt()); - query.bindValue(":firstmsg", first.toInt()); - safeExec(query); - if(!watchQuery(query)) { - db.rollback(); +} + + +QList PostgreSqlStorage::requestAllMsgs(UserId user, MsgId first, MsgId last, int limit) +{ + QList messagelist; + + // requestBuffers uses it's own transaction. + QHash bufferInfoHash; + foreach(BufferInfo bufferInfo, requestBuffers(user)) { + bufferInfoHash[bufferInfo.bufferId()] = bufferInfo; + } + + QSqlDatabase db = logDb(); + if (!beginReadOnlyTransaction(db)) { + qWarning() << "PostgreSqlStorage::requestAllMsgs(): cannot start read only transaction!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return messagelist; + } + + QSqlQuery query(db); + if (last == -1) { + query.prepare(queryString("select_messagesAllNew")); + } + else { + query.prepare(queryString("select_messagesAll")); + query.bindValue(":lastmsg", last.toInt()); + } + query.bindValue(":userid", user.toInt()); + query.bindValue(":firstmsg", first.toInt()); + safeExec(query); + if (!watchQuery(query)) { + db.rollback(); + return messagelist; + } + + QDateTime timestamp; + for (int i = 0; i < limit && query.next(); i++) { + timestamp = query.value(1).toDateTime(); + timestamp.setTimeSpec(Qt::UTC); + Message msg(timestamp, + bufferInfoHash[query.value(1).toInt()], + (Message::Type)query.value(3).toUInt(), + query.value(6).toString(), + query.value(5).toString(), + (Message::Flags)query.value(4).toUInt()); + msg.setMsgId(query.value(0).toInt()); + messagelist << msg; + } + + db.commit(); return messagelist; - } - - QDateTime timestamp; - for(int i = 0; i < limit && query.next(); i++) { - timestamp = query.value(1).toDateTime(); - timestamp.setTimeSpec(Qt::UTC); - Message msg(timestamp, - bufferInfoHash[query.value(1).toInt()], - (Message::Type)query.value(3).toUInt(), - query.value(6).toString(), - query.value(5).toString(), - (Message::Flags)query.value(4).toUInt()); - msg.setMsgId(query.value(0).toInt()); - messagelist << msg; - } - - db.commit(); - return messagelist; } + // void PostgreSqlStorage::safeExec(QSqlQuery &query) { // qDebug() << "PostgreSqlStorage::safeExec"; // qDebug() << " executing:\n" << query.executedQuery(); @@ -1453,291 +1579,327 @@ QList PostgreSqlStorage::requestAllMsgs(UserId user, MsgId first, MsgId // return; // } -bool PostgreSqlStorage::beginReadOnlyTransaction(QSqlDatabase &db) { - QSqlQuery query = db.exec("BEGIN TRANSACTION READ ONLY"); - return !query.lastError().isValid(); +bool PostgreSqlStorage::beginReadOnlyTransaction(QSqlDatabase &db) +{ + QSqlQuery query = db.exec("BEGIN TRANSACTION READ ONLY"); + return !query.lastError().isValid(); } -QSqlQuery PostgreSqlStorage::prepareAndExecuteQuery(const QString &queryname, const QString ¶mstring, const QSqlDatabase &db) { - // Query preparing is done lazily. That means that instead of always checking if the query is already prepared - // we just EXECUTE and catch the error - QSqlQuery query; - db.exec("SAVEPOINT quassel_prepare_query"); - if(paramstring.isNull()) { - query = db.exec(QString("EXECUTE quassel_%1").arg(queryname)); - } else { - query = db.exec(QString("EXECUTE quassel_%1 (%2)").arg(queryname).arg(paramstring)); - } +QSqlQuery PostgreSqlStorage::prepareAndExecuteQuery(const QString &queryname, const QString ¶mstring, const QSqlDatabase &db) +{ + // Query preparing is done lazily. That means that instead of always checking if the query is already prepared + // we just EXECUTE and catch the error + QSqlQuery query; - if(db.lastError().isValid()) { - // and once again: Qt leaves us without error codes so we either parse (language dependant(!)) strings - // or we just guess the error. As we're only interested in unprepared queries, this will be our guess. :) - db.exec("ROLLBACK TO SAVEPOINT quassel_prepare_query"); - QSqlQuery checkQuery = db.exec(QString("SELECT count(name) FROM pg_prepared_statements WHERE name = 'quassel_%1' AND from_sql = TRUE").arg(queryname.toLower())); - checkQuery.first(); - if(checkQuery.value(0).toInt() == 0) { - db.exec(QString("PREPARE quassel_%1 AS %2").arg(queryname).arg(queryString(queryname))); - if(db.lastError().isValid()) { - qWarning() << "PostgreSqlStorage::prepareQuery(): unable to prepare query:" << queryname << "AS" << queryString(queryname); - qWarning() << " Error:" << db.lastError().text(); - return QSqlQuery(db); - } - } - // we alwas execute the query again, even if the query was already prepared. - // this ensures, that the error is properly propagated to the calling function - // (otherwise the last call would be the testing select to pg_prepared_statements - // which always gives a proper result and the error would be lost) - if(paramstring.isNull()) { - query = db.exec(QString("EXECUTE quassel_%1").arg(queryname)); - } else { - query = db.exec(QString("EXECUTE quassel_%1 (%2)").arg(queryname).arg(paramstring)); - } - } else { - // only release the SAVEPOINT - db.exec("RELEASE SAVEPOINT quassel_prepare_query"); - } - return query; -} - -QSqlQuery PostgreSqlStorage::executePreparedQuery(const QString &queryname, const QVariantList ¶ms, const QSqlDatabase &db) { - QSqlDriver *driver = db.driver(); - - QStringList paramStrings; - QSqlField field; - for(int i = 0; i < params.count(); i++) { - const QVariant &value = params.at(i); - field.setType(value.type()); - if(value.isNull()) - field.clear(); - else - field.setValue(value); + db.exec("SAVEPOINT quassel_prepare_query"); + if (paramstring.isNull()) { + query = db.exec(QString("EXECUTE quassel_%1").arg(queryname)); + } + else { + query = db.exec(QString("EXECUTE quassel_%1 (%2)").arg(queryname).arg(paramstring)); + } - paramStrings << driver->formatValue(field); - } + if (db.lastError().isValid()) { + // and once again: Qt leaves us without error codes so we either parse (language dependant(!)) strings + // or we just guess the error. As we're only interested in unprepared queries, this will be our guess. :) + db.exec("ROLLBACK TO SAVEPOINT quassel_prepare_query"); + QSqlQuery checkQuery = db.exec(QString("SELECT count(name) FROM pg_prepared_statements WHERE name = 'quassel_%1' AND from_sql = TRUE").arg(queryname.toLower())); + checkQuery.first(); + if (checkQuery.value(0).toInt() == 0) { + db.exec(QString("PREPARE quassel_%1 AS %2").arg(queryname).arg(queryString(queryname))); + if (db.lastError().isValid()) { + qWarning() << "PostgreSqlStorage::prepareQuery(): unable to prepare query:" << queryname << "AS" << queryString(queryname); + qWarning() << " Error:" << db.lastError().text(); + return QSqlQuery(db); + } + } + // we alwas execute the query again, even if the query was already prepared. + // this ensures, that the error is properly propagated to the calling function + // (otherwise the last call would be the testing select to pg_prepared_statements + // which always gives a proper result and the error would be lost) + if (paramstring.isNull()) { + query = db.exec(QString("EXECUTE quassel_%1").arg(queryname)); + } + else { + query = db.exec(QString("EXECUTE quassel_%1 (%2)").arg(queryname).arg(paramstring)); + } + } + else { + // only release the SAVEPOINT + db.exec("RELEASE SAVEPOINT quassel_prepare_query"); + } + return query; +} + + +QSqlQuery PostgreSqlStorage::executePreparedQuery(const QString &queryname, const QVariantList ¶ms, const QSqlDatabase &db) +{ + QSqlDriver *driver = db.driver(); + + QStringList paramStrings; + QSqlField field; + for (int i = 0; i < params.count(); i++) { + const QVariant &value = params.at(i); + field.setType(value.type()); + if (value.isNull()) + field.clear(); + else + field.setValue(value); + + paramStrings << driver->formatValue(field); + } - if(params.isEmpty()) { - return prepareAndExecuteQuery(queryname, db); - } else { - return prepareAndExecuteQuery(queryname, paramStrings.join(", "), db); - } + if (params.isEmpty()) { + return prepareAndExecuteQuery(queryname, db); + } + else { + return prepareAndExecuteQuery(queryname, paramStrings.join(", "), db); + } } -QSqlQuery PostgreSqlStorage::executePreparedQuery(const QString &queryname, const QVariant ¶m, const QSqlDatabase &db) { - QSqlField field; - field.setType(param.type()); - if(param.isNull()) - field.clear(); - else - field.setValue(param); - QString paramString = db.driver()->formatValue(field); - return prepareAndExecuteQuery(queryname, paramString, db); +QSqlQuery PostgreSqlStorage::executePreparedQuery(const QString &queryname, const QVariant ¶m, const QSqlDatabase &db) +{ + QSqlField field; + field.setType(param.type()); + if (param.isNull()) + field.clear(); + else + field.setValue(param); + + QString paramString = db.driver()->formatValue(field); + return prepareAndExecuteQuery(queryname, paramString, db); } -void PostgreSqlStorage::deallocateQuery(const QString &queryname, const QSqlDatabase &db) { - db.exec(QString("DEALLOCATE quassel_%1").arg(queryname)); + +void PostgreSqlStorage::deallocateQuery(const QString &queryname, const QSqlDatabase &db) +{ + db.exec(QString("DEALLOCATE quassel_%1").arg(queryname)); } + // ======================================== // PostgreSqlMigrationWriter // ======================================== PostgreSqlMigrationWriter::PostgreSqlMigrationWriter() - : PostgreSqlStorage() -{ -} - -bool PostgreSqlMigrationWriter::prepareQuery(MigrationObject mo) { - QString query; - switch(mo) { - case QuasselUser: - query = queryString("migrate_write_quasseluser"); - break; - case Sender: - query = queryString("migrate_write_sender"); - break; - case Identity: - _validIdentities.clear(); - query = queryString("migrate_write_identity"); - break; - case IdentityNick: - query = queryString("migrate_write_identity_nick"); - break; - case Network: - query = queryString("migrate_write_network"); - break; - case Buffer: - query = queryString("migrate_write_buffer"); - break; - case Backlog: - query = queryString("migrate_write_backlog"); - break; - case IrcServer: - query = queryString("migrate_write_ircserver"); - break; - case UserSetting: - query = queryString("migrate_write_usersetting"); - break; - } - newQuery(query, logDb()); - return true; + : PostgreSqlStorage() +{ } + +bool PostgreSqlMigrationWriter::prepareQuery(MigrationObject mo) +{ + QString query; + switch (mo) { + case QuasselUser: + query = queryString("migrate_write_quasseluser"); + break; + case Sender: + query = queryString("migrate_write_sender"); + break; + case Identity: + _validIdentities.clear(); + query = queryString("migrate_write_identity"); + break; + case IdentityNick: + query = queryString("migrate_write_identity_nick"); + break; + case Network: + query = queryString("migrate_write_network"); + break; + case Buffer: + query = queryString("migrate_write_buffer"); + break; + case Backlog: + query = queryString("migrate_write_backlog"); + break; + case IrcServer: + query = queryString("migrate_write_ircserver"); + break; + case UserSetting: + query = queryString("migrate_write_usersetting"); + break; + } + newQuery(query, logDb()); + return true; +} + + //bool PostgreSqlMigrationWriter::writeUser(const QuasselUserMO &user) { -bool PostgreSqlMigrationWriter::writeMo(const QuasselUserMO &user) { - bindValue(0, user.id.toInt()); - bindValue(1, user.username); - bindValue(2, user.password); - return exec(); +bool PostgreSqlMigrationWriter::writeMo(const QuasselUserMO &user) +{ + bindValue(0, user.id.toInt()); + bindValue(1, user.username); + bindValue(2, user.password); + return exec(); } + //bool PostgreSqlMigrationWriter::writeSender(const SenderMO &sender) { -bool PostgreSqlMigrationWriter::writeMo(const SenderMO &sender) { - bindValue(0, sender.senderId); - bindValue(1, sender.sender); - return exec(); +bool PostgreSqlMigrationWriter::writeMo(const SenderMO &sender) +{ + bindValue(0, sender.senderId); + bindValue(1, sender.sender); + return exec(); } + //bool PostgreSqlMigrationWriter::writeIdentity(const IdentityMO &identity) { -bool PostgreSqlMigrationWriter::writeMo(const IdentityMO &identity) { - _validIdentities << identity.id.toInt(); - bindValue(0, identity.id.toInt()); - bindValue(1, identity.userid.toInt()); - bindValue(2, identity.identityname); - bindValue(3, identity.realname); - bindValue(4, identity.awayNick); - bindValue(5, identity.awayNickEnabled); - bindValue(6, identity.awayReason); - bindValue(7, identity.awayReasonEnabled); - bindValue(8, identity.autoAwayEnabled); - bindValue(9, identity.autoAwayTime); - bindValue(10, identity.autoAwayReason); - bindValue(11, identity.autoAwayReasonEnabled); - bindValue(12, identity.detachAwayEnabled); - bindValue(13, identity.detachAwayReason); - bindValue(14, identity.detchAwayReasonEnabled); - bindValue(15, identity.ident); - bindValue(16, identity.kickReason); - bindValue(17, identity.partReason); - bindValue(18, identity.quitReason); - bindValue(19, identity.sslCert); - bindValue(20, identity.sslKey); - return exec(); +bool PostgreSqlMigrationWriter::writeMo(const IdentityMO &identity) +{ + _validIdentities << identity.id.toInt(); + bindValue(0, identity.id.toInt()); + bindValue(1, identity.userid.toInt()); + bindValue(2, identity.identityname); + bindValue(3, identity.realname); + bindValue(4, identity.awayNick); + bindValue(5, identity.awayNickEnabled); + bindValue(6, identity.awayReason); + bindValue(7, identity.awayReasonEnabled); + bindValue(8, identity.autoAwayEnabled); + bindValue(9, identity.autoAwayTime); + bindValue(10, identity.autoAwayReason); + bindValue(11, identity.autoAwayReasonEnabled); + bindValue(12, identity.detachAwayEnabled); + bindValue(13, identity.detachAwayReason); + bindValue(14, identity.detchAwayReasonEnabled); + bindValue(15, identity.ident); + bindValue(16, identity.kickReason); + bindValue(17, identity.partReason); + bindValue(18, identity.quitReason); + bindValue(19, identity.sslCert); + bindValue(20, identity.sslKey); + return exec(); } + //bool PostgreSqlMigrationWriter::writeIdentityNick(const IdentityNickMO &identityNick) { -bool PostgreSqlMigrationWriter::writeMo(const IdentityNickMO &identityNick) { - bindValue(0, identityNick.nickid); - bindValue(1, identityNick.identityId.toInt()); - bindValue(2, identityNick.nick); - return exec(); +bool PostgreSqlMigrationWriter::writeMo(const IdentityNickMO &identityNick) +{ + bindValue(0, identityNick.nickid); + bindValue(1, identityNick.identityId.toInt()); + bindValue(2, identityNick.nick); + return exec(); } + //bool PostgreSqlMigrationWriter::writeNetwork(const NetworkMO &network) { -bool PostgreSqlMigrationWriter::writeMo(const NetworkMO &network) { - bindValue(0, network.networkid.toInt()); - bindValue(1, network.userid.toInt()); - bindValue(2, network.networkname); - if(_validIdentities.contains(network.identityid.toInt())) - bindValue(3, network.identityid.toInt()); - else - bindValue(3, QVariant()); - bindValue(4, network.encodingcodec); - bindValue(5, network.decodingcodec); - bindValue(6, network.servercodec); - bindValue(7, network.userandomserver); - bindValue(8, network.perform); - bindValue(9, network.useautoidentify); - bindValue(10, network.autoidentifyservice); - bindValue(11, network.autoidentifypassword); - bindValue(12, network.useautoreconnect); - bindValue(13, network.autoreconnectinterval); - bindValue(14, network.autoreconnectretries); - bindValue(15, network.unlimitedconnectretries); - bindValue(16, network.rejoinchannels); - bindValue(17, network.connected); - bindValue(18, network.usermode); - bindValue(19, network.awaymessage); - bindValue(20, network.attachperform); - bindValue(21, network.detachperform); - bindValue(22, network.usesasl); - bindValue(23, network.saslaccount); - bindValue(24, network.saslpassword); - return exec(); +bool PostgreSqlMigrationWriter::writeMo(const NetworkMO &network) +{ + bindValue(0, network.networkid.toInt()); + bindValue(1, network.userid.toInt()); + bindValue(2, network.networkname); + if (_validIdentities.contains(network.identityid.toInt())) + bindValue(3, network.identityid.toInt()); + else + bindValue(3, QVariant()); + bindValue(4, network.encodingcodec); + bindValue(5, network.decodingcodec); + bindValue(6, network.servercodec); + bindValue(7, network.userandomserver); + bindValue(8, network.perform); + bindValue(9, network.useautoidentify); + bindValue(10, network.autoidentifyservice); + bindValue(11, network.autoidentifypassword); + bindValue(12, network.useautoreconnect); + bindValue(13, network.autoreconnectinterval); + bindValue(14, network.autoreconnectretries); + bindValue(15, network.unlimitedconnectretries); + bindValue(16, network.rejoinchannels); + bindValue(17, network.connected); + bindValue(18, network.usermode); + bindValue(19, network.awaymessage); + bindValue(20, network.attachperform); + bindValue(21, network.detachperform); + bindValue(22, network.usesasl); + bindValue(23, network.saslaccount); + bindValue(24, network.saslpassword); + return exec(); } + //bool PostgreSqlMigrationWriter::writeBuffer(const BufferMO &buffer) { -bool PostgreSqlMigrationWriter::writeMo(const BufferMO &buffer) { - bindValue(0, buffer.bufferid.toInt()); - bindValue(1, buffer.userid.toInt()); - bindValue(2, buffer.groupid); - bindValue(3, buffer.networkid.toInt()); - bindValue(4, buffer.buffername); - bindValue(5, buffer.buffercname); - bindValue(6, (int)buffer.buffertype); - bindValue(7, buffer.lastseenmsgid); - bindValue(8, buffer.markerlinemsgid); - bindValue(9, buffer.key); - bindValue(10, buffer.joined); - return exec(); +bool PostgreSqlMigrationWriter::writeMo(const BufferMO &buffer) +{ + bindValue(0, buffer.bufferid.toInt()); + bindValue(1, buffer.userid.toInt()); + bindValue(2, buffer.groupid); + bindValue(3, buffer.networkid.toInt()); + bindValue(4, buffer.buffername); + bindValue(5, buffer.buffercname); + bindValue(6, (int)buffer.buffertype); + bindValue(7, buffer.lastseenmsgid); + bindValue(8, buffer.markerlinemsgid); + bindValue(9, buffer.key); + bindValue(10, buffer.joined); + return exec(); } + //bool PostgreSqlMigrationWriter::writeBacklog(const BacklogMO &backlog) { -bool PostgreSqlMigrationWriter::writeMo(const BacklogMO &backlog) { - bindValue(0, backlog.messageid.toInt()); - bindValue(1, backlog.time); - bindValue(2, backlog.bufferid.toInt()); - bindValue(3, backlog.type); - bindValue(4, (int)backlog.flags); - bindValue(5, backlog.senderid); - bindValue(6, backlog.message); - return exec(); +bool PostgreSqlMigrationWriter::writeMo(const BacklogMO &backlog) +{ + bindValue(0, backlog.messageid.toInt()); + bindValue(1, backlog.time); + bindValue(2, backlog.bufferid.toInt()); + bindValue(3, backlog.type); + bindValue(4, (int)backlog.flags); + bindValue(5, backlog.senderid); + bindValue(6, backlog.message); + return exec(); } + //bool PostgreSqlMigrationWriter::writeIrcServer(const IrcServerMO &ircserver) { -bool PostgreSqlMigrationWriter::writeMo(const IrcServerMO &ircserver) { - bindValue(0, ircserver.serverid); - bindValue(1, ircserver.userid.toInt()); - bindValue(2, ircserver.networkid.toInt()); - bindValue(3, ircserver.hostname); - bindValue(4, ircserver.port); - bindValue(5, ircserver.password); - bindValue(6, ircserver.ssl); - bindValue(7, ircserver.sslversion); - bindValue(8, ircserver.useproxy); - bindValue(9, ircserver.proxytype); - bindValue(10, ircserver.proxyhost); - bindValue(11, ircserver.proxyport); - bindValue(12, ircserver.proxyuser); - bindValue(13, ircserver.proxypass); - return exec(); +bool PostgreSqlMigrationWriter::writeMo(const IrcServerMO &ircserver) +{ + bindValue(0, ircserver.serverid); + bindValue(1, ircserver.userid.toInt()); + bindValue(2, ircserver.networkid.toInt()); + bindValue(3, ircserver.hostname); + bindValue(4, ircserver.port); + bindValue(5, ircserver.password); + bindValue(6, ircserver.ssl); + bindValue(7, ircserver.sslversion); + bindValue(8, ircserver.useproxy); + bindValue(9, ircserver.proxytype); + bindValue(10, ircserver.proxyhost); + bindValue(11, ircserver.proxyport); + bindValue(12, ircserver.proxyuser); + bindValue(13, ircserver.proxypass); + return exec(); } + //bool PostgreSqlMigrationWriter::writeUserSetting(const UserSettingMO &userSetting) { -bool PostgreSqlMigrationWriter::writeMo(const UserSettingMO &userSetting) { - bindValue(0, userSetting.userid.toInt()); - bindValue(1, userSetting.settingname); - bindValue(2, userSetting.settingvalue); - return exec(); -} - -bool PostgreSqlMigrationWriter::postProcess() { - QSqlDatabase db = logDb(); - QList sequences; - sequences << Sequence("backlog", "messageid") - << Sequence("buffer", "bufferid") - << Sequence("identity", "identityid") - << Sequence("identity_nick", "nickid") - << Sequence("ircserver", "serverid") - << Sequence("network", "networkid") - << Sequence("quasseluser", "userid") - << Sequence("sender", "senderid"); - QList::const_iterator iter; - for(iter = sequences.constBegin(); iter != sequences.constEnd(); iter++) { - resetQuery(); - newQuery(QString("SELECT setval('%1_%2_seq', max(%2)) FROM %1").arg(iter->table, iter->field), db); - if(!exec()) - return false; - } - return true; +bool PostgreSqlMigrationWriter::writeMo(const UserSettingMO &userSetting) +{ + bindValue(0, userSetting.userid.toInt()); + bindValue(1, userSetting.settingname); + bindValue(2, userSetting.settingvalue); + return exec(); +} + + +bool PostgreSqlMigrationWriter::postProcess() +{ + QSqlDatabase db = logDb(); + QList sequences; + sequences << Sequence("backlog", "messageid") + << Sequence("buffer", "bufferid") + << Sequence("identity", "identityid") + << Sequence("identity_nick", "nickid") + << Sequence("ircserver", "serverid") + << Sequence("network", "networkid") + << Sequence("quasseluser", "userid") + << Sequence("sender", "senderid"); + QList::const_iterator iter; + for (iter = sequences.constBegin(); iter != sequences.constEnd(); iter++) { + resetQuery(); + newQuery(QString("SELECT setval('%1_%2_seq', max(%2)) FROM %1").arg(iter->table, iter->field), db); + if (!exec()) + return false; + } + return true; } diff --git a/src/core/postgresqlstorage.h b/src/core/postgresqlstorage.h index 83b24e22..efa2d8a4 100644 --- a/src/core/postgresqlstorage.h +++ b/src/core/postgresqlstorage.h @@ -26,158 +26,161 @@ #include #include -class PostgreSqlStorage : public AbstractSqlStorage { - Q_OBJECT +class PostgreSqlStorage : public AbstractSqlStorage +{ + Q_OBJECT public: - PostgreSqlStorage(QObject *parent = 0); - virtual ~PostgreSqlStorage(); + PostgreSqlStorage(QObject *parent = 0); + virtual ~PostgreSqlStorage(); - virtual AbstractSqlMigrationWriter *createMigrationWriter(); + virtual AbstractSqlMigrationWriter *createMigrationWriter(); public slots: - /* General */ - virtual bool isAvailable() const; - virtual QString displayName() const; - virtual QString description() const; - virtual QStringList setupKeys() const; - virtual QVariantMap setupDefaults() const; - - // TODO: Add functions for configuring the backlog handling, i.e. defining auto-cleanup settings etc - - /* User handling */ - - virtual UserId addUser(const QString &user, const QString &password); - virtual bool updateUser(UserId user, const QString &password); - virtual void renameUser(UserId user, const QString &newName); - virtual UserId validateUser(const QString &user, const QString &password); - virtual UserId getUserId(const QString &username); - virtual UserId internalUser(); - virtual void delUser(UserId user); - virtual void setUserSetting(UserId userId, const QString &settingName, const QVariant &data); - virtual QVariant getUserSetting(UserId userId, const QString &settingName, const QVariant &defaultData = QVariant()); - - /* Identity handling */ - virtual IdentityId createIdentity(UserId user, CoreIdentity &identity); - virtual bool updateIdentity(UserId user, const CoreIdentity &identity); - virtual void removeIdentity(UserId user, IdentityId identityId); - virtual QList identities(UserId user); - - /* Network handling */ - virtual NetworkId createNetwork(UserId user, const NetworkInfo &info); - virtual bool updateNetwork(UserId user, const NetworkInfo &info); - virtual bool removeNetwork(UserId user, const NetworkId &networkId); - virtual QList networks(UserId user); - virtual QList connectedNetworks(UserId user); - virtual void setNetworkConnected(UserId user, const NetworkId &networkId, bool isConnected); - - /* persistent channels */ - virtual QHash persistentChannels(UserId user, const NetworkId &networkId); - virtual void setChannelPersistent(UserId user, const NetworkId &networkId, const QString &channel, bool isJoined); - virtual void setPersistentChannelKey(UserId user, const NetworkId &networkId, const QString &channel, const QString &key); - - /* persistent user states */ - virtual QString awayMessage(UserId user, NetworkId networkId); - virtual void setAwayMessage(UserId user, NetworkId networkId, const QString &awayMsg); - virtual QString userModes(UserId user, NetworkId networkId); - virtual void setUserModes(UserId user, NetworkId networkId, const QString &userModes); - - /* Buffer handling */ - virtual BufferInfo bufferInfo(UserId user, const NetworkId &networkId, BufferInfo::Type type, const QString &buffer = "", bool create = true); - virtual BufferInfo getBufferInfo(UserId user, const BufferId &bufferId); - virtual QList requestBuffers(UserId user); - virtual QList requestBufferIdsForNetwork(UserId user, NetworkId networkId); - virtual bool removeBuffer(const UserId &user, const BufferId &bufferId); - virtual bool renameBuffer(const UserId &user, const BufferId &bufferId, const QString &newName); - virtual bool mergeBuffersPermanently(const UserId &user, const BufferId &bufferId1, const BufferId &bufferId2); - virtual void setBufferLastSeenMsg(UserId user, const BufferId &bufferId, const MsgId &msgId); - virtual QHash bufferLastSeenMsgIds(UserId user); - virtual void setBufferMarkerLineMsg(UserId user, const BufferId &bufferId, const MsgId &msgId); - virtual QHash bufferMarkerLineMsgIds(UserId user); - - /* Message handling */ - virtual bool logMessage(Message &msg); - virtual bool logMessages(MessageList &msgs); - virtual QList requestMsgs(UserId user, BufferId bufferId, MsgId first = -1, MsgId last = -1, int limit = -1); - virtual QList requestAllMsgs(UserId user, MsgId first = -1, MsgId last = -1, int limit = -1); + /* General */ + virtual bool isAvailable() const; + virtual QString displayName() const; + virtual QString description() const; + virtual QStringList setupKeys() const; + virtual QVariantMap setupDefaults() const; + + // TODO: Add functions for configuring the backlog handling, i.e. defining auto-cleanup settings etc + + /* User handling */ + + virtual UserId addUser(const QString &user, const QString &password); + virtual bool updateUser(UserId user, const QString &password); + virtual void renameUser(UserId user, const QString &newName); + virtual UserId validateUser(const QString &user, const QString &password); + virtual UserId getUserId(const QString &username); + virtual UserId internalUser(); + virtual void delUser(UserId user); + virtual void setUserSetting(UserId userId, const QString &settingName, const QVariant &data); + virtual QVariant getUserSetting(UserId userId, const QString &settingName, const QVariant &defaultData = QVariant()); + + /* Identity handling */ + virtual IdentityId createIdentity(UserId user, CoreIdentity &identity); + virtual bool updateIdentity(UserId user, const CoreIdentity &identity); + virtual void removeIdentity(UserId user, IdentityId identityId); + virtual QList identities(UserId user); + + /* Network handling */ + virtual NetworkId createNetwork(UserId user, const NetworkInfo &info); + virtual bool updateNetwork(UserId user, const NetworkInfo &info); + virtual bool removeNetwork(UserId user, const NetworkId &networkId); + virtual QList networks(UserId user); + virtual QList connectedNetworks(UserId user); + virtual void setNetworkConnected(UserId user, const NetworkId &networkId, bool isConnected); + + /* persistent channels */ + virtual QHash persistentChannels(UserId user, const NetworkId &networkId); + virtual void setChannelPersistent(UserId user, const NetworkId &networkId, const QString &channel, bool isJoined); + virtual void setPersistentChannelKey(UserId user, const NetworkId &networkId, const QString &channel, const QString &key); + + /* persistent user states */ + virtual QString awayMessage(UserId user, NetworkId networkId); + virtual void setAwayMessage(UserId user, NetworkId networkId, const QString &awayMsg); + virtual QString userModes(UserId user, NetworkId networkId); + virtual void setUserModes(UserId user, NetworkId networkId, const QString &userModes); + + /* Buffer handling */ + virtual BufferInfo bufferInfo(UserId user, const NetworkId &networkId, BufferInfo::Type type, const QString &buffer = "", bool create = true); + virtual BufferInfo getBufferInfo(UserId user, const BufferId &bufferId); + virtual QList requestBuffers(UserId user); + virtual QList requestBufferIdsForNetwork(UserId user, NetworkId networkId); + virtual bool removeBuffer(const UserId &user, const BufferId &bufferId); + virtual bool renameBuffer(const UserId &user, const BufferId &bufferId, const QString &newName); + virtual bool mergeBuffersPermanently(const UserId &user, const BufferId &bufferId1, const BufferId &bufferId2); + virtual void setBufferLastSeenMsg(UserId user, const BufferId &bufferId, const MsgId &msgId); + virtual QHash bufferLastSeenMsgIds(UserId user); + virtual void setBufferMarkerLineMsg(UserId user, const BufferId &bufferId, const MsgId &msgId); + virtual QHash bufferMarkerLineMsgIds(UserId user); + + /* Message handling */ + virtual bool logMessage(Message &msg); + virtual bool logMessages(MessageList &msgs); + virtual QList requestMsgs(UserId user, BufferId bufferId, MsgId first = -1, MsgId last = -1, int limit = -1); + virtual QList requestAllMsgs(UserId user, MsgId first = -1, MsgId last = -1, int limit = -1); protected: - virtual void initDbSession(QSqlDatabase &db); - virtual void setConnectionProperties(const QVariantMap &properties); - inline virtual QString driverName() { return "QPSQL"; } - inline virtual QString hostName() { return _hostName; } - inline virtual int port() { return _port; } - inline virtual QString databaseName() { return _databaseName; } - inline virtual QString userName() { return _userName; } - inline virtual QString password() { return _password; } - virtual int installedSchemaVersion(); - virtual bool updateSchemaVersion(int newVersion); - virtual bool setupSchemaVersion(int version); - void safeExec(QSqlQuery &query); - - bool beginReadOnlyTransaction(QSqlDatabase &db); - - QSqlQuery executePreparedQuery(const QString &queryname, const QVariantList ¶ms, const QSqlDatabase &db); - QSqlQuery executePreparedQuery(const QString &queryname, const QVariant ¶m, const QSqlDatabase &db); - void deallocateQuery(const QString &queryname, const QSqlDatabase &db); - - inline void savePoint(const QString &handle, const QSqlDatabase &db) { db.exec(QString("SAVEPOINT %1").arg(handle)); } - inline void rollbackSavePoint(const QString &handle, const QSqlDatabase &db) { db.exec(QString("ROLLBACK TO SAVEPOINT %1").arg(handle)); } - inline void releaseSavePoint(const QString &handle, const QSqlDatabase &db) { db.exec(QString("RELEASE SAVEPOINT %1").arg(handle)); } + virtual void initDbSession(QSqlDatabase &db); + virtual void setConnectionProperties(const QVariantMap &properties); + inline virtual QString driverName() { return "QPSQL"; } + inline virtual QString hostName() { return _hostName; } + inline virtual int port() { return _port; } + inline virtual QString databaseName() { return _databaseName; } + inline virtual QString userName() { return _userName; } + inline virtual QString password() { return _password; } + virtual int installedSchemaVersion(); + virtual bool updateSchemaVersion(int newVersion); + virtual bool setupSchemaVersion(int version); + void safeExec(QSqlQuery &query); + + bool beginReadOnlyTransaction(QSqlDatabase &db); + + QSqlQuery executePreparedQuery(const QString &queryname, const QVariantList ¶ms, const QSqlDatabase &db); + QSqlQuery executePreparedQuery(const QString &queryname, const QVariant ¶m, const QSqlDatabase &db); + void deallocateQuery(const QString &queryname, const QSqlDatabase &db); + + inline void savePoint(const QString &handle, const QSqlDatabase &db) { db.exec(QString("SAVEPOINT %1").arg(handle)); } + inline void rollbackSavePoint(const QString &handle, const QSqlDatabase &db) { db.exec(QString("ROLLBACK TO SAVEPOINT %1").arg(handle)); } + inline void releaseSavePoint(const QString &handle, const QSqlDatabase &db) { db.exec(QString("RELEASE SAVEPOINT %1").arg(handle)); } private: - void bindNetworkInfo(QSqlQuery &query, const NetworkInfo &info); - void bindServerInfo(QSqlQuery &query, const Network::Server &server); - QSqlQuery prepareAndExecuteQuery(const QString &queryname, const QString ¶mstring, const QSqlDatabase &db); - inline QSqlQuery prepareAndExecuteQuery(const QString &queryname, const QSqlDatabase &db) { return prepareAndExecuteQuery(queryname, QString(), db); } - - QString _hostName; - int _port; - QString _databaseName; - QString _userName; - QString _password; + void bindNetworkInfo(QSqlQuery &query, const NetworkInfo &info); + void bindServerInfo(QSqlQuery &query, const Network::Server &server); + QSqlQuery prepareAndExecuteQuery(const QString &queryname, const QString ¶mstring, const QSqlDatabase &db); + inline QSqlQuery prepareAndExecuteQuery(const QString &queryname, const QSqlDatabase &db) { return prepareAndExecuteQuery(queryname, QString(), db); } + + QString _hostName; + int _port; + QString _databaseName; + QString _userName; + QString _password; }; -inline void PostgreSqlStorage::safeExec(QSqlQuery &query) { query.exec(); } +inline void PostgreSqlStorage::safeExec(QSqlQuery &query) { query.exec(); } // ======================================== // PostgreSqlMigration // ======================================== -class PostgreSqlMigrationWriter : public PostgreSqlStorage, public AbstractSqlMigrationWriter { - Q_OBJECT +class PostgreSqlMigrationWriter : public PostgreSqlStorage, public AbstractSqlMigrationWriter +{ + Q_OBJECT public: - PostgreSqlMigrationWriter(); + PostgreSqlMigrationWriter(); - virtual bool writeMo(const QuasselUserMO &user); - virtual bool writeMo(const SenderMO &sender); - virtual bool writeMo(const IdentityMO &identity); - virtual bool writeMo(const IdentityNickMO &identityNick); - virtual bool writeMo(const NetworkMO &network); - virtual bool writeMo(const BufferMO &buffer); - virtual bool writeMo(const BacklogMO &backlog); - virtual bool writeMo(const IrcServerMO &ircserver); - virtual bool writeMo(const UserSettingMO &userSetting); + virtual bool writeMo(const QuasselUserMO &user); + virtual bool writeMo(const SenderMO &sender); + virtual bool writeMo(const IdentityMO &identity); + virtual bool writeMo(const IdentityNickMO &identityNick); + virtual bool writeMo(const NetworkMO &network); + virtual bool writeMo(const BufferMO &buffer); + virtual bool writeMo(const BacklogMO &backlog); + virtual bool writeMo(const IrcServerMO &ircserver); + virtual bool writeMo(const UserSettingMO &userSetting); - bool prepareQuery(MigrationObject mo); + bool prepareQuery(MigrationObject mo); - virtual bool postProcess(); + virtual bool postProcess(); protected: - virtual inline bool transaction() { return logDb().transaction(); } - virtual inline void rollback() { logDb().rollback(); } - virtual inline bool commit() { return logDb().commit(); } + virtual inline bool transaction() { return logDb().transaction(); } + virtual inline void rollback() { logDb().rollback(); } + virtual inline bool commit() { return logDb().commit(); } private: - // helper struct - struct Sequence { - QLatin1String table; - QLatin1String field; - Sequence(const char *table, const char *field) : table(table), field(field) {} - }; - - QSet _validIdentities; + // helper struct + struct Sequence { + QLatin1String table; + QLatin1String field; + Sequence(const char *table, const char *field) : table(table), field(field) {} + }; + + QSet _validIdentities; }; + #endif diff --git a/src/core/sessionthread.cpp b/src/core/sessionthread.cpp index 35caf13b..6cd2b70d 100644 --- a/src/core/sessionthread.cpp +++ b/src/core/sessionthread.cpp @@ -26,82 +26,102 @@ #include "core.h" SessionThread::SessionThread(UserId uid, bool restoreState, QObject *parent) - : QThread(parent), + : QThread(parent), _session(0), _user(uid), _sessionInitialized(false), _restoreState(restoreState) { - connect(this, SIGNAL(initialized()), this, SLOT(setSessionInitialized())); + connect(this, SIGNAL(initialized()), this, SLOT(setSessionInitialized())); } -SessionThread::~SessionThread() { - // shut down thread gracefully - quit(); - wait(); -} -CoreSession *SessionThread::session() { - return _session; +SessionThread::~SessionThread() +{ + // shut down thread gracefully + quit(); + wait(); } -UserId SessionThread::user() { - return _user; -} -bool SessionThread::isSessionInitialized() { - return _sessionInitialized; +CoreSession *SessionThread::session() +{ + return _session; } -void SessionThread::setSessionInitialized() { - _sessionInitialized = true; - foreach(QObject *peer, clientQueue) { - addClientToSession(peer); - } - clientQueue.clear(); + +UserId SessionThread::user() +{ + return _user; } -void SessionThread::addClient(QObject *peer) { - if(isSessionInitialized()) { - addClientToSession(peer); - } else { - clientQueue.append(peer); - } + +bool SessionThread::isSessionInitialized() +{ + return _sessionInitialized; } -void SessionThread::addClientToSession(QObject *peer) { - QIODevice *socket = qobject_cast(peer); - if(socket) { - addRemoteClientToSession(socket); - return; - } - SignalProxy *proxy = qobject_cast(peer); - if(proxy) { - addInternalClientToSession(proxy); - return; - } +void SessionThread::setSessionInitialized() +{ + _sessionInitialized = true; + foreach(QObject *peer, clientQueue) { + addClientToSession(peer); + } + clientQueue.clear(); +} + - qWarning() << "SessionThread::addClient() received neither QIODevice nor SignalProxy as peer!" << peer; +void SessionThread::addClient(QObject *peer) +{ + if (isSessionInitialized()) { + addClientToSession(peer); + } + else { + clientQueue.append(peer); + } } -void SessionThread::addRemoteClientToSession(QIODevice *socket) { - socket->setParent(0); - socket->moveToThread(session()->thread()); - emit addRemoteClient(socket); + +void SessionThread::addClientToSession(QObject *peer) +{ + QIODevice *socket = qobject_cast(peer); + if (socket) { + addRemoteClientToSession(socket); + return; + } + + SignalProxy *proxy = qobject_cast(peer); + if (proxy) { + addInternalClientToSession(proxy); + return; + } + + qWarning() << "SessionThread::addClient() received neither QIODevice nor SignalProxy as peer!" << peer; } -void SessionThread::addInternalClientToSession(SignalProxy *proxy) { - emit addInternalClient(proxy); + +void SessionThread::addRemoteClientToSession(QIODevice *socket) +{ + socket->setParent(0); + socket->moveToThread(session()->thread()); + emit addRemoteClient(socket); } -void SessionThread::run() { - _session = new CoreSession(user(), _restoreState); - connect(this, SIGNAL(addRemoteClient(QIODevice *)), _session, SLOT(addClient(QIODevice *))); - connect(this, SIGNAL(addInternalClient(SignalProxy *)), _session, SLOT(addClient(SignalProxy *))); - connect(_session, SIGNAL(sessionState(const QVariant &)), Core::instance(), SIGNAL(sessionState(const QVariant &))); - emit initialized(); - exec(); - delete _session; + +void SessionThread::addInternalClientToSession(SignalProxy *proxy) +{ + emit addInternalClient(proxy); } + +void SessionThread::run() +{ + _session = new CoreSession(user(), _restoreState); + connect(this, SIGNAL(addRemoteClient(QIODevice *)), _session, SLOT(addClient(QIODevice *))); + connect(this, SIGNAL(addInternalClient(SignalProxy *)), _session, SLOT(addClient(SignalProxy *))); + connect(_session, SIGNAL(sessionState(const QVariant &)), Core::instance(), SIGNAL(sessionState(const QVariant &))); + emit initialized(); + exec(); + delete _session; +} diff --git a/src/core/sessionthread.h b/src/core/sessionthread.h index 810e8583..34c8ed67 100644 --- a/src/core/sessionthread.h +++ b/src/core/sessionthread.h @@ -30,42 +30,44 @@ class CoreSession; class QIODevice; class SignalProxy; -class SessionThread : public QThread { - Q_OBJECT +class SessionThread : public QThread +{ + Q_OBJECT public: - SessionThread(UserId user, bool restoreState, QObject *parent = 0); - ~SessionThread(); + SessionThread(UserId user, bool restoreState, QObject *parent = 0); + ~SessionThread(); - void run(); + void run(); - CoreSession *session(); - UserId user(); + CoreSession *session(); + UserId user(); public slots: - void addClient(QObject *peer); + void addClient(QObject *peer); private slots: - void setSessionInitialized(); + void setSessionInitialized(); signals: - void initialized(); - void shutdown(); + void initialized(); + void shutdown(); - void addRemoteClient(QIODevice *); - void addInternalClient(SignalProxy *); + void addRemoteClient(QIODevice *); + void addInternalClient(SignalProxy *); private: - CoreSession *_session; - UserId _user; - QList clientQueue; - bool _sessionInitialized; - bool _restoreState; - - bool isSessionInitialized(); - void addClientToSession(QObject *peer); - void addRemoteClientToSession(QIODevice *socket); - void addInternalClientToSession(SignalProxy *proxy); + CoreSession *_session; + UserId _user; + QList clientQueue; + bool _sessionInitialized; + bool _restoreState; + + bool isSessionInitialized(); + void addClientToSession(QObject *peer); + void addRemoteClientToSession(QIODevice *socket); + void addInternalClientToSession(SignalProxy *proxy); }; + #endif diff --git a/src/core/sqlitestorage.cpp b/src/core/sqlitestorage.cpp index 34852e9c..3b95cf01 100644 --- a/src/core/sqlitestorage.cpp +++ b/src/core/sqlitestorage.cpp @@ -29,1573 +29,1694 @@ int SqliteStorage::_maxRetryCount = 150; SqliteStorage::SqliteStorage(QObject *parent) - : AbstractSqlStorage(parent) + : AbstractSqlStorage(parent) { } -SqliteStorage::~SqliteStorage() { + +SqliteStorage::~SqliteStorage() +{ } -bool SqliteStorage::isAvailable() const { - if(!QSqlDatabase::isDriverAvailable("QSQLITE")) return false; - return true; + +bool SqliteStorage::isAvailable() const +{ + if (!QSqlDatabase::isDriverAvailable("QSQLITE")) return false; + return true; } -QString SqliteStorage::displayName() const { - // We identify the backend to use for the monolithic core by its displayname. - // so only change this string if you _really_ have to and make sure the core - // setup for the mono client still works ;) - return QString("SQLite"); + +QString SqliteStorage::displayName() const +{ + // We identify the backend to use for the monolithic core by its displayname. + // so only change this string if you _really_ have to and make sure the core + // setup for the mono client still works ;) + return QString("SQLite"); } -QString SqliteStorage::description() const { - return tr("SQLite is a file-based database engine that does not require any setup. It is suitable for small and medium-sized " - "databases that do not require access via network. Use SQLite if your Quassel Core should store its data on the same machine " - "it is running on, and if you only expect a few users to use your core."); + +QString SqliteStorage::description() const +{ + return tr("SQLite is a file-based database engine that does not require any setup. It is suitable for small and medium-sized " + "databases that do not require access via network. Use SQLite if your Quassel Core should store its data on the same machine " + "it is running on, and if you only expect a few users to use your core."); } -int SqliteStorage::installedSchemaVersion() { - // only used when there is a singlethread (during startup) - // so we don't need locking here - QSqlQuery query = logDb().exec("SELECT value FROM coreinfo WHERE key = 'schemaversion'"); - if(query.first()) - return query.value(0).toInt(); - // maybe it's really old... (schema version 0) - query = logDb().exec("SELECT MAX(version) FROM coreinfo"); - if(query.first()) - return query.value(0).toInt(); +int SqliteStorage::installedSchemaVersion() +{ + // only used when there is a singlethread (during startup) + // so we don't need locking here + QSqlQuery query = logDb().exec("SELECT value FROM coreinfo WHERE key = 'schemaversion'"); + if (query.first()) + return query.value(0).toInt(); + + // maybe it's really old... (schema version 0) + query = logDb().exec("SELECT MAX(version) FROM coreinfo"); + if (query.first()) + return query.value(0).toInt(); - return AbstractSqlStorage::installedSchemaVersion(); + return AbstractSqlStorage::installedSchemaVersion(); } -bool SqliteStorage::updateSchemaVersion(int newVersion) { - // only used when there is a singlethread (during startup) - // so we don't need locking here - QSqlQuery query(logDb()); - query.prepare("UPDATE coreinfo SET value = :version WHERE key = 'schemaversion'"); - query.bindValue(":version", newVersion); - query.exec(); - bool success = true; - if(query.lastError().isValid()) { - qCritical() << "SqliteStorage::updateSchemaVersion(int): Updating schema version failed!"; - success = false; - } - return success; +bool SqliteStorage::updateSchemaVersion(int newVersion) +{ + // only used when there is a singlethread (during startup) + // so we don't need locking here + QSqlQuery query(logDb()); + query.prepare("UPDATE coreinfo SET value = :version WHERE key = 'schemaversion'"); + query.bindValue(":version", newVersion); + query.exec(); + + bool success = true; + if (query.lastError().isValid()) { + qCritical() << "SqliteStorage::updateSchemaVersion(int): Updating schema version failed!"; + success = false; + } + return success; } -bool SqliteStorage::setupSchemaVersion(int version) { - // only used when there is a singlethread (during startup) - // so we don't need locking here - QSqlQuery query(logDb()); - query.prepare("INSERT INTO coreinfo (key, value) VALUES ('schemaversion', :version)"); - query.bindValue(":version", version); - query.exec(); - bool success = true; - if(query.lastError().isValid()) { - qCritical() << "SqliteStorage::setupSchemaVersion(int): Updating schema version failed!"; - success = false; - } - return success; +bool SqliteStorage::setupSchemaVersion(int version) +{ + // only used when there is a singlethread (during startup) + // so we don't need locking here + QSqlQuery query(logDb()); + query.prepare("INSERT INTO coreinfo (key, value) VALUES ('schemaversion', :version)"); + query.bindValue(":version", version); + query.exec(); + + bool success = true; + if (query.lastError().isValid()) { + qCritical() << "SqliteStorage::setupSchemaVersion(int): Updating schema version failed!"; + success = false; + } + return success; } -UserId SqliteStorage::addUser(const QString &user, const QString &password) { - QSqlDatabase db = logDb(); - UserId uid; - db.transaction(); - // this scope ensures that the query is freed in sqlite before we call unlock() - // this ensures that our thread doesn't hold a internal after unlock is called - // (see sqlites doc on implicit locking for details) - { - QSqlQuery query(db); - query.prepare(queryString("insert_quasseluser")); - query.bindValue(":username", user); - query.bindValue(":password", cryptedPassword(password)); - lockForWrite(); - safeExec(query); - if(query.lastError().isValid() && query.lastError().number() == 19) { // user already exists - sadly 19 seems to be the general constraint violation error... - db.rollback(); - } else { - uid = query.lastInsertId().toInt(); - db.commit(); - } - } - unlock(); - - if(uid.isValid()) - emit userAdded(uid, user); - return uid; -} - -bool SqliteStorage::updateUser(UserId user, const QString &password) { - QSqlDatabase db = logDb(); - bool success = false; - - db.transaction(); - { - QSqlQuery query(db); - query.prepare(queryString("update_userpassword")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":password", cryptedPassword(password)); - lockForWrite(); - safeExec(query); - success = query.numRowsAffected() != 0; - db.commit(); - } - unlock(); - return success; -} - -void SqliteStorage::renameUser(UserId user, const QString &newName) { - QSqlDatabase db = logDb(); - db.transaction(); - { - QSqlQuery query(db); - query.prepare(queryString("update_username")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":username", newName); - lockForWrite(); - safeExec(query); - db.commit(); - } - unlock(); - emit userRenamed(user, newName); +UserId SqliteStorage::addUser(const QString &user, const QString &password) +{ + QSqlDatabase db = logDb(); + UserId uid; + + db.transaction(); + // this scope ensures that the query is freed in sqlite before we call unlock() + // this ensures that our thread doesn't hold a internal after unlock is called + // (see sqlites doc on implicit locking for details) + { + QSqlQuery query(db); + query.prepare(queryString("insert_quasseluser")); + query.bindValue(":username", user); + query.bindValue(":password", cryptedPassword(password)); + lockForWrite(); + safeExec(query); + if (query.lastError().isValid() && query.lastError().number() == 19) { // user already exists - sadly 19 seems to be the general constraint violation error... + db.rollback(); + } + else { + uid = query.lastInsertId().toInt(); + db.commit(); + } + } + unlock(); + + if (uid.isValid()) + emit userAdded(uid, user); + return uid; } -UserId SqliteStorage::validateUser(const QString &user, const QString &password) { - UserId userId; - { - QSqlQuery query(logDb()); - query.prepare(queryString("select_authuser")); - query.bindValue(":username", user); - query.bindValue(":password", cryptedPassword(password)); +bool SqliteStorage::updateUser(UserId user, const QString &password) +{ + QSqlDatabase db = logDb(); + bool success = false; + + db.transaction(); + { + QSqlQuery query(db); + query.prepare(queryString("update_userpassword")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":password", cryptedPassword(password)); + lockForWrite(); + safeExec(query); + success = query.numRowsAffected() != 0; + db.commit(); + } + unlock(); + return success; +} - lockForRead(); - safeExec(query); - if(query.first()) { - userId = query.value(0).toInt(); +void SqliteStorage::renameUser(UserId user, const QString &newName) +{ + QSqlDatabase db = logDb(); + db.transaction(); + { + QSqlQuery query(db); + query.prepare(queryString("update_username")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":username", newName); + lockForWrite(); + safeExec(query); + db.commit(); } - } - unlock(); - - return userId; + unlock(); + emit userRenamed(user, newName); } -UserId SqliteStorage::getUserId(const QString &username) { - UserId userId; - { - QSqlQuery query(logDb()); - query.prepare(queryString("select_userid")); - query.bindValue(":username", username); +UserId SqliteStorage::validateUser(const QString &user, const QString &password) +{ + UserId userId; - lockForRead(); - safeExec(query); + { + QSqlQuery query(logDb()); + query.prepare(queryString("select_authuser")); + query.bindValue(":username", user); + query.bindValue(":password", cryptedPassword(password)); - if(query.first()) { - userId = query.value(0).toInt(); + lockForRead(); + safeExec(query); + + if (query.first()) { + userId = query.value(0).toInt(); + } } - } - unlock(); + unlock(); - return userId; + return userId; } -UserId SqliteStorage::internalUser() { - UserId userId; - { - QSqlQuery query(logDb()); - query.prepare(queryString("select_internaluser")); - lockForRead(); - safeExec(query); +UserId SqliteStorage::getUserId(const QString &username) +{ + UserId userId; + + { + QSqlQuery query(logDb()); + query.prepare(queryString("select_userid")); + query.bindValue(":username", username); + + lockForRead(); + safeExec(query); - if(query.first()) { - userId = query.value(0).toInt(); + if (query.first()) { + userId = query.value(0).toInt(); + } } - } - unlock(); + unlock(); - return userId; + return userId; } -void SqliteStorage::delUser(UserId user) { - QSqlDatabase db = logDb(); - db.transaction(); - lockForWrite(); - { - QSqlQuery query(db); - query.prepare(queryString("delete_backlog_by_uid")); - query.bindValue(":userid", user.toInt()); - safeExec(query); +UserId SqliteStorage::internalUser() +{ + UserId userId; - query.prepare(queryString("delete_buffers_by_uid")); - query.bindValue(":userid", user.toInt()); - safeExec(query); + { + QSqlQuery query(logDb()); + query.prepare(queryString("select_internaluser")); + lockForRead(); + safeExec(query); - query.prepare(queryString("delete_networks_by_uid")); - query.bindValue(":userid", user.toInt()); - safeExec(query); + if (query.first()) { + userId = query.value(0).toInt(); + } + } + unlock(); + + return userId; +} + + +void SqliteStorage::delUser(UserId user) +{ + QSqlDatabase db = logDb(); + db.transaction(); - query.prepare(queryString("delete_quasseluser")); - query.bindValue(":userid", user.toInt()); - safeExec(query); - // I hate the lack of foreign keys and on delete cascade... :( - db.commit(); - } - unlock(); - - emit userRemoved(user); -} - -void SqliteStorage::setUserSetting(UserId userId, const QString &settingName, const QVariant &data) { - QByteArray rawData; - QDataStream out(&rawData, QIODevice::WriteOnly); - out.setVersion(QDataStream::Qt_4_2); - out << data; - - QSqlDatabase db = logDb(); - db.transaction(); - { - QSqlQuery query(db); - query.prepare(queryString("insert_user_setting")); - query.bindValue(":userid", userId.toInt()); - query.bindValue(":settingname", settingName); - query.bindValue(":settingvalue", rawData); lockForWrite(); - safeExec(query); + { + QSqlQuery query(db); + query.prepare(queryString("delete_backlog_by_uid")); + query.bindValue(":userid", user.toInt()); + safeExec(query); + + query.prepare(queryString("delete_buffers_by_uid")); + query.bindValue(":userid", user.toInt()); + safeExec(query); + + query.prepare(queryString("delete_networks_by_uid")); + query.bindValue(":userid", user.toInt()); + safeExec(query); + + query.prepare(queryString("delete_quasseluser")); + query.bindValue(":userid", user.toInt()); + safeExec(query); + // I hate the lack of foreign keys and on delete cascade... :( + db.commit(); + } + unlock(); + + emit userRemoved(user); +} - if(query.lastError().isValid()) { - QSqlQuery updateQuery(db); - updateQuery.prepare(queryString("update_user_setting")); - updateQuery.bindValue(":userid", userId.toInt()); - updateQuery.bindValue(":settingname", settingName); - updateQuery.bindValue(":settingvalue", rawData); - safeExec(updateQuery); + +void SqliteStorage::setUserSetting(UserId userId, const QString &settingName, const QVariant &data) +{ + QByteArray rawData; + QDataStream out(&rawData, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_2); + out << data; + + QSqlDatabase db = logDb(); + db.transaction(); + { + QSqlQuery query(db); + query.prepare(queryString("insert_user_setting")); + query.bindValue(":userid", userId.toInt()); + query.bindValue(":settingname", settingName); + query.bindValue(":settingvalue", rawData); + lockForWrite(); + safeExec(query); + + if (query.lastError().isValid()) { + QSqlQuery updateQuery(db); + updateQuery.prepare(queryString("update_user_setting")); + updateQuery.bindValue(":userid", userId.toInt()); + updateQuery.bindValue(":settingname", settingName); + updateQuery.bindValue(":settingvalue", rawData); + safeExec(updateQuery); + } + db.commit(); } - db.commit(); - } - unlock(); + unlock(); } -QVariant SqliteStorage::getUserSetting(UserId userId, const QString &settingName, const QVariant &defaultData) { - QVariant data = defaultData; - { - QSqlQuery query(logDb()); - query.prepare(queryString("select_user_setting")); - query.bindValue(":userid", userId.toInt()); - query.bindValue(":settingname", settingName); - lockForRead(); - safeExec(query); - - if(query.first()) { - QByteArray rawData = query.value(0).toByteArray(); - QDataStream in(&rawData, QIODevice::ReadOnly); - in.setVersion(QDataStream::Qt_4_2); - in >> data; - } - } - unlock(); - return data; -} - -IdentityId SqliteStorage::createIdentity(UserId user, CoreIdentity &identity) { - IdentityId identityId; - - QSqlDatabase db = logDb(); - db.transaction(); - - { - QSqlQuery query(db); - query.prepare(queryString("insert_identity")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":identityname", identity.identityName()); - query.bindValue(":realname", identity.realName()); - query.bindValue(":awaynick", identity.awayNick()); - query.bindValue(":awaynickenabled", identity.awayNickEnabled() ? 1 : 0); - query.bindValue(":awayreason", identity.awayReason()); - query.bindValue(":awayreasonenabled", identity.awayReasonEnabled() ? 1 : 0); - query.bindValue(":autoawayenabled", identity.awayReasonEnabled() ? 1 : 0); - query.bindValue(":autoawaytime", identity.autoAwayTime()); - query.bindValue(":autoawayreason", identity.autoAwayReason()); - query.bindValue(":autoawayreasonenabled", identity.autoAwayReasonEnabled() ? 1 : 0); - query.bindValue(":detachawayenabled", identity.detachAwayEnabled() ? 1 : 0); - query.bindValue(":detachawayreason", identity.detachAwayReason()); - query.bindValue(":detachawayreasonenabled", identity.detachAwayReasonEnabled() ? 1 : 0); - query.bindValue(":ident", identity.ident()); - query.bindValue(":kickreason", identity.kickReason()); - query.bindValue(":partreason", identity.partReason()); - query.bindValue(":quitreason", identity.quitReason()); + +QVariant SqliteStorage::getUserSetting(UserId userId, const QString &settingName, const QVariant &defaultData) +{ + QVariant data = defaultData; + { + QSqlQuery query(logDb()); + query.prepare(queryString("select_user_setting")); + query.bindValue(":userid", userId.toInt()); + query.bindValue(":settingname", settingName); + lockForRead(); + safeExec(query); + + if (query.first()) { + QByteArray rawData = query.value(0).toByteArray(); + QDataStream in(&rawData, QIODevice::ReadOnly); + in.setVersion(QDataStream::Qt_4_2); + in >> data; + } + } + unlock(); + return data; +} + + +IdentityId SqliteStorage::createIdentity(UserId user, CoreIdentity &identity) +{ + IdentityId identityId; + + QSqlDatabase db = logDb(); + db.transaction(); + + { + QSqlQuery query(db); + query.prepare(queryString("insert_identity")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":identityname", identity.identityName()); + query.bindValue(":realname", identity.realName()); + query.bindValue(":awaynick", identity.awayNick()); + query.bindValue(":awaynickenabled", identity.awayNickEnabled() ? 1 : 0); + query.bindValue(":awayreason", identity.awayReason()); + query.bindValue(":awayreasonenabled", identity.awayReasonEnabled() ? 1 : 0); + query.bindValue(":autoawayenabled", identity.awayReasonEnabled() ? 1 : 0); + query.bindValue(":autoawaytime", identity.autoAwayTime()); + query.bindValue(":autoawayreason", identity.autoAwayReason()); + query.bindValue(":autoawayreasonenabled", identity.autoAwayReasonEnabled() ? 1 : 0); + query.bindValue(":detachawayenabled", identity.detachAwayEnabled() ? 1 : 0); + query.bindValue(":detachawayreason", identity.detachAwayReason()); + query.bindValue(":detachawayreasonenabled", identity.detachAwayReasonEnabled() ? 1 : 0); + query.bindValue(":ident", identity.ident()); + query.bindValue(":kickreason", identity.kickReason()); + query.bindValue(":partreason", identity.partReason()); + query.bindValue(":quitreason", identity.quitReason()); #ifdef HAVE_SSL - query.bindValue(":sslcert", identity.sslCert().toPem()); - query.bindValue(":sslkey", identity.sslKey().toPem()); + query.bindValue(":sslcert", identity.sslCert().toPem()); + query.bindValue(":sslkey", identity.sslKey().toPem()); #else - query.bindValue(":sslcert", QByteArray()); - query.bindValue(":sslkey", QByteArray()); + query.bindValue(":sslcert", QByteArray()); + query.bindValue(":sslkey", QByteArray()); #endif - lockForWrite(); - safeExec(query); - - identityId = query.lastInsertId().toInt(); - if(!identityId.isValid()) { - watchQuery(query); - } else { - QSqlQuery deleteNickQuery(db); - deleteNickQuery.prepare(queryString("delete_nicks")); - deleteNickQuery.bindValue(":identityid", identityId.toInt()); - safeExec(deleteNickQuery); - - QSqlQuery insertNickQuery(db); - insertNickQuery.prepare(queryString("insert_nick")); - foreach(QString nick, identity.nicks()) { - insertNickQuery.bindValue(":identityid", identityId.toInt()); - insertNickQuery.bindValue(":nick", nick); - safeExec(insertNickQuery); - } + lockForWrite(); + safeExec(query); + + identityId = query.lastInsertId().toInt(); + if (!identityId.isValid()) { + watchQuery(query); + } + else { + QSqlQuery deleteNickQuery(db); + deleteNickQuery.prepare(queryString("delete_nicks")); + deleteNickQuery.bindValue(":identityid", identityId.toInt()); + safeExec(deleteNickQuery); + + QSqlQuery insertNickQuery(db); + insertNickQuery.prepare(queryString("insert_nick")); + foreach(QString nick, identity.nicks()) { + insertNickQuery.bindValue(":identityid", identityId.toInt()); + insertNickQuery.bindValue(":nick", nick); + safeExec(insertNickQuery); + } + } + db.commit(); } - db.commit(); - } - unlock(); - identity.setId(identityId); - return identityId; -} - -bool SqliteStorage::updateIdentity(UserId user, const CoreIdentity &identity) { - QSqlDatabase db = logDb(); - bool error = false; - db.transaction(); - - { - QSqlQuery checkQuery(db); - checkQuery.prepare(queryString("select_checkidentity")); - checkQuery.bindValue(":identityid", identity.id().toInt()); - checkQuery.bindValue(":userid", user.toInt()); - lockForRead(); - safeExec(checkQuery); - - // there should be exactly one identity for the given id and user - error = (!checkQuery.first() || checkQuery.value(0).toInt() != 1); - } - if(error) { unlock(); - return false; - } - - { - QSqlQuery query(db); - query.prepare(queryString("update_identity")); - query.bindValue(":identityname", identity.identityName()); - query.bindValue(":realname", identity.realName()); - query.bindValue(":awaynick", identity.awayNick()); - query.bindValue(":awaynickenabled", identity.awayNickEnabled() ? 1 : 0); - query.bindValue(":awayreason", identity.awayReason()); - query.bindValue(":awayreasonenabled", identity.awayReasonEnabled() ? 1 : 0); - query.bindValue(":autoawayenabled", identity.awayReasonEnabled() ? 1 : 0); - query.bindValue(":autoawaytime", identity.autoAwayTime()); - query.bindValue(":autoawayreason", identity.autoAwayReason()); - query.bindValue(":autoawayreasonenabled", identity.autoAwayReasonEnabled() ? 1 : 0); - query.bindValue(":detachawayenabled", identity.detachAwayEnabled() ? 1 : 0); - query.bindValue(":detachawayreason", identity.detachAwayReason()); - query.bindValue(":detachawayreasonenabled", identity.detachAwayReasonEnabled() ? 1 : 0); - query.bindValue(":ident", identity.ident()); - query.bindValue(":kickreason", identity.kickReason()); - query.bindValue(":partreason", identity.partReason()); - query.bindValue(":quitreason", identity.quitReason()); + identity.setId(identityId); + return identityId; +} + + +bool SqliteStorage::updateIdentity(UserId user, const CoreIdentity &identity) +{ + QSqlDatabase db = logDb(); + bool error = false; + db.transaction(); + + { + QSqlQuery checkQuery(db); + checkQuery.prepare(queryString("select_checkidentity")); + checkQuery.bindValue(":identityid", identity.id().toInt()); + checkQuery.bindValue(":userid", user.toInt()); + lockForRead(); + safeExec(checkQuery); + + // there should be exactly one identity for the given id and user + error = (!checkQuery.first() || checkQuery.value(0).toInt() != 1); + } + if (error) { + unlock(); + return false; + } + + { + QSqlQuery query(db); + query.prepare(queryString("update_identity")); + query.bindValue(":identityname", identity.identityName()); + query.bindValue(":realname", identity.realName()); + query.bindValue(":awaynick", identity.awayNick()); + query.bindValue(":awaynickenabled", identity.awayNickEnabled() ? 1 : 0); + query.bindValue(":awayreason", identity.awayReason()); + query.bindValue(":awayreasonenabled", identity.awayReasonEnabled() ? 1 : 0); + query.bindValue(":autoawayenabled", identity.awayReasonEnabled() ? 1 : 0); + query.bindValue(":autoawaytime", identity.autoAwayTime()); + query.bindValue(":autoawayreason", identity.autoAwayReason()); + query.bindValue(":autoawayreasonenabled", identity.autoAwayReasonEnabled() ? 1 : 0); + query.bindValue(":detachawayenabled", identity.detachAwayEnabled() ? 1 : 0); + query.bindValue(":detachawayreason", identity.detachAwayReason()); + query.bindValue(":detachawayreasonenabled", identity.detachAwayReasonEnabled() ? 1 : 0); + query.bindValue(":ident", identity.ident()); + query.bindValue(":kickreason", identity.kickReason()); + query.bindValue(":partreason", identity.partReason()); + query.bindValue(":quitreason", identity.quitReason()); #ifdef HAVE_SSL - query.bindValue(":sslcert", identity.sslCert().toPem()); - query.bindValue(":sslkey", identity.sslKey().toPem()); + query.bindValue(":sslcert", identity.sslCert().toPem()); + query.bindValue(":sslkey", identity.sslKey().toPem()); #else - query.bindValue(":sslcert", QByteArray()); - query.bindValue(":sslkey", QByteArray()); + query.bindValue(":sslcert", QByteArray()); + query.bindValue(":sslkey", QByteArray()); #endif - query.bindValue(":identityid", identity.id().toInt()); - safeExec(query); - watchQuery(query); - - QSqlQuery deleteNickQuery(db); - deleteNickQuery.prepare(queryString("delete_nicks")); - deleteNickQuery.bindValue(":identityid", identity.id().toInt()); - safeExec(deleteNickQuery); - watchQuery(deleteNickQuery); - - QSqlQuery insertNickQuery(db); - insertNickQuery.prepare(queryString("insert_nick")); - foreach(QString nick, identity.nicks()) { - insertNickQuery.bindValue(":identityid", identity.id().toInt()); - insertNickQuery.bindValue(":nick", nick); - safeExec(insertNickQuery); - watchQuery(insertNickQuery); + query.bindValue(":identityid", identity.id().toInt()); + safeExec(query); + watchQuery(query); + + QSqlQuery deleteNickQuery(db); + deleteNickQuery.prepare(queryString("delete_nicks")); + deleteNickQuery.bindValue(":identityid", identity.id().toInt()); + safeExec(deleteNickQuery); + watchQuery(deleteNickQuery); + + QSqlQuery insertNickQuery(db); + insertNickQuery.prepare(queryString("insert_nick")); + foreach(QString nick, identity.nicks()) { + insertNickQuery.bindValue(":identityid", identity.id().toInt()); + insertNickQuery.bindValue(":nick", nick); + safeExec(insertNickQuery); + watchQuery(insertNickQuery); + } + db.commit(); } - db.commit(); - } - unlock(); - return true; -} - -void SqliteStorage::removeIdentity(UserId user, IdentityId identityId) { - QSqlDatabase db = logDb(); - db.transaction(); - - bool error = false; - { - QSqlQuery checkQuery(db); - checkQuery.prepare(queryString("select_checkidentity")); - checkQuery.bindValue(":identityid", identityId.toInt()); - checkQuery.bindValue(":userid", user.toInt()); - lockForRead(); - safeExec(checkQuery); - - // there should be exactly one identity for the given id and user - error = (!checkQuery.first() || checkQuery.value(0).toInt() != 1); - } - if(error) { unlock(); - return; - } - - { - QSqlQuery deleteNickQuery(db); - deleteNickQuery.prepare(queryString("delete_nicks")); - deleteNickQuery.bindValue(":identityid", identityId.toInt()); - safeExec(deleteNickQuery); - - QSqlQuery deleteIdentityQuery(db); - deleteIdentityQuery.prepare(queryString("delete_identity")); - deleteIdentityQuery.bindValue(":identityid", identityId.toInt()); - deleteIdentityQuery.bindValue(":userid", user.toInt()); - safeExec(deleteIdentityQuery); - db.commit(); - } - unlock(); -} - -QList SqliteStorage::identities(UserId user) { - QList identities; - QSqlDatabase db = logDb(); - db.transaction(); - - { - QSqlQuery query(db); - query.prepare(queryString("select_identities")); - query.bindValue(":userid", user.toInt()); - - QSqlQuery nickQuery(db); - nickQuery.prepare(queryString("select_nicks")); - - lockForRead(); - safeExec(query); - - while(query.next()) { - CoreIdentity identity(IdentityId(query.value(0).toInt())); - - identity.setIdentityName(query.value(1).toString()); - identity.setRealName(query.value(2).toString()); - identity.setAwayNick(query.value(3).toString()); - identity.setAwayNickEnabled(!!query.value(4).toInt()); - identity.setAwayReason(query.value(5).toString()); - identity.setAwayReasonEnabled(!!query.value(6).toInt()); - identity.setAutoAwayEnabled(!!query.value(7).toInt()); - identity.setAutoAwayTime(query.value(8).toInt()); - identity.setAutoAwayReason(query.value(9).toString()); - identity.setAutoAwayReasonEnabled(!!query.value(10).toInt()); - identity.setDetachAwayEnabled(!!query.value(11).toInt()); - identity.setDetachAwayReason(query.value(12).toString()); - identity.setDetachAwayReasonEnabled(!!query.value(13).toInt()); - identity.setIdent(query.value(14).toString()); - identity.setKickReason(query.value(15).toString()); - identity.setPartReason(query.value(16).toString()); - identity.setQuitReason(query.value(17).toString()); -#ifdef HAVE_SSL - identity.setSslCert(query.value(18).toByteArray()); - identity.setSslKey(query.value(19).toByteArray()); -#endif + return true; +} - nickQuery.bindValue(":identityid", identity.id().toInt()); - QList nicks; - safeExec(nickQuery); - watchQuery(nickQuery); - while(nickQuery.next()) { - nicks << nickQuery.value(0).toString(); - } - identity.setNicks(nicks); - identities << identity; + +void SqliteStorage::removeIdentity(UserId user, IdentityId identityId) +{ + QSqlDatabase db = logDb(); + db.transaction(); + + bool error = false; + { + QSqlQuery checkQuery(db); + checkQuery.prepare(queryString("select_checkidentity")); + checkQuery.bindValue(":identityid", identityId.toInt()); + checkQuery.bindValue(":userid", user.toInt()); + lockForRead(); + safeExec(checkQuery); + + // there should be exactly one identity for the given id and user + error = (!checkQuery.first() || checkQuery.value(0).toInt() != 1); } - db.commit(); - } - unlock(); - return identities; + if (error) { + unlock(); + return; + } + + { + QSqlQuery deleteNickQuery(db); + deleteNickQuery.prepare(queryString("delete_nicks")); + deleteNickQuery.bindValue(":identityid", identityId.toInt()); + safeExec(deleteNickQuery); + + QSqlQuery deleteIdentityQuery(db); + deleteIdentityQuery.prepare(queryString("delete_identity")); + deleteIdentityQuery.bindValue(":identityid", identityId.toInt()); + deleteIdentityQuery.bindValue(":userid", user.toInt()); + safeExec(deleteIdentityQuery); + db.commit(); + } + unlock(); } -NetworkId SqliteStorage::createNetwork(UserId user, const NetworkInfo &info) { - NetworkId networkId; - QSqlDatabase db = logDb(); - db.transaction(); +QList SqliteStorage::identities(UserId user) +{ + QList identities; + QSqlDatabase db = logDb(); + db.transaction(); + + { + QSqlQuery query(db); + query.prepare(queryString("select_identities")); + query.bindValue(":userid", user.toInt()); + + QSqlQuery nickQuery(db); + nickQuery.prepare(queryString("select_nicks")); + + lockForRead(); + safeExec(query); + + while (query.next()) { + CoreIdentity identity(IdentityId(query.value(0).toInt())); + + identity.setIdentityName(query.value(1).toString()); + identity.setRealName(query.value(2).toString()); + identity.setAwayNick(query.value(3).toString()); + identity.setAwayNickEnabled(!!query.value(4).toInt()); + identity.setAwayReason(query.value(5).toString()); + identity.setAwayReasonEnabled(!!query.value(6).toInt()); + identity.setAutoAwayEnabled(!!query.value(7).toInt()); + identity.setAutoAwayTime(query.value(8).toInt()); + identity.setAutoAwayReason(query.value(9).toString()); + identity.setAutoAwayReasonEnabled(!!query.value(10).toInt()); + identity.setDetachAwayEnabled(!!query.value(11).toInt()); + identity.setDetachAwayReason(query.value(12).toString()); + identity.setDetachAwayReasonEnabled(!!query.value(13).toInt()); + identity.setIdent(query.value(14).toString()); + identity.setKickReason(query.value(15).toString()); + identity.setPartReason(query.value(16).toString()); + identity.setQuitReason(query.value(17).toString()); +#ifdef HAVE_SSL + identity.setSslCert(query.value(18).toByteArray()); + identity.setSslKey(query.value(19).toByteArray()); +#endif - bool error = false; - { - QSqlQuery query(db); - query.prepare(queryString("insert_network")); - query.bindValue(":userid", user.toInt()); - bindNetworkInfo(query, info); - lockForWrite(); - safeExec(query); - if(!watchQuery(query)) { - db.rollback(); - error = true; - } else { - networkId = query.lastInsertId().toInt(); - } - } - if(error) { + nickQuery.bindValue(":identityid", identity.id().toInt()); + QList nicks; + safeExec(nickQuery); + watchQuery(nickQuery); + while (nickQuery.next()) { + nicks << nickQuery.value(0).toString(); + } + identity.setNicks(nicks); + identities << identity; + } + db.commit(); + } unlock(); - return NetworkId(); - } - - { - QSqlQuery insertServersQuery(db); - insertServersQuery.prepare(queryString("insert_server")); - foreach(Network::Server server, info.serverList) { - insertServersQuery.bindValue(":userid", user.toInt()); - insertServersQuery.bindValue(":networkid", networkId.toInt()); - bindServerInfo(insertServersQuery, server); - safeExec(insertServersQuery); - if(!watchQuery(insertServersQuery)) { - db.rollback(); - error = true; - break; - } - } - if(!error) - db.commit(); - } - unlock(); - if(error) - return NetworkId(); - else - return networkId; -} - -void SqliteStorage::bindNetworkInfo(QSqlQuery &query, const NetworkInfo &info) { - query.bindValue(":networkname", info.networkName); - query.bindValue(":identityid", info.identity.toInt()); - query.bindValue(":encodingcodec", QString(info.codecForEncoding)); - query.bindValue(":decodingcodec", QString(info.codecForDecoding)); - query.bindValue(":servercodec", QString(info.codecForServer)); - query.bindValue(":userandomserver", info.useRandomServer ? 1 : 0); - query.bindValue(":perform", info.perform.join("\n")); - query.bindValue(":useautoidentify", info.useAutoIdentify ? 1 : 0); - query.bindValue(":autoidentifyservice", info.autoIdentifyService); - query.bindValue(":autoidentifypassword", info.autoIdentifyPassword); - query.bindValue(":usesasl", info.useSasl ? 1 : 0); - query.bindValue(":saslaccount", info.saslAccount); - query.bindValue(":saslpassword", info.saslPassword); - query.bindValue(":useautoreconnect", info.useAutoReconnect ? 1 : 0); - query.bindValue(":autoreconnectinterval", info.autoReconnectInterval); - query.bindValue(":autoreconnectretries", info.autoReconnectRetries); - query.bindValue(":unlimitedconnectretries", info.unlimitedReconnectRetries ? 1 : 0); - query.bindValue(":rejoinchannels", info.rejoinChannels ? 1 : 0); - if(info.networkId.isValid()) - query.bindValue(":networkid", info.networkId.toInt()); -} - -void SqliteStorage::bindServerInfo(QSqlQuery &query, const Network::Server &server) { - query.bindValue(":hostname", server.host); - query.bindValue(":port", server.port); - query.bindValue(":password", server.password); - query.bindValue(":ssl", server.useSsl ? 1 : 0); - query.bindValue(":sslversion", server.sslVersion); - query.bindValue(":useproxy", server.useProxy ? 1 : 0); - query.bindValue(":proxytype", server.proxyType); - query.bindValue(":proxyhost", server.proxyHost); - query.bindValue(":proxyport", server.proxyPort); - query.bindValue(":proxyuser", server.proxyUser); - query.bindValue(":proxypass", server.proxyPass); -} - -bool SqliteStorage::updateNetwork(UserId user, const NetworkInfo &info) { - QSqlDatabase db = logDb(); - bool error = false; - db.transaction(); - - { - QSqlQuery updateQuery(db); - updateQuery.prepare(queryString("update_network")); - updateQuery.bindValue(":userid", user.toInt()); - bindNetworkInfo(updateQuery, info); + return identities; +} - lockForWrite(); - safeExec(updateQuery); - if(!watchQuery(updateQuery) || updateQuery.numRowsAffected() != 1) { - error = true; - db.rollback(); + +NetworkId SqliteStorage::createNetwork(UserId user, const NetworkInfo &info) +{ + NetworkId networkId; + + QSqlDatabase db = logDb(); + db.transaction(); + + bool error = false; + { + QSqlQuery query(db); + query.prepare(queryString("insert_network")); + query.bindValue(":userid", user.toInt()); + bindNetworkInfo(query, info); + lockForWrite(); + safeExec(query); + if (!watchQuery(query)) { + db.rollback(); + error = true; + } + else { + networkId = query.lastInsertId().toInt(); + } } - } - if(error) { - unlock(); - return false; - } - - { - QSqlQuery dropServersQuery(db); - dropServersQuery.prepare("DELETE FROM ircserver WHERE networkid = :networkid"); - dropServersQuery.bindValue(":networkid", info.networkId.toInt()); - safeExec(dropServersQuery); - if(!watchQuery(dropServersQuery)) { - error = true; - db.rollback(); - } - } - if(error) { - unlock(); - return false; - } - - { - QSqlQuery insertServersQuery(db); - insertServersQuery.prepare(queryString("insert_server")); - foreach(Network::Server server, info.serverList) { - insertServersQuery.bindValue(":userid", user.toInt()); - insertServersQuery.bindValue(":networkid", info.networkId.toInt()); - bindServerInfo(insertServersQuery, server); - safeExec(insertServersQuery); - if(!watchQuery(insertServersQuery)) { - error = true; - db.rollback(); - break; - } + if (error) { + unlock(); + return NetworkId(); } - } - db.commit(); - unlock(); - return !error; + { + QSqlQuery insertServersQuery(db); + insertServersQuery.prepare(queryString("insert_server")); + foreach(Network::Server server, info.serverList) { + insertServersQuery.bindValue(":userid", user.toInt()); + insertServersQuery.bindValue(":networkid", networkId.toInt()); + bindServerInfo(insertServersQuery, server); + safeExec(insertServersQuery); + if (!watchQuery(insertServersQuery)) { + db.rollback(); + error = true; + break; + } + } + if (!error) + db.commit(); + } + unlock(); + if (error) + return NetworkId(); + else + return networkId; } -bool SqliteStorage::removeNetwork(UserId user, const NetworkId &networkId) { - QSqlDatabase db = logDb(); - bool error = false; - db.transaction(); - { - QSqlQuery deleteNetworkQuery(db); - deleteNetworkQuery.prepare(queryString("delete_network")); - deleteNetworkQuery.bindValue(":networkid", networkId.toInt()); - deleteNetworkQuery.bindValue(":userid", user.toInt()); - lockForWrite(); - safeExec(deleteNetworkQuery); - if(!watchQuery(deleteNetworkQuery) || deleteNetworkQuery.numRowsAffected() != 1) { - error = true; - db.rollback(); +void SqliteStorage::bindNetworkInfo(QSqlQuery &query, const NetworkInfo &info) +{ + query.bindValue(":networkname", info.networkName); + query.bindValue(":identityid", info.identity.toInt()); + query.bindValue(":encodingcodec", QString(info.codecForEncoding)); + query.bindValue(":decodingcodec", QString(info.codecForDecoding)); + query.bindValue(":servercodec", QString(info.codecForServer)); + query.bindValue(":userandomserver", info.useRandomServer ? 1 : 0); + query.bindValue(":perform", info.perform.join("\n")); + query.bindValue(":useautoidentify", info.useAutoIdentify ? 1 : 0); + query.bindValue(":autoidentifyservice", info.autoIdentifyService); + query.bindValue(":autoidentifypassword", info.autoIdentifyPassword); + query.bindValue(":usesasl", info.useSasl ? 1 : 0); + query.bindValue(":saslaccount", info.saslAccount); + query.bindValue(":saslpassword", info.saslPassword); + query.bindValue(":useautoreconnect", info.useAutoReconnect ? 1 : 0); + query.bindValue(":autoreconnectinterval", info.autoReconnectInterval); + query.bindValue(":autoreconnectretries", info.autoReconnectRetries); + query.bindValue(":unlimitedconnectretries", info.unlimitedReconnectRetries ? 1 : 0); + query.bindValue(":rejoinchannels", info.rejoinChannels ? 1 : 0); + if (info.networkId.isValid()) + query.bindValue(":networkid", info.networkId.toInt()); +} + + +void SqliteStorage::bindServerInfo(QSqlQuery &query, const Network::Server &server) +{ + query.bindValue(":hostname", server.host); + query.bindValue(":port", server.port); + query.bindValue(":password", server.password); + query.bindValue(":ssl", server.useSsl ? 1 : 0); + query.bindValue(":sslversion", server.sslVersion); + query.bindValue(":useproxy", server.useProxy ? 1 : 0); + query.bindValue(":proxytype", server.proxyType); + query.bindValue(":proxyhost", server.proxyHost); + query.bindValue(":proxyport", server.proxyPort); + query.bindValue(":proxyuser", server.proxyUser); + query.bindValue(":proxypass", server.proxyPass); +} + + +bool SqliteStorage::updateNetwork(UserId user, const NetworkInfo &info) +{ + QSqlDatabase db = logDb(); + bool error = false; + db.transaction(); + + { + QSqlQuery updateQuery(db); + updateQuery.prepare(queryString("update_network")); + updateQuery.bindValue(":userid", user.toInt()); + bindNetworkInfo(updateQuery, info); + + lockForWrite(); + safeExec(updateQuery); + if (!watchQuery(updateQuery) || updateQuery.numRowsAffected() != 1) { + error = true; + db.rollback(); + } } - } - if(error) { - unlock(); - return false; - } - - { - QSqlQuery deleteBacklogQuery(db); - deleteBacklogQuery.prepare(queryString("delete_backlog_for_network")); - deleteBacklogQuery.bindValue(":networkid", networkId.toInt()); - safeExec(deleteBacklogQuery); - if(!watchQuery(deleteBacklogQuery)) { - db.rollback(); - error = true; - } - } - if(error) { - unlock(); - return false; - } - - { - QSqlQuery deleteBuffersQuery(db); - deleteBuffersQuery.prepare(queryString("delete_buffers_for_network")); - deleteBuffersQuery.bindValue(":networkid", networkId.toInt()); - safeExec(deleteBuffersQuery); - if(!watchQuery(deleteBuffersQuery)) { - db.rollback(); - error = true; - } - } - if(error) { - unlock(); - return false; - } - - { - QSqlQuery deleteServersQuery(db); - deleteServersQuery.prepare(queryString("delete_ircservers_for_network")); - deleteServersQuery.bindValue(":networkid", networkId.toInt()); - safeExec(deleteServersQuery); - if(!watchQuery(deleteServersQuery)) { - db.rollback(); - error = true; - } - } - if(error) { - unlock(); - return false; - } - - db.commit(); - unlock(); - return true; -} - -QList SqliteStorage::networks(UserId user) { - QList nets; - - QSqlDatabase db = logDb(); - db.transaction(); - - { - QSqlQuery networksQuery(db); - networksQuery.prepare(queryString("select_networks_for_user")); - networksQuery.bindValue(":userid", user.toInt()); - - QSqlQuery serversQuery(db); - serversQuery.prepare(queryString("select_servers_for_network")); - - lockForRead(); - safeExec(networksQuery); - if(watchQuery(networksQuery)) { - while(networksQuery.next()) { - NetworkInfo net; - net.networkId = networksQuery.value(0).toInt(); - net.networkName = networksQuery.value(1).toString(); - net.identity = networksQuery.value(2).toInt(); - net.codecForServer = networksQuery.value(3).toString().toAscii(); - net.codecForEncoding = networksQuery.value(4).toString().toAscii(); - net.codecForDecoding = networksQuery.value(5).toString().toAscii(); - net.useRandomServer = networksQuery.value(6).toInt() == 1 ? true : false; - net.perform = networksQuery.value(7).toString().split("\n"); - net.useAutoIdentify = networksQuery.value(8).toInt() == 1 ? true : false; - net.autoIdentifyService = networksQuery.value(9).toString(); - net.autoIdentifyPassword = networksQuery.value(10).toString(); - net.useAutoReconnect = networksQuery.value(11).toInt() == 1 ? true : false; - net.autoReconnectInterval = networksQuery.value(12).toUInt(); - net.autoReconnectRetries = networksQuery.value(13).toInt(); - net.unlimitedReconnectRetries = networksQuery.value(14).toInt() == 1 ? true : false; - net.rejoinChannels = networksQuery.value(15).toInt() == 1 ? true : false; - net.useSasl = networksQuery.value(16).toInt() == 1 ? true : false; - net.saslAccount = networksQuery.value(17).toString(); - net.saslPassword = networksQuery.value(18).toString(); - - serversQuery.bindValue(":networkid", net.networkId.toInt()); - safeExec(serversQuery); - if(!watchQuery(serversQuery)) { - nets.clear(); - break; - } else { - Network::ServerList servers; - while(serversQuery.next()) { - Network::Server server; - server.host = serversQuery.value(0).toString(); - server.port = serversQuery.value(1).toUInt(); - server.password = serversQuery.value(2).toString(); - server.useSsl = serversQuery.value(3).toInt() == 1 ? true : false; - server.sslVersion = serversQuery.value(4).toInt(); - server.useProxy = serversQuery.value(5).toInt() == 1 ? true : false; - server.proxyType = serversQuery.value(6).toInt(); - server.proxyHost = serversQuery.value(7).toString(); - server.proxyPort = serversQuery.value(8).toUInt(); - server.proxyUser = serversQuery.value(9).toString(); - server.proxyPass = serversQuery.value(10).toString(); - servers << server; - } - net.serverList = servers; - nets << net; + if (error) { + unlock(); + return false; + } + + { + QSqlQuery dropServersQuery(db); + dropServersQuery.prepare("DELETE FROM ircserver WHERE networkid = :networkid"); + dropServersQuery.bindValue(":networkid", info.networkId.toInt()); + safeExec(dropServersQuery); + if (!watchQuery(dropServersQuery)) { + error = true; + db.rollback(); } - } } - } - db.commit(); - unlock(); - return nets; + if (error) { + unlock(); + return false; + } + + { + QSqlQuery insertServersQuery(db); + insertServersQuery.prepare(queryString("insert_server")); + foreach(Network::Server server, info.serverList) { + insertServersQuery.bindValue(":userid", user.toInt()); + insertServersQuery.bindValue(":networkid", info.networkId.toInt()); + bindServerInfo(insertServersQuery, server); + safeExec(insertServersQuery); + if (!watchQuery(insertServersQuery)) { + error = true; + db.rollback(); + break; + } + } + } + + db.commit(); + unlock(); + return !error; } -QList SqliteStorage::connectedNetworks(UserId user) { - QList connectedNets; - QSqlDatabase db = logDb(); - db.transaction(); +bool SqliteStorage::removeNetwork(UserId user, const NetworkId &networkId) +{ + QSqlDatabase db = logDb(); + bool error = false; + db.transaction(); + + { + QSqlQuery deleteNetworkQuery(db); + deleteNetworkQuery.prepare(queryString("delete_network")); + deleteNetworkQuery.bindValue(":networkid", networkId.toInt()); + deleteNetworkQuery.bindValue(":userid", user.toInt()); + lockForWrite(); + safeExec(deleteNetworkQuery); + if (!watchQuery(deleteNetworkQuery) || deleteNetworkQuery.numRowsAffected() != 1) { + error = true; + db.rollback(); + } + } + if (error) { + unlock(); + return false; + } - { - QSqlQuery query(db); - query.prepare(queryString("select_connected_networks")); - query.bindValue(":userid", user.toInt()); - lockForRead(); - safeExec(query); - watchQuery(query); + { + QSqlQuery deleteBacklogQuery(db); + deleteBacklogQuery.prepare(queryString("delete_backlog_for_network")); + deleteBacklogQuery.bindValue(":networkid", networkId.toInt()); + safeExec(deleteBacklogQuery); + if (!watchQuery(deleteBacklogQuery)) { + db.rollback(); + error = true; + } + } + if (error) { + unlock(); + return false; + } - while(query.next()) { - connectedNets << query.value(0).toInt(); + { + QSqlQuery deleteBuffersQuery(db); + deleteBuffersQuery.prepare(queryString("delete_buffers_for_network")); + deleteBuffersQuery.bindValue(":networkid", networkId.toInt()); + safeExec(deleteBuffersQuery); + if (!watchQuery(deleteBuffersQuery)) { + db.rollback(); + error = true; + } + } + if (error) { + unlock(); + return false; + } + + { + QSqlQuery deleteServersQuery(db); + deleteServersQuery.prepare(queryString("delete_ircservers_for_network")); + deleteServersQuery.bindValue(":networkid", networkId.toInt()); + safeExec(deleteServersQuery); + if (!watchQuery(deleteServersQuery)) { + db.rollback(); + error = true; + } } + if (error) { + unlock(); + return false; + } + db.commit(); - } - unlock(); - return connectedNets; + unlock(); + return true; } -void SqliteStorage::setNetworkConnected(UserId user, const NetworkId &networkId, bool isConnected) { - QSqlDatabase db = logDb(); - db.transaction(); - - { - QSqlQuery query(db); - query.prepare(queryString("update_network_connected")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":networkid", networkId.toInt()); - query.bindValue(":connected", isConnected ? 1 : 0); - lockForWrite(); - safeExec(query); - watchQuery(query); +QList SqliteStorage::networks(UserId user) +{ + QList nets; + + QSqlDatabase db = logDb(); + db.transaction(); + + { + QSqlQuery networksQuery(db); + networksQuery.prepare(queryString("select_networks_for_user")); + networksQuery.bindValue(":userid", user.toInt()); + + QSqlQuery serversQuery(db); + serversQuery.prepare(queryString("select_servers_for_network")); + + lockForRead(); + safeExec(networksQuery); + if (watchQuery(networksQuery)) { + while (networksQuery.next()) { + NetworkInfo net; + net.networkId = networksQuery.value(0).toInt(); + net.networkName = networksQuery.value(1).toString(); + net.identity = networksQuery.value(2).toInt(); + net.codecForServer = networksQuery.value(3).toString().toAscii(); + net.codecForEncoding = networksQuery.value(4).toString().toAscii(); + net.codecForDecoding = networksQuery.value(5).toString().toAscii(); + net.useRandomServer = networksQuery.value(6).toInt() == 1 ? true : false; + net.perform = networksQuery.value(7).toString().split("\n"); + net.useAutoIdentify = networksQuery.value(8).toInt() == 1 ? true : false; + net.autoIdentifyService = networksQuery.value(9).toString(); + net.autoIdentifyPassword = networksQuery.value(10).toString(); + net.useAutoReconnect = networksQuery.value(11).toInt() == 1 ? true : false; + net.autoReconnectInterval = networksQuery.value(12).toUInt(); + net.autoReconnectRetries = networksQuery.value(13).toInt(); + net.unlimitedReconnectRetries = networksQuery.value(14).toInt() == 1 ? true : false; + net.rejoinChannels = networksQuery.value(15).toInt() == 1 ? true : false; + net.useSasl = networksQuery.value(16).toInt() == 1 ? true : false; + net.saslAccount = networksQuery.value(17).toString(); + net.saslPassword = networksQuery.value(18).toString(); + + serversQuery.bindValue(":networkid", net.networkId.toInt()); + safeExec(serversQuery); + if (!watchQuery(serversQuery)) { + nets.clear(); + break; + } + else { + Network::ServerList servers; + while (serversQuery.next()) { + Network::Server server; + server.host = serversQuery.value(0).toString(); + server.port = serversQuery.value(1).toUInt(); + server.password = serversQuery.value(2).toString(); + server.useSsl = serversQuery.value(3).toInt() == 1 ? true : false; + server.sslVersion = serversQuery.value(4).toInt(); + server.useProxy = serversQuery.value(5).toInt() == 1 ? true : false; + server.proxyType = serversQuery.value(6).toInt(); + server.proxyHost = serversQuery.value(7).toString(); + server.proxyPort = serversQuery.value(8).toUInt(); + server.proxyUser = serversQuery.value(9).toString(); + server.proxyPass = serversQuery.value(10).toString(); + servers << server; + } + net.serverList = servers; + nets << net; + } + } + } + } db.commit(); - } - unlock(); + unlock(); + return nets; } -QHash SqliteStorage::persistentChannels(UserId user, const NetworkId &networkId) { - QHash persistentChans; - QSqlDatabase db = logDb(); - db.transaction(); - { - QSqlQuery query(db); - query.prepare(queryString("select_persistent_channels")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":networkid", networkId.toInt()); +QList SqliteStorage::connectedNetworks(UserId user) +{ + QList connectedNets; + + QSqlDatabase db = logDb(); + db.transaction(); + + { + QSqlQuery query(db); + query.prepare(queryString("select_connected_networks")); + query.bindValue(":userid", user.toInt()); + lockForRead(); + safeExec(query); + watchQuery(query); - lockForRead(); - safeExec(query); - watchQuery(query); - while(query.next()) { - persistentChans[query.value(0).toString()] = query.value(1).toString(); + while (query.next()) { + connectedNets << query.value(0).toInt(); + } + db.commit(); } - } - unlock(); - return persistentChans; + unlock(); + return connectedNets; } -void SqliteStorage::setChannelPersistent(UserId user, const NetworkId &networkId, const QString &channel, bool isJoined) { - QSqlDatabase db = logDb(); - db.transaction(); - { - QSqlQuery query(db); - query.prepare(queryString("update_buffer_persistent_channel")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":networkId", networkId.toInt()); - query.bindValue(":buffercname", channel.toLower()); - query.bindValue(":joined", isJoined ? 1 : 0); - - lockForWrite(); - safeExec(query); - watchQuery(query); - db.commit(); - } - unlock(); +void SqliteStorage::setNetworkConnected(UserId user, const NetworkId &networkId, bool isConnected) +{ + QSqlDatabase db = logDb(); + db.transaction(); + + { + QSqlQuery query(db); + query.prepare(queryString("update_network_connected")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":networkid", networkId.toInt()); + query.bindValue(":connected", isConnected ? 1 : 0); + + lockForWrite(); + safeExec(query); + watchQuery(query); + db.commit(); + } + unlock(); } -void SqliteStorage::setPersistentChannelKey(UserId user, const NetworkId &networkId, const QString &channel, const QString &key) { - QSqlDatabase db = logDb(); - db.transaction(); - { - QSqlQuery query(db); - query.prepare(queryString("update_buffer_set_channel_key")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":networkId", networkId.toInt()); - query.bindValue(":buffercname", channel.toLower()); - query.bindValue(":key", key); +QHash SqliteStorage::persistentChannels(UserId user, const NetworkId &networkId) +{ + QHash persistentChans; + + QSqlDatabase db = logDb(); + db.transaction(); + { + QSqlQuery query(db); + query.prepare(queryString("select_persistent_channels")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":networkid", networkId.toInt()); + + lockForRead(); + safeExec(query); + watchQuery(query); + while (query.next()) { + persistentChans[query.value(0).toString()] = query.value(1).toString(); + } + } + unlock(); + return persistentChans; +} - lockForWrite(); - safeExec(query); - watchQuery(query); - db.commit(); - } - unlock(); -} - -QString SqliteStorage::awayMessage(UserId user, NetworkId networkId) { - QSqlDatabase db = logDb(); - db.transaction(); - - QString awayMsg; - { - QSqlQuery query(db); - query.prepare(queryString("select_network_awaymsg")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":networkid", networkId.toInt()); - - lockForRead(); - safeExec(query); - watchQuery(query); - if(query.first()) - awayMsg = query.value(0).toString(); - db.commit(); - } - unlock(); - return awayMsg; +void SqliteStorage::setChannelPersistent(UserId user, const NetworkId &networkId, const QString &channel, bool isJoined) +{ + QSqlDatabase db = logDb(); + db.transaction(); + + { + QSqlQuery query(db); + query.prepare(queryString("update_buffer_persistent_channel")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":networkId", networkId.toInt()); + query.bindValue(":buffercname", channel.toLower()); + query.bindValue(":joined", isJoined ? 1 : 0); + + lockForWrite(); + safeExec(query); + watchQuery(query); + db.commit(); + } + unlock(); } -void SqliteStorage::setAwayMessage(UserId user, NetworkId networkId, const QString &awayMsg) { - QSqlDatabase db = logDb(); - db.transaction(); - { - QSqlQuery query(db); - query.prepare(queryString("update_network_set_awaymsg")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":networkid", networkId.toInt()); - query.bindValue(":awaymsg", awayMsg); +void SqliteStorage::setPersistentChannelKey(UserId user, const NetworkId &networkId, const QString &channel, const QString &key) +{ + QSqlDatabase db = logDb(); + db.transaction(); + + { + QSqlQuery query(db); + query.prepare(queryString("update_buffer_set_channel_key")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":networkId", networkId.toInt()); + query.bindValue(":buffercname", channel.toLower()); + query.bindValue(":key", key); + + lockForWrite(); + safeExec(query); + watchQuery(query); + db.commit(); + } + unlock(); +} - lockForWrite(); - safeExec(query); - watchQuery(query); - db.commit(); - } - unlock(); -} - -QString SqliteStorage::userModes(UserId user, NetworkId networkId) { - QSqlDatabase db = logDb(); - db.transaction(); - - QString modes; - { - QSqlQuery query(db); - query.prepare(queryString("select_network_usermode")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":networkid", networkId.toInt()); - - lockForRead(); - safeExec(query); - watchQuery(query); - if(query.first()) - modes = query.value(0).toString(); - db.commit(); - } - unlock(); - return modes; +QString SqliteStorage::awayMessage(UserId user, NetworkId networkId) +{ + QSqlDatabase db = logDb(); + db.transaction(); + + QString awayMsg; + { + QSqlQuery query(db); + query.prepare(queryString("select_network_awaymsg")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":networkid", networkId.toInt()); + + lockForRead(); + safeExec(query); + watchQuery(query); + if (query.first()) + awayMsg = query.value(0).toString(); + db.commit(); + } + unlock(); + + return awayMsg; } -void SqliteStorage::setUserModes(UserId user, NetworkId networkId, const QString &userModes) { - QSqlDatabase db = logDb(); - db.transaction(); - { - QSqlQuery query(db); - query.prepare(queryString("update_network_set_usermode")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":networkid", networkId.toInt()); - query.bindValue(":usermode", userModes); +void SqliteStorage::setAwayMessage(UserId user, NetworkId networkId, const QString &awayMsg) +{ + QSqlDatabase db = logDb(); + db.transaction(); + + { + QSqlQuery query(db); + query.prepare(queryString("update_network_set_awaymsg")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":networkid", networkId.toInt()); + query.bindValue(":awaymsg", awayMsg); + + lockForWrite(); + safeExec(query); + watchQuery(query); + db.commit(); + } + unlock(); +} + - lockForWrite(); - safeExec(query); - watchQuery(query); - db.commit(); - } - unlock(); -} - -BufferInfo SqliteStorage::bufferInfo(UserId user, const NetworkId &networkId, BufferInfo::Type type, const QString &buffer, bool create) { - QSqlDatabase db = logDb(); - db.transaction(); - - BufferInfo bufferInfo; - { - QSqlQuery query(db); - query.prepare(queryString("select_bufferByName")); - query.bindValue(":networkid", networkId.toInt()); - query.bindValue(":userid", user.toInt()); - query.bindValue(":buffercname", buffer.toLower()); - - lockForRead(); - safeExec(query); - - if(query.first()) { - bufferInfo = BufferInfo(query.value(0).toInt(), networkId, (BufferInfo::Type)query.value(1).toInt(), 0, buffer); - if(query.next()) { - qCritical() << "SqliteStorage::getBufferInfo(): received more then one Buffer!"; - qCritical() << " Query:" << query.lastQuery(); - qCritical() << " bound Values:"; - QList list = query.boundValues().values(); - for (int i = 0; i < list.size(); ++i) - qCritical() << i << ":" << list.at(i).toString().toAscii().data(); - Q_ASSERT(false); - } - } else if(create) { - // let's create the buffer - QSqlQuery createQuery(db); - createQuery.prepare(queryString("insert_buffer")); - createQuery.bindValue(":userid", user.toInt()); - createQuery.bindValue(":networkid", networkId.toInt()); - createQuery.bindValue(":buffertype", (int)type); - createQuery.bindValue(":buffername", buffer); - createQuery.bindValue(":buffercname", buffer.toLower()); - createQuery.bindValue(":joined", type & BufferInfo::ChannelBuffer ? 1 : 0); - - unlock(); - lockForWrite(); - safeExec(createQuery); - watchQuery(createQuery); - bufferInfo = BufferInfo(createQuery.lastInsertId().toInt(), networkId, type, 0, buffer); - } - } - db.commit(); - unlock(); - return bufferInfo; -} - -BufferInfo SqliteStorage::getBufferInfo(UserId user, const BufferId &bufferId) { - QSqlDatabase db = logDb(); - db.transaction(); - - BufferInfo bufferInfo; - { - QSqlQuery query(db); - query.prepare(queryString("select_buffer_by_id")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":bufferid", bufferId.toInt()); - - lockForRead(); - safeExec(query); - - if(watchQuery(query) && query.first()) { - bufferInfo = BufferInfo(query.value(0).toInt(), query.value(1).toInt(), (BufferInfo::Type)query.value(2).toInt(), 0, query.value(4).toString()); - Q_ASSERT(!query.next()); +QString SqliteStorage::userModes(UserId user, NetworkId networkId) +{ + QSqlDatabase db = logDb(); + db.transaction(); + + QString modes; + { + QSqlQuery query(db); + query.prepare(queryString("select_network_usermode")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":networkid", networkId.toInt()); + + lockForRead(); + safeExec(query); + watchQuery(query); + if (query.first()) + modes = query.value(0).toString(); + db.commit(); } - db.commit(); - } - unlock(); - return bufferInfo; + unlock(); + + return modes; } -QList SqliteStorage::requestBuffers(UserId user) { - QList bufferlist; - QSqlDatabase db = logDb(); - db.transaction(); +void SqliteStorage::setUserModes(UserId user, NetworkId networkId, const QString &userModes) +{ + QSqlDatabase db = logDb(); + db.transaction(); + + { + QSqlQuery query(db); + query.prepare(queryString("update_network_set_usermode")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":networkid", networkId.toInt()); + query.bindValue(":usermode", userModes); + + lockForWrite(); + safeExec(query); + watchQuery(query); + db.commit(); + } + unlock(); +} - { - QSqlQuery query(db); - query.prepare(queryString("select_buffers")); - query.bindValue(":userid", user.toInt()); - lockForRead(); - safeExec(query); - watchQuery(query); - while(query.next()) { - bufferlist << BufferInfo(query.value(0).toInt(), query.value(1).toInt(), (BufferInfo::Type)query.value(2).toInt(), query.value(3).toInt(), query.value(4).toString()); +BufferInfo SqliteStorage::bufferInfo(UserId user, const NetworkId &networkId, BufferInfo::Type type, const QString &buffer, bool create) +{ + QSqlDatabase db = logDb(); + db.transaction(); + + BufferInfo bufferInfo; + { + QSqlQuery query(db); + query.prepare(queryString("select_bufferByName")); + query.bindValue(":networkid", networkId.toInt()); + query.bindValue(":userid", user.toInt()); + query.bindValue(":buffercname", buffer.toLower()); + + lockForRead(); + safeExec(query); + + if (query.first()) { + bufferInfo = BufferInfo(query.value(0).toInt(), networkId, (BufferInfo::Type)query.value(1).toInt(), 0, buffer); + if (query.next()) { + qCritical() << "SqliteStorage::getBufferInfo(): received more then one Buffer!"; + qCritical() << " Query:" << query.lastQuery(); + qCritical() << " bound Values:"; + QList list = query.boundValues().values(); + for (int i = 0; i < list.size(); ++i) + qCritical() << i << ":" << list.at(i).toString().toAscii().data(); + Q_ASSERT(false); + } + } + else if (create) { + // let's create the buffer + QSqlQuery createQuery(db); + createQuery.prepare(queryString("insert_buffer")); + createQuery.bindValue(":userid", user.toInt()); + createQuery.bindValue(":networkid", networkId.toInt()); + createQuery.bindValue(":buffertype", (int)type); + createQuery.bindValue(":buffername", buffer); + createQuery.bindValue(":buffercname", buffer.toLower()); + createQuery.bindValue(":joined", type & BufferInfo::ChannelBuffer ? 1 : 0); + + unlock(); + lockForWrite(); + safeExec(createQuery); + watchQuery(createQuery); + bufferInfo = BufferInfo(createQuery.lastInsertId().toInt(), networkId, type, 0, buffer); + } } db.commit(); - } - unlock(); + unlock(); + return bufferInfo; +} - return bufferlist; + +BufferInfo SqliteStorage::getBufferInfo(UserId user, const BufferId &bufferId) +{ + QSqlDatabase db = logDb(); + db.transaction(); + + BufferInfo bufferInfo; + { + QSqlQuery query(db); + query.prepare(queryString("select_buffer_by_id")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":bufferid", bufferId.toInt()); + + lockForRead(); + safeExec(query); + + if (watchQuery(query) && query.first()) { + bufferInfo = BufferInfo(query.value(0).toInt(), query.value(1).toInt(), (BufferInfo::Type)query.value(2).toInt(), 0, query.value(4).toString()); + Q_ASSERT(!query.next()); + } + db.commit(); + } + unlock(); + return bufferInfo; } -QList SqliteStorage::requestBufferIdsForNetwork(UserId user, NetworkId networkId) { - QList bufferList; - QSqlDatabase db = logDb(); - db.transaction(); +QList SqliteStorage::requestBuffers(UserId user) +{ + QList bufferlist; + + QSqlDatabase db = logDb(); + db.transaction(); - { - QSqlQuery query(db); - query.prepare(queryString("select_buffers_for_network")); - query.bindValue(":networkid", networkId.toInt()); - query.bindValue(":userid", user.toInt()); + { + QSqlQuery query(db); + query.prepare(queryString("select_buffers")); + query.bindValue(":userid", user.toInt()); - lockForRead(); - safeExec(query); - watchQuery(query); - while(query.next()) { - bufferList << BufferId(query.value(0).toInt()); + lockForRead(); + safeExec(query); + watchQuery(query); + while (query.next()) { + bufferlist << BufferInfo(query.value(0).toInt(), query.value(1).toInt(), (BufferInfo::Type)query.value(2).toInt(), query.value(3).toInt(), query.value(4).toString()); + } + db.commit(); } - db.commit(); - } - unlock(); + unlock(); - return bufferList; + return bufferlist; } -bool SqliteStorage::removeBuffer(const UserId &user, const BufferId &bufferId) { - QSqlDatabase db = logDb(); - db.transaction(); - bool error = false; - { - QSqlQuery delBufferQuery(db); - delBufferQuery.prepare(queryString("delete_buffer_for_bufferid")); - delBufferQuery.bindValue(":bufferid", bufferId.toInt()); - delBufferQuery.bindValue(":userid", user.toInt()); +QList SqliteStorage::requestBufferIdsForNetwork(UserId user, NetworkId networkId) +{ + QList bufferList; + + QSqlDatabase db = logDb(); + db.transaction(); + + { + QSqlQuery query(db); + query.prepare(queryString("select_buffers_for_network")); + query.bindValue(":networkid", networkId.toInt()); + query.bindValue(":userid", user.toInt()); + + lockForRead(); + safeExec(query); + watchQuery(query); + while (query.next()) { + bufferList << BufferId(query.value(0).toInt()); + } + db.commit(); + } + unlock(); - lockForWrite(); - safeExec(delBufferQuery); + return bufferList; +} - error = (!watchQuery(delBufferQuery) || delBufferQuery.numRowsAffected() != 1); - } - if(error) { - db.rollback(); - unlock(); - return false; - } +bool SqliteStorage::removeBuffer(const UserId &user, const BufferId &bufferId) +{ + QSqlDatabase db = logDb(); + db.transaction(); - { - QSqlQuery delBacklogQuery(db); - delBacklogQuery.prepare(queryString("delete_backlog_for_buffer")); - delBacklogQuery.bindValue(":bufferid", bufferId.toInt()); + bool error = false; + { + QSqlQuery delBufferQuery(db); + delBufferQuery.prepare(queryString("delete_buffer_for_bufferid")); + delBufferQuery.bindValue(":bufferid", bufferId.toInt()); + delBufferQuery.bindValue(":userid", user.toInt()); - safeExec(delBacklogQuery); - error = !watchQuery(delBacklogQuery); - } + lockForWrite(); + safeExec(delBufferQuery); - if(error) { - db.rollback(); - } else { - db.commit(); - } - unlock(); - return !error; -} + error = (!watchQuery(delBufferQuery) || delBufferQuery.numRowsAffected() != 1); + } + + if (error) { + db.rollback(); + unlock(); + return false; + } -bool SqliteStorage::renameBuffer(const UserId &user, const BufferId &bufferId, const QString &newName) { - QSqlDatabase db = logDb(); - db.transaction(); + { + QSqlQuery delBacklogQuery(db); + delBacklogQuery.prepare(queryString("delete_backlog_for_buffer")); + delBacklogQuery.bindValue(":bufferid", bufferId.toInt()); - bool error = false; - { - QSqlQuery query(db); - query.prepare(queryString("update_buffer_name")); - query.bindValue(":buffername", newName); - query.bindValue(":buffercname", newName.toLower()); - query.bindValue(":bufferid", bufferId.toInt()); - query.bindValue(":userid", user.toInt()); + safeExec(delBacklogQuery); + error = !watchQuery(delBacklogQuery); + } - lockForWrite(); - safeExec(query); - - error = query.lastError().isValid(); - // unexepcted error occured (19 == constraint violation) - if(error && query.lastError().number() != 19) { - watchQuery(query); - } else { - error |= (query.numRowsAffected() != 1); - } - } - if(error) { - db.rollback(); - } else { - db.commit(); - } - unlock(); - return !error; -} - -bool SqliteStorage::mergeBuffersPermanently(const UserId &user, const BufferId &bufferId1, const BufferId &bufferId2) { - QSqlDatabase db = logDb(); - db.transaction(); - - bool error = false; - { - QSqlQuery checkQuery(db); - checkQuery.prepare(queryString("select_buffers_for_merge")); - checkQuery.bindValue(":oldbufferid", bufferId2.toInt()); - checkQuery.bindValue(":newbufferid", bufferId1.toInt()); - checkQuery.bindValue(":userid", user.toInt()); - - lockForRead(); - safeExec(checkQuery); - error = (!checkQuery.first() || checkQuery.value(0).toInt() != 2); - } - if(error) { - db.rollback(); - unlock(); - return false; - } - - { - QSqlQuery query(db); - query.prepare(queryString("update_backlog_bufferid")); - query.bindValue(":oldbufferid", bufferId2.toInt()); - query.bindValue(":newbufferid", bufferId1.toInt()); - safeExec(query); - error = !watchQuery(query); - } - if(error) { - db.rollback(); + if (error) { + db.rollback(); + } + else { + db.commit(); + } unlock(); - return false; - } - - { - QSqlQuery delBufferQuery(db); - delBufferQuery.prepare(queryString("delete_buffer_for_bufferid")); - delBufferQuery.bindValue(":bufferid", bufferId2.toInt()); - delBufferQuery.bindValue(":userid", user.toInt()); - safeExec(delBufferQuery); - error = !watchQuery(delBufferQuery); - } - - if(error) { - db.rollback(); - } else { - db.commit(); - } - unlock(); - return !error; + return !error; } -void SqliteStorage::setBufferLastSeenMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) { - QSqlDatabase db = logDb(); - db.transaction(); - { - QSqlQuery query(db); - query.prepare(queryString("update_buffer_lastseen")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":bufferid", bufferId.toInt()); - query.bindValue(":lastseenmsgid", msgId.toInt()); - - lockForWrite(); - safeExec(query); - watchQuery(query); - } - db.commit(); - unlock(); +bool SqliteStorage::renameBuffer(const UserId &user, const BufferId &bufferId, const QString &newName) +{ + QSqlDatabase db = logDb(); + db.transaction(); + + bool error = false; + { + QSqlQuery query(db); + query.prepare(queryString("update_buffer_name")); + query.bindValue(":buffername", newName); + query.bindValue(":buffercname", newName.toLower()); + query.bindValue(":bufferid", bufferId.toInt()); + query.bindValue(":userid", user.toInt()); + + lockForWrite(); + safeExec(query); + + error = query.lastError().isValid(); + // unexepcted error occured (19 == constraint violation) + if (error && query.lastError().number() != 19) { + watchQuery(query); + } + else { + error |= (query.numRowsAffected() != 1); + } + } + if (error) { + db.rollback(); + } + else { + db.commit(); + } + unlock(); + return !error; } -QHash SqliteStorage::bufferLastSeenMsgIds(UserId user) { - QHash lastSeenHash; - QSqlDatabase db = logDb(); - db.transaction(); +bool SqliteStorage::mergeBuffersPermanently(const UserId &user, const BufferId &bufferId1, const BufferId &bufferId2) +{ + QSqlDatabase db = logDb(); + db.transaction(); + + bool error = false; + { + QSqlQuery checkQuery(db); + checkQuery.prepare(queryString("select_buffers_for_merge")); + checkQuery.bindValue(":oldbufferid", bufferId2.toInt()); + checkQuery.bindValue(":newbufferid", bufferId1.toInt()); + checkQuery.bindValue(":userid", user.toInt()); + + lockForRead(); + safeExec(checkQuery); + error = (!checkQuery.first() || checkQuery.value(0).toInt() != 2); + } + if (error) { + db.rollback(); + unlock(); + return false; + } + + { + QSqlQuery query(db); + query.prepare(queryString("update_backlog_bufferid")); + query.bindValue(":oldbufferid", bufferId2.toInt()); + query.bindValue(":newbufferid", bufferId1.toInt()); + safeExec(query); + error = !watchQuery(query); + } + if (error) { + db.rollback(); + unlock(); + return false; + } - bool error = false; - { - QSqlQuery query(db); - query.prepare(queryString("select_buffer_lastseen_messages")); - query.bindValue(":userid", user.toInt()); + { + QSqlQuery delBufferQuery(db); + delBufferQuery.prepare(queryString("delete_buffer_for_bufferid")); + delBufferQuery.bindValue(":bufferid", bufferId2.toInt()); + delBufferQuery.bindValue(":userid", user.toInt()); + safeExec(delBufferQuery); + error = !watchQuery(delBufferQuery); + } - lockForRead(); - safeExec(query); - error = !watchQuery(query); - if(!error) { - while(query.next()) { - lastSeenHash[query.value(0).toInt()] = query.value(1).toInt(); - } + if (error) { + db.rollback(); } - } + else { + db.commit(); + } + unlock(); + return !error; +} + - db.commit(); - unlock(); - return lastSeenHash; +void SqliteStorage::setBufferLastSeenMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) +{ + QSqlDatabase db = logDb(); + db.transaction(); + + { + QSqlQuery query(db); + query.prepare(queryString("update_buffer_lastseen")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":bufferid", bufferId.toInt()); + query.bindValue(":lastseenmsgid", msgId.toInt()); + + lockForWrite(); + safeExec(query); + watchQuery(query); + } + db.commit(); + unlock(); } -void SqliteStorage::setBufferMarkerLineMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) { - QSqlDatabase db = logDb(); - db.transaction(); - { - QSqlQuery query(db); - query.prepare(queryString("update_buffer_markerlinemsgid")); - query.bindValue(":userid", user.toInt()); - query.bindValue(":bufferid", bufferId.toInt()); - query.bindValue(":markerlinemsgid", msgId.toInt()); +QHash SqliteStorage::bufferLastSeenMsgIds(UserId user) +{ + QHash lastSeenHash; + + QSqlDatabase db = logDb(); + db.transaction(); + + bool error = false; + { + QSqlQuery query(db); + query.prepare(queryString("select_buffer_lastseen_messages")); + query.bindValue(":userid", user.toInt()); + + lockForRead(); + safeExec(query); + error = !watchQuery(query); + if (!error) { + while (query.next()) { + lastSeenHash[query.value(0).toInt()] = query.value(1).toInt(); + } + } + } - lockForWrite(); - safeExec(query); - watchQuery(query); - } - db.commit(); - unlock(); + db.commit(); + unlock(); + return lastSeenHash; } -QHash SqliteStorage::bufferMarkerLineMsgIds(UserId user) { - QHash markerLineHash; - QSqlDatabase db = logDb(); - db.transaction(); +void SqliteStorage::setBufferMarkerLineMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) +{ + QSqlDatabase db = logDb(); + db.transaction(); + + { + QSqlQuery query(db); + query.prepare(queryString("update_buffer_markerlinemsgid")); + query.bindValue(":userid", user.toInt()); + query.bindValue(":bufferid", bufferId.toInt()); + query.bindValue(":markerlinemsgid", msgId.toInt()); + + lockForWrite(); + safeExec(query); + watchQuery(query); + } + db.commit(); + unlock(); +} - bool error = false; - { - QSqlQuery query(db); - query.prepare(queryString("select_buffer_markerlinemsgids")); - query.bindValue(":userid", user.toInt()); - lockForRead(); - safeExec(query); - error = !watchQuery(query); - if(!error) { - while(query.next()) { - markerLineHash[query.value(0).toInt()] = query.value(1).toInt(); - } +QHash SqliteStorage::bufferMarkerLineMsgIds(UserId user) +{ + QHash markerLineHash; + + QSqlDatabase db = logDb(); + db.transaction(); + + bool error = false; + { + QSqlQuery query(db); + query.prepare(queryString("select_buffer_markerlinemsgids")); + query.bindValue(":userid", user.toInt()); + + lockForRead(); + safeExec(query); + error = !watchQuery(query); + if (!error) { + while (query.next()) { + markerLineHash[query.value(0).toInt()] = query.value(1).toInt(); + } + } } - } - db.commit(); - unlock(); - return markerLineHash; + db.commit(); + unlock(); + return markerLineHash; } -bool SqliteStorage::logMessage(Message &msg) { - QSqlDatabase db = logDb(); - db.transaction(); - bool error = false; - { - QSqlQuery logMessageQuery(db); - logMessageQuery.prepare(queryString("insert_message")); +bool SqliteStorage::logMessage(Message &msg) +{ + QSqlDatabase db = logDb(); + db.transaction(); + + bool error = false; + { + QSqlQuery logMessageQuery(db); + logMessageQuery.prepare(queryString("insert_message")); + + logMessageQuery.bindValue(":time", msg.timestamp().toTime_t()); + logMessageQuery.bindValue(":bufferid", msg.bufferInfo().bufferId().toInt()); + logMessageQuery.bindValue(":type", msg.type()); + logMessageQuery.bindValue(":flags", (int)msg.flags()); + logMessageQuery.bindValue(":sender", msg.sender()); + logMessageQuery.bindValue(":message", msg.contents()); + + lockForWrite(); + safeExec(logMessageQuery); + + if (logMessageQuery.lastError().isValid()) { + // constraint violation - must be NOT NULL constraint - probably the sender is missing... + if (logMessageQuery.lastError().number() == 19) { + QSqlQuery addSenderQuery(db); + addSenderQuery.prepare(queryString("insert_sender")); + addSenderQuery.bindValue(":sender", msg.sender()); + safeExec(addSenderQuery); + safeExec(logMessageQuery); + error = !watchQuery(logMessageQuery); + } + else { + watchQuery(logMessageQuery); + } + } + if (!error) { + MsgId msgId = logMessageQuery.lastInsertId().toInt(); + if (msgId.isValid()) { + msg.setMsgId(msgId); + } + else { + error = true; + } + } + } + + if (error) { + db.rollback(); + } + else { + db.commit(); + } + + unlock(); + return !error; +} - logMessageQuery.bindValue(":time", msg.timestamp().toTime_t()); - logMessageQuery.bindValue(":bufferid", msg.bufferInfo().bufferId().toInt()); - logMessageQuery.bindValue(":type", msg.type()); - logMessageQuery.bindValue(":flags", (int)msg.flags()); - logMessageQuery.bindValue(":sender", msg.sender()); - logMessageQuery.bindValue(":message", msg.contents()); - lockForWrite(); - safeExec(logMessageQuery); +bool SqliteStorage::logMessages(MessageList &msgs) +{ + QSqlDatabase db = logDb(); + db.transaction(); - if(logMessageQuery.lastError().isValid()) { - // constraint violation - must be NOT NULL constraint - probably the sender is missing... - if(logMessageQuery.lastError().number() == 19) { + { + QSet senders; QSqlQuery addSenderQuery(db); addSenderQuery.prepare(queryString("insert_sender")); - addSenderQuery.bindValue(":sender", msg.sender()); - safeExec(addSenderQuery); - safeExec(logMessageQuery); - error = !watchQuery(logMessageQuery); - } else { - watchQuery(logMessageQuery); - } - } - if(!error) { - MsgId msgId = logMessageQuery.lastInsertId().toInt(); - if(msgId.isValid()) { - msg.setMsgId(msgId); - } else { - error = true; - } - } - } - - if(error) { - db.rollback(); - } else { - db.commit(); - } + lockForWrite(); + for (int i = 0; i < msgs.count(); i++) { + const QString &sender = msgs.at(i).sender(); + if (senders.contains(sender)) + continue; + senders << sender; + + addSenderQuery.bindValue(":sender", sender); + safeExec(addSenderQuery); + } + } - unlock(); - return !error; + bool error = false; + { + QSqlQuery logMessageQuery(db); + logMessageQuery.prepare(queryString("insert_message")); + for (int i = 0; i < msgs.count(); i++) { + Message &msg = msgs[i]; + + logMessageQuery.bindValue(":time", msg.timestamp().toTime_t()); + logMessageQuery.bindValue(":bufferid", msg.bufferInfo().bufferId().toInt()); + logMessageQuery.bindValue(":type", msg.type()); + logMessageQuery.bindValue(":flags", (int)msg.flags()); + logMessageQuery.bindValue(":sender", msg.sender()); + logMessageQuery.bindValue(":message", msg.contents()); + + safeExec(logMessageQuery); + if (!watchQuery(logMessageQuery)) { + error = true; + break; + } + else { + msg.setMsgId(logMessageQuery.lastInsertId().toInt()); + } + } + } + + if (error) { + db.rollback(); + unlock(); + // we had a rollback in the db so we need to reset all msgIds + for (int i = 0; i < msgs.count(); i++) { + msgs[i].setMsgId(MsgId()); + } + } + else { + db.commit(); + unlock(); + } + return !error; } -bool SqliteStorage::logMessages(MessageList &msgs) { - QSqlDatabase db = logDb(); - db.transaction(); - { - QSet senders; - QSqlQuery addSenderQuery(db); - addSenderQuery.prepare(queryString("insert_sender")); - lockForWrite(); - for(int i = 0; i < msgs.count(); i++) { - const QString &sender = msgs.at(i).sender(); - if(senders.contains(sender)) - continue; - senders << sender; - - addSenderQuery.bindValue(":sender", sender); - safeExec(addSenderQuery); - } - } - - bool error = false; - { - QSqlQuery logMessageQuery(db); - logMessageQuery.prepare(queryString("insert_message")); - for(int i = 0; i < msgs.count(); i++) { - Message &msg = msgs[i]; - - logMessageQuery.bindValue(":time", msg.timestamp().toTime_t()); - logMessageQuery.bindValue(":bufferid", msg.bufferInfo().bufferId().toInt()); - logMessageQuery.bindValue(":type", msg.type()); - logMessageQuery.bindValue(":flags", (int)msg.flags()); - logMessageQuery.bindValue(":sender", msg.sender()); - logMessageQuery.bindValue(":message", msg.contents()); - - safeExec(logMessageQuery); - if(!watchQuery(logMessageQuery)) { - error = true; - break; - } else { - msg.setMsgId(logMessageQuery.lastInsertId().toInt()); - } +QList SqliteStorage::requestMsgs(UserId user, BufferId bufferId, MsgId first, MsgId last, int limit) +{ + QList messagelist; + + QSqlDatabase db = logDb(); + db.transaction(); + + bool error = false; + BufferInfo bufferInfo; + { + // code dupication from getBufferInfo: + // this is due to the impossibility of nesting transactions and recursive locking + QSqlQuery bufferInfoQuery(db); + bufferInfoQuery.prepare(queryString("select_buffer_by_id")); + bufferInfoQuery.bindValue(":userid", user.toInt()); + bufferInfoQuery.bindValue(":bufferid", bufferId.toInt()); + + lockForRead(); + safeExec(bufferInfoQuery); + error = !watchQuery(bufferInfoQuery) || !bufferInfoQuery.first(); + if (!error) { + bufferInfo = BufferInfo(bufferInfoQuery.value(0).toInt(), bufferInfoQuery.value(1).toInt(), (BufferInfo::Type)bufferInfoQuery.value(2).toInt(), 0, bufferInfoQuery.value(4).toString()); + error = !bufferInfo.isValid(); + } + } + if (error) { + db.rollback(); + unlock(); + return messagelist; } - } - if(error) { - db.rollback(); - unlock(); - // we had a rollback in the db so we need to reset all msgIds - for(int i = 0; i < msgs.count(); i++) { - msgs[i].setMsgId(MsgId()); + { + QSqlQuery query(db); + if (last == -1 && first == -1) { + query.prepare(queryString("select_messagesNewestK")); + } + else if (last == -1) { + query.prepare(queryString("select_messagesNewerThan")); + query.bindValue(":firstmsg", first.toInt()); + } + else { + query.prepare(queryString("select_messages")); + query.bindValue(":lastmsg", last.toInt()); + query.bindValue(":firstmsg", first.toInt()); + } + query.bindValue(":bufferid", bufferId.toInt()); + query.bindValue(":limit", limit); + + safeExec(query); + watchQuery(query); + + while (query.next()) { + Message msg(QDateTime::fromTime_t(query.value(1).toInt()), + bufferInfo, + (Message::Type)query.value(2).toUInt(), + query.value(5).toString(), + query.value(4).toString(), + (Message::Flags)query.value(3).toUInt()); + msg.setMsgId(query.value(0).toInt()); + messagelist << msg; + } } - } else { db.commit(); unlock(); - } - return !error; -} - -QList SqliteStorage::requestMsgs(UserId user, BufferId bufferId, MsgId first, MsgId last, int limit) { - QList messagelist; - - QSqlDatabase db = logDb(); - db.transaction(); - - bool error = false; - BufferInfo bufferInfo; - { - // code dupication from getBufferInfo: - // this is due to the impossibility of nesting transactions and recursive locking - QSqlQuery bufferInfoQuery(db); - bufferInfoQuery.prepare(queryString("select_buffer_by_id")); - bufferInfoQuery.bindValue(":userid", user.toInt()); - bufferInfoQuery.bindValue(":bufferid", bufferId.toInt()); - - lockForRead(); - safeExec(bufferInfoQuery); - error = !watchQuery(bufferInfoQuery) || !bufferInfoQuery.first(); - if(!error) { - bufferInfo = BufferInfo(bufferInfoQuery.value(0).toInt(), bufferInfoQuery.value(1).toInt(), (BufferInfo::Type)bufferInfoQuery.value(2).toInt(), 0, bufferInfoQuery.value(4).toString()); - error = !bufferInfo.isValid(); - } - } - if(error) { - db.rollback(); + + return messagelist; +} + + +QList SqliteStorage::requestAllMsgs(UserId user, MsgId first, MsgId last, int limit) +{ + QList messagelist; + + QSqlDatabase db = logDb(); + db.transaction(); + + QHash bufferInfoHash; + { + QSqlQuery bufferInfoQuery(db); + bufferInfoQuery.prepare(queryString("select_buffers")); + bufferInfoQuery.bindValue(":userid", user.toInt()); + + lockForRead(); + safeExec(bufferInfoQuery); + watchQuery(bufferInfoQuery); + while (bufferInfoQuery.next()) { + BufferInfo bufferInfo = BufferInfo(bufferInfoQuery.value(0).toInt(), bufferInfoQuery.value(1).toInt(), (BufferInfo::Type)bufferInfoQuery.value(2).toInt(), bufferInfoQuery.value(3).toInt(), bufferInfoQuery.value(4).toString()); + bufferInfoHash[bufferInfo.bufferId()] = bufferInfo; + } + + QSqlQuery query(db); + if (last == -1) { + query.prepare(queryString("select_messagesAllNew")); + } + else { + query.prepare(queryString("select_messagesAll")); + query.bindValue(":lastmsg", last.toInt()); + } + query.bindValue(":userid", user.toInt()); + query.bindValue(":firstmsg", first.toInt()); + query.bindValue(":limit", limit); + safeExec(query); + + watchQuery(query); + + while (query.next()) { + Message msg(QDateTime::fromTime_t(query.value(2).toInt()), + bufferInfoHash[query.value(1).toInt()], + (Message::Type)query.value(3).toUInt(), + query.value(6).toString(), + query.value(5).toString(), + (Message::Flags)query.value(4).toUInt()); + msg.setMsgId(query.value(0).toInt()); + messagelist << msg; + } + } + db.commit(); unlock(); return messagelist; - } - - { - QSqlQuery query(db); - if(last == -1 && first == -1) { - query.prepare(queryString("select_messagesNewestK")); - } else if(last == -1) { - query.prepare(queryString("select_messagesNewerThan")); - query.bindValue(":firstmsg", first.toInt()); - } else { - query.prepare(queryString("select_messages")); - query.bindValue(":lastmsg", last.toInt()); - query.bindValue(":firstmsg", first.toInt()); - } - query.bindValue(":bufferid", bufferId.toInt()); - query.bindValue(":limit", limit); - - safeExec(query); - watchQuery(query); - - while(query.next()) { - Message msg(QDateTime::fromTime_t(query.value(1).toInt()), - bufferInfo, - (Message::Type)query.value(2).toUInt(), - query.value(5).toString(), - query.value(4).toString(), - (Message::Flags)query.value(3).toUInt()); - msg.setMsgId(query.value(0).toInt()); - messagelist << msg; - } - } - db.commit(); - unlock(); - - return messagelist; -} - -QList SqliteStorage::requestAllMsgs(UserId user, MsgId first, MsgId last, int limit) { - QList messagelist; - - QSqlDatabase db = logDb(); - db.transaction(); - - QHash bufferInfoHash; - { - QSqlQuery bufferInfoQuery(db); - bufferInfoQuery.prepare(queryString("select_buffers")); - bufferInfoQuery.bindValue(":userid", user.toInt()); - - lockForRead(); - safeExec(bufferInfoQuery); - watchQuery(bufferInfoQuery); - while(bufferInfoQuery.next()) { - BufferInfo bufferInfo = BufferInfo(bufferInfoQuery.value(0).toInt(), bufferInfoQuery.value(1).toInt(), (BufferInfo::Type)bufferInfoQuery.value(2).toInt(), bufferInfoQuery.value(3).toInt(), bufferInfoQuery.value(4).toString()); - bufferInfoHash[bufferInfo.bufferId()] = bufferInfo; - } - - QSqlQuery query(db); - if(last == -1) { - query.prepare(queryString("select_messagesAllNew")); - } else { - query.prepare(queryString("select_messagesAll")); - query.bindValue(":lastmsg", last.toInt()); - } - query.bindValue(":userid", user.toInt()); - query.bindValue(":firstmsg", first.toInt()); - query.bindValue(":limit", limit); - safeExec(query); - - watchQuery(query); - - while(query.next()) { - Message msg(QDateTime::fromTime_t(query.value(2).toInt()), - bufferInfoHash[query.value(1).toInt()], - (Message::Type)query.value(3).toUInt(), - query.value(6).toString(), - query.value(5).toString(), - (Message::Flags)query.value(4).toUInt()); - msg.setMsgId(query.value(0).toInt()); - messagelist << msg; - } - } - db.commit(); - unlock(); - return messagelist; -} - -QString SqliteStorage::backlogFile() { - return Quassel::configDirPath() + "quassel-storage.sqlite"; -} - -bool SqliteStorage::safeExec(QSqlQuery &query, int retryCount) { - query.exec(); - - if(!query.lastError().isValid()) - return true; +} + + +QString SqliteStorage::backlogFile() +{ + return Quassel::configDirPath() + "quassel-storage.sqlite"; +} - switch(query.lastError().number()) { - case 5: // SQLITE_BUSY 5 /* The database file is locked */ - case 6: // SQLITE_LOCKED 6 /* A table in the database is locked */ - if(retryCount < _maxRetryCount) - return safeExec(query, retryCount + 1); - default: - return false; - } + +bool SqliteStorage::safeExec(QSqlQuery &query, int retryCount) +{ + query.exec(); + + if (!query.lastError().isValid()) + return true; + + switch (query.lastError().number()) { + case 5: // SQLITE_BUSY 5 /* The database file is locked */ + case 6: // SQLITE_LOCKED 6 /* A table in the database is locked */ + if (retryCount < _maxRetryCount) + return safeExec(query, retryCount + 1); + default: + return false; + } } @@ -1603,237 +1724,261 @@ bool SqliteStorage::safeExec(QSqlQuery &query, int retryCount) { // SqliteMigration // ======================================== SqliteMigrationReader::SqliteMigrationReader() - : SqliteStorage(), + : SqliteStorage(), _maxId(0) { } -void SqliteMigrationReader::setMaxId(MigrationObject mo) { - QString queryString; - switch(mo) { - case Sender: - queryString = "SELECT max(senderid) FROM sender"; - break; - case Backlog: - queryString = "SELECT max(messageid) FROM backlog"; - break; - default: - _maxId = 0; - return; - } - QSqlQuery query = logDb().exec(queryString); - query.first(); - _maxId = query.value(0).toInt(); -} - -bool SqliteMigrationReader::prepareQuery(MigrationObject mo) { - setMaxId(mo); - - switch(mo) { - case QuasselUser: - newQuery(queryString("migrate_read_quasseluser"), logDb()); - break; - case Identity: - newQuery(queryString("migrate_read_identity"), logDb()); - break; - case IdentityNick: - newQuery(queryString("migrate_read_identity_nick"), logDb()); - break; - case Network: - newQuery(queryString("migrate_read_network"), logDb()); - break; - case Buffer: - newQuery(queryString("migrate_read_buffer"), logDb()); - break; - case Sender: - newQuery(queryString("migrate_read_sender"), logDb()); - bindValue(0, 0); - bindValue(1, stepSize()); - break; - case Backlog: - newQuery(queryString("migrate_read_backlog"), logDb()); - bindValue(0, 0); - bindValue(1, stepSize()); - break; - case IrcServer: - newQuery(queryString("migrate_read_ircserver"), logDb()); - break; - case UserSetting: - newQuery(queryString("migrate_read_usersetting"), logDb()); - break; - } - return exec(); -} - -bool SqliteMigrationReader::readMo(QuasselUserMO &user) { - if(!next()) - return false; - - user.id = value(0).toInt(); - user.username = value(1).toString(); - user.password = value(2).toString(); - return true; -} - -bool SqliteMigrationReader::readMo(IdentityMO &identity) { - if(!next()) - return false; - - identity.id = value(0).toInt(); - identity.userid = value(1).toInt(); - identity.identityname = value(2).toString(); - identity.realname = value(3).toString(); - identity.awayNick = value(4).toString(); - identity.awayNickEnabled = value(5).toInt() == 1 ? true : false; - identity.awayReason = value(6).toString(); - identity.awayReasonEnabled = value(7).toInt() == 1 ? true : false; - identity.autoAwayEnabled = value(8).toInt() == 1 ? true : false; - identity.autoAwayTime = value(9).toInt(); - identity.autoAwayReason = value(10).toString(); - identity.autoAwayReasonEnabled = value(11).toInt() == 1 ? true : false; - identity.detachAwayEnabled = value(12).toInt() == 1 ? true : false; - identity.detachAwayReason = value(13).toString(); - identity.detchAwayReasonEnabled = value(14).toInt() == 1 ? true : false; - identity.ident = value(15).toString(); - identity.kickReason = value(16).toString(); - identity.partReason = value(17).toString(); - identity.quitReason = value(18).toString(); - identity.sslCert = value(19).toByteArray(); - identity.sslKey = value(20).toByteArray(); - return true; -} - -bool SqliteMigrationReader::readMo(IdentityNickMO &identityNick) { - if(!next()) - return false; - - identityNick.nickid = value(0).toInt(); - identityNick.identityId = value(1).toInt(); - identityNick.nick = value(2).toString(); - return true; -} - -bool SqliteMigrationReader::readMo(NetworkMO &network) { - if(!next()) - return false; - - network.networkid = value(0).toInt(); - network.userid = value(1).toInt(); - network.networkname = value(2).toString(); - network.identityid = value(3).toInt(); - network.encodingcodec = value(4).toString(); - network.decodingcodec = value(5).toString(); - network.servercodec = value(6).toString(); - network.userandomserver = value(7).toInt() == 1 ? true : false; - network.perform = value(8).toString(); - network.useautoidentify = value(9).toInt() == 1 ? true : false; - network.autoidentifyservice = value(10).toString(); - network.autoidentifypassword = value(11).toString(); - network.useautoreconnect = value(12).toInt() == 1 ? true : false; - network.autoreconnectinterval = value(13).toInt(); - network.autoreconnectretries = value(14).toInt(); - network.unlimitedconnectretries = value(15).toInt() == 1 ? true : false; - network.rejoinchannels = value(16).toInt() == 1 ? true : false; - network.connected = value(17).toInt() == 1 ? true : false; - network.usermode = value(18).toString(); - network.awaymessage = value(19).toString(); - network.attachperform = value(20).toString(); - network.detachperform = value(21).toString(); - network.usesasl = value(22).toInt() == 1 ? true : false; - network.saslaccount = value(23).toString(); - network.saslpassword = value(24).toString(); - return true; -} - -bool SqliteMigrationReader::readMo(BufferMO &buffer) { - if(!next()) - return false; - - buffer.bufferid = value(0).toInt(); - buffer.userid = value(1).toInt(); - buffer.groupid = value(2).toInt(); - buffer.networkid = value(3).toInt(); - buffer.buffername = value(4).toString(); - buffer.buffercname = value(5).toString(); - buffer.buffertype = value(6).toInt(); - buffer.lastseenmsgid = value(7).toInt(); - buffer.markerlinemsgid = value(8).toInt(); - buffer.key = value(9).toString(); - buffer.joined = value(10).toInt() == 1 ? true : false; - return true; -} - -bool SqliteMigrationReader::readMo(SenderMO &sender) { - int skipSteps = 0; - while(!next()) { - if(sender.senderId < _maxId) { - bindValue(0, sender.senderId + (skipSteps * stepSize())); - bindValue(1, sender.senderId + ((skipSteps + 1) * stepSize())); - skipSteps++; - if(!exec()) - return false; - } else { - return false; - } - } - - sender.senderId = value(0).toInt(); - sender.sender = value(1).toString(); - return true; -} - -bool SqliteMigrationReader::readMo(BacklogMO &backlog) { - int skipSteps = 0; - while(!next()) { - if(backlog.messageid < _maxId) { - bindValue(0, backlog.messageid.toInt() + (skipSteps * stepSize())); - bindValue(1, backlog.messageid.toInt() + ((skipSteps + 1) * stepSize())); - skipSteps++; - if(!exec()) - return false; - } else { - return false; - } - } - - backlog.messageid = value(0).toInt(); - backlog.time = QDateTime::fromTime_t(value(1).toInt()).toUTC(); - backlog.bufferid = value(2).toInt(); - backlog.type = value(3).toInt(); - backlog.flags = value(4).toInt(); - backlog.senderid = value(5).toInt(); - backlog.message = value(6).toString(); - return true; -} - -bool SqliteMigrationReader::readMo(IrcServerMO &ircserver) { - if(!next()) - return false; - - ircserver.serverid = value(0).toInt(); - ircserver.userid = value(1).toInt(); - ircserver.networkid = value(2).toInt(); - ircserver.hostname = value(3).toString(); - ircserver.port = value(4).toInt(); - ircserver.password = value(5).toString(); - ircserver.ssl = value(6).toInt() == 1 ? true : false; - ircserver.sslversion = value(7).toInt(); - ircserver.useproxy = value(8).toInt() == 1 ? true : false; - ircserver.proxytype = value(9).toInt(); - ircserver.proxyhost = value(10).toString(); - ircserver.proxyport = value(11).toInt(); - ircserver.proxyuser = value(12).toString(); - ircserver.proxypass = value(13).toString(); - return true; -} - -bool SqliteMigrationReader::readMo(UserSettingMO &userSetting) { - if(!next()) - return false; - - userSetting.userid = value(0).toInt(); - userSetting.settingname = value(1).toString(); - userSetting.settingvalue = value(2).toByteArray(); - - return true; + +void SqliteMigrationReader::setMaxId(MigrationObject mo) +{ + QString queryString; + switch (mo) { + case Sender: + queryString = "SELECT max(senderid) FROM sender"; + break; + case Backlog: + queryString = "SELECT max(messageid) FROM backlog"; + break; + default: + _maxId = 0; + return; + } + QSqlQuery query = logDb().exec(queryString); + query.first(); + _maxId = query.value(0).toInt(); +} + + +bool SqliteMigrationReader::prepareQuery(MigrationObject mo) +{ + setMaxId(mo); + + switch (mo) { + case QuasselUser: + newQuery(queryString("migrate_read_quasseluser"), logDb()); + break; + case Identity: + newQuery(queryString("migrate_read_identity"), logDb()); + break; + case IdentityNick: + newQuery(queryString("migrate_read_identity_nick"), logDb()); + break; + case Network: + newQuery(queryString("migrate_read_network"), logDb()); + break; + case Buffer: + newQuery(queryString("migrate_read_buffer"), logDb()); + break; + case Sender: + newQuery(queryString("migrate_read_sender"), logDb()); + bindValue(0, 0); + bindValue(1, stepSize()); + break; + case Backlog: + newQuery(queryString("migrate_read_backlog"), logDb()); + bindValue(0, 0); + bindValue(1, stepSize()); + break; + case IrcServer: + newQuery(queryString("migrate_read_ircserver"), logDb()); + break; + case UserSetting: + newQuery(queryString("migrate_read_usersetting"), logDb()); + break; + } + return exec(); +} + + +bool SqliteMigrationReader::readMo(QuasselUserMO &user) +{ + if (!next()) + return false; + + user.id = value(0).toInt(); + user.username = value(1).toString(); + user.password = value(2).toString(); + return true; +} + + +bool SqliteMigrationReader::readMo(IdentityMO &identity) +{ + if (!next()) + return false; + + identity.id = value(0).toInt(); + identity.userid = value(1).toInt(); + identity.identityname = value(2).toString(); + identity.realname = value(3).toString(); + identity.awayNick = value(4).toString(); + identity.awayNickEnabled = value(5).toInt() == 1 ? true : false; + identity.awayReason = value(6).toString(); + identity.awayReasonEnabled = value(7).toInt() == 1 ? true : false; + identity.autoAwayEnabled = value(8).toInt() == 1 ? true : false; + identity.autoAwayTime = value(9).toInt(); + identity.autoAwayReason = value(10).toString(); + identity.autoAwayReasonEnabled = value(11).toInt() == 1 ? true : false; + identity.detachAwayEnabled = value(12).toInt() == 1 ? true : false; + identity.detachAwayReason = value(13).toString(); + identity.detchAwayReasonEnabled = value(14).toInt() == 1 ? true : false; + identity.ident = value(15).toString(); + identity.kickReason = value(16).toString(); + identity.partReason = value(17).toString(); + identity.quitReason = value(18).toString(); + identity.sslCert = value(19).toByteArray(); + identity.sslKey = value(20).toByteArray(); + return true; +} + + +bool SqliteMigrationReader::readMo(IdentityNickMO &identityNick) +{ + if (!next()) + return false; + + identityNick.nickid = value(0).toInt(); + identityNick.identityId = value(1).toInt(); + identityNick.nick = value(2).toString(); + return true; +} + + +bool SqliteMigrationReader::readMo(NetworkMO &network) +{ + if (!next()) + return false; + + network.networkid = value(0).toInt(); + network.userid = value(1).toInt(); + network.networkname = value(2).toString(); + network.identityid = value(3).toInt(); + network.encodingcodec = value(4).toString(); + network.decodingcodec = value(5).toString(); + network.servercodec = value(6).toString(); + network.userandomserver = value(7).toInt() == 1 ? true : false; + network.perform = value(8).toString(); + network.useautoidentify = value(9).toInt() == 1 ? true : false; + network.autoidentifyservice = value(10).toString(); + network.autoidentifypassword = value(11).toString(); + network.useautoreconnect = value(12).toInt() == 1 ? true : false; + network.autoreconnectinterval = value(13).toInt(); + network.autoreconnectretries = value(14).toInt(); + network.unlimitedconnectretries = value(15).toInt() == 1 ? true : false; + network.rejoinchannels = value(16).toInt() == 1 ? true : false; + network.connected = value(17).toInt() == 1 ? true : false; + network.usermode = value(18).toString(); + network.awaymessage = value(19).toString(); + network.attachperform = value(20).toString(); + network.detachperform = value(21).toString(); + network.usesasl = value(22).toInt() == 1 ? true : false; + network.saslaccount = value(23).toString(); + network.saslpassword = value(24).toString(); + return true; +} + + +bool SqliteMigrationReader::readMo(BufferMO &buffer) +{ + if (!next()) + return false; + + buffer.bufferid = value(0).toInt(); + buffer.userid = value(1).toInt(); + buffer.groupid = value(2).toInt(); + buffer.networkid = value(3).toInt(); + buffer.buffername = value(4).toString(); + buffer.buffercname = value(5).toString(); + buffer.buffertype = value(6).toInt(); + buffer.lastseenmsgid = value(7).toInt(); + buffer.markerlinemsgid = value(8).toInt(); + buffer.key = value(9).toString(); + buffer.joined = value(10).toInt() == 1 ? true : false; + return true; +} + + +bool SqliteMigrationReader::readMo(SenderMO &sender) +{ + int skipSteps = 0; + while (!next()) { + if (sender.senderId < _maxId) { + bindValue(0, sender.senderId + (skipSteps * stepSize())); + bindValue(1, sender.senderId + ((skipSteps + 1) * stepSize())); + skipSteps++; + if (!exec()) + return false; + } + else { + return false; + } + } + + sender.senderId = value(0).toInt(); + sender.sender = value(1).toString(); + return true; +} + + +bool SqliteMigrationReader::readMo(BacklogMO &backlog) +{ + int skipSteps = 0; + while (!next()) { + if (backlog.messageid < _maxId) { + bindValue(0, backlog.messageid.toInt() + (skipSteps * stepSize())); + bindValue(1, backlog.messageid.toInt() + ((skipSteps + 1) * stepSize())); + skipSteps++; + if (!exec()) + return false; + } + else { + return false; + } + } + + backlog.messageid = value(0).toInt(); + backlog.time = QDateTime::fromTime_t(value(1).toInt()).toUTC(); + backlog.bufferid = value(2).toInt(); + backlog.type = value(3).toInt(); + backlog.flags = value(4).toInt(); + backlog.senderid = value(5).toInt(); + backlog.message = value(6).toString(); + return true; +} + + +bool SqliteMigrationReader::readMo(IrcServerMO &ircserver) +{ + if (!next()) + return false; + + ircserver.serverid = value(0).toInt(); + ircserver.userid = value(1).toInt(); + ircserver.networkid = value(2).toInt(); + ircserver.hostname = value(3).toString(); + ircserver.port = value(4).toInt(); + ircserver.password = value(5).toString(); + ircserver.ssl = value(6).toInt() == 1 ? true : false; + ircserver.sslversion = value(7).toInt(); + ircserver.useproxy = value(8).toInt() == 1 ? true : false; + ircserver.proxytype = value(9).toInt(); + ircserver.proxyhost = value(10).toString(); + ircserver.proxyport = value(11).toInt(); + ircserver.proxyuser = value(12).toString(); + ircserver.proxypass = value(13).toString(); + return true; +} + + +bool SqliteMigrationReader::readMo(UserSettingMO &userSetting) +{ + if (!next()) + return false; + + userSetting.userid = value(0).toInt(); + userSetting.settingname = value(1).toString(); + userSetting.settingvalue = value(2).toByteArray(); + + return true; } diff --git a/src/core/sqlitestorage.h b/src/core/sqlitestorage.h index 9aa70066..6cfba17a 100644 --- a/src/core/sqlitestorage.h +++ b/src/core/sqlitestorage.h @@ -27,137 +27,143 @@ class QSqlQuery; -class SqliteStorage : public AbstractSqlStorage { - Q_OBJECT +class SqliteStorage : public AbstractSqlStorage +{ + Q_OBJECT public: - SqliteStorage(QObject *parent = 0); - virtual ~SqliteStorage(); + SqliteStorage(QObject *parent = 0); + virtual ~SqliteStorage(); - virtual AbstractSqlMigrationReader *createMigrationReader(); + virtual AbstractSqlMigrationReader *createMigrationReader(); public slots: - /* General */ - - bool isAvailable() const; - QString displayName() const; - virtual inline QStringList setupKeys() const { return QStringList(); } - virtual inline QVariantMap setupDefaults() const { return QVariantMap(); } - QString description() const; - - // TODO: Add functions for configuring the backlog handling, i.e. defining auto-cleanup settings etc - - /* User handling */ - virtual UserId addUser(const QString &user, const QString &password); - virtual bool updateUser(UserId user, const QString &password); - virtual void renameUser(UserId user, const QString &newName); - virtual UserId validateUser(const QString &user, const QString &password); - virtual UserId getUserId(const QString &username); - virtual UserId internalUser(); - virtual void delUser(UserId user); - virtual void setUserSetting(UserId userId, const QString &settingName, const QVariant &data); - virtual QVariant getUserSetting(UserId userId, const QString &settingName, const QVariant &defaultData = QVariant()); - - /* Identity handling */ - virtual IdentityId createIdentity(UserId user, CoreIdentity &identity); - virtual bool updateIdentity(UserId user, const CoreIdentity &identity); - virtual void removeIdentity(UserId user, IdentityId identityId); - virtual QList identities(UserId user); - - /* Network handling */ - virtual NetworkId createNetwork(UserId user, const NetworkInfo &info); - virtual bool updateNetwork(UserId user, const NetworkInfo &info); - virtual bool removeNetwork(UserId user, const NetworkId &networkId); - virtual QList networks(UserId user); - virtual QList connectedNetworks(UserId user); - virtual void setNetworkConnected(UserId user, const NetworkId &networkId, bool isConnected); - - /* persistent channels */ - virtual QHash persistentChannels(UserId user, const NetworkId &networkId); - virtual void setChannelPersistent(UserId user, const NetworkId &networkId, const QString &channel, bool isJoined); - virtual void setPersistentChannelKey(UserId user, const NetworkId &networkId, const QString &channel, const QString &key); - - /* persistent user states */ - virtual QString awayMessage(UserId user, NetworkId networkId); - virtual void setAwayMessage(UserId user, NetworkId networkId, const QString &awayMsg); - virtual QString userModes(UserId user, NetworkId networkId); - virtual void setUserModes(UserId user, NetworkId networkId, const QString &userModes); - - /* Buffer handling */ - virtual BufferInfo bufferInfo(UserId user, const NetworkId &networkId, BufferInfo::Type type, const QString &buffer = "", bool create = true); - virtual BufferInfo getBufferInfo(UserId user, const BufferId &bufferId); - virtual QList requestBuffers(UserId user); - virtual QList requestBufferIdsForNetwork(UserId user, NetworkId networkId); - virtual bool removeBuffer(const UserId &user, const BufferId &bufferId); - virtual bool renameBuffer(const UserId &user, const BufferId &bufferId, const QString &newName); - virtual bool mergeBuffersPermanently(const UserId &user, const BufferId &bufferId1, const BufferId &bufferId2); - virtual void setBufferLastSeenMsg(UserId user, const BufferId &bufferId, const MsgId &msgId); - virtual QHash bufferLastSeenMsgIds(UserId user); - virtual void setBufferMarkerLineMsg(UserId user, const BufferId &bufferId, const MsgId &msgId); - virtual QHash bufferMarkerLineMsgIds(UserId user); - - /* Message handling */ - virtual bool logMessage(Message &msg); - virtual bool logMessages(MessageList &msgs); - virtual QList requestMsgs(UserId user, BufferId bufferId, MsgId first = -1, MsgId last = -1, int limit = -1); - virtual QList requestAllMsgs(UserId user, MsgId first = -1, MsgId last = -1, int limit = -1); + /* General */ + + bool isAvailable() const; + QString displayName() const; + virtual inline QStringList setupKeys() const { return QStringList(); } + virtual inline QVariantMap setupDefaults() const { return QVariantMap(); } + QString description() const; + + // TODO: Add functions for configuring the backlog handling, i.e. defining auto-cleanup settings etc + + /* User handling */ + virtual UserId addUser(const QString &user, const QString &password); + virtual bool updateUser(UserId user, const QString &password); + virtual void renameUser(UserId user, const QString &newName); + virtual UserId validateUser(const QString &user, const QString &password); + virtual UserId getUserId(const QString &username); + virtual UserId internalUser(); + virtual void delUser(UserId user); + virtual void setUserSetting(UserId userId, const QString &settingName, const QVariant &data); + virtual QVariant getUserSetting(UserId userId, const QString &settingName, const QVariant &defaultData = QVariant()); + + /* Identity handling */ + virtual IdentityId createIdentity(UserId user, CoreIdentity &identity); + virtual bool updateIdentity(UserId user, const CoreIdentity &identity); + virtual void removeIdentity(UserId user, IdentityId identityId); + virtual QList identities(UserId user); + + /* Network handling */ + virtual NetworkId createNetwork(UserId user, const NetworkInfo &info); + virtual bool updateNetwork(UserId user, const NetworkInfo &info); + virtual bool removeNetwork(UserId user, const NetworkId &networkId); + virtual QList networks(UserId user); + virtual QList connectedNetworks(UserId user); + virtual void setNetworkConnected(UserId user, const NetworkId &networkId, bool isConnected); + + /* persistent channels */ + virtual QHash persistentChannels(UserId user, const NetworkId &networkId); + virtual void setChannelPersistent(UserId user, const NetworkId &networkId, const QString &channel, bool isJoined); + virtual void setPersistentChannelKey(UserId user, const NetworkId &networkId, const QString &channel, const QString &key); + + /* persistent user states */ + virtual QString awayMessage(UserId user, NetworkId networkId); + virtual void setAwayMessage(UserId user, NetworkId networkId, const QString &awayMsg); + virtual QString userModes(UserId user, NetworkId networkId); + virtual void setUserModes(UserId user, NetworkId networkId, const QString &userModes); + + /* Buffer handling */ + virtual BufferInfo bufferInfo(UserId user, const NetworkId &networkId, BufferInfo::Type type, const QString &buffer = "", bool create = true); + virtual BufferInfo getBufferInfo(UserId user, const BufferId &bufferId); + virtual QList requestBuffers(UserId user); + virtual QList requestBufferIdsForNetwork(UserId user, NetworkId networkId); + virtual bool removeBuffer(const UserId &user, const BufferId &bufferId); + virtual bool renameBuffer(const UserId &user, const BufferId &bufferId, const QString &newName); + virtual bool mergeBuffersPermanently(const UserId &user, const BufferId &bufferId1, const BufferId &bufferId2); + virtual void setBufferLastSeenMsg(UserId user, const BufferId &bufferId, const MsgId &msgId); + virtual QHash bufferLastSeenMsgIds(UserId user); + virtual void setBufferMarkerLineMsg(UserId user, const BufferId &bufferId, const MsgId &msgId); + virtual QHash bufferMarkerLineMsgIds(UserId user); + + /* Message handling */ + virtual bool logMessage(Message &msg); + virtual bool logMessages(MessageList &msgs); + virtual QList requestMsgs(UserId user, BufferId bufferId, MsgId first = -1, MsgId last = -1, int limit = -1); + virtual QList requestAllMsgs(UserId user, MsgId first = -1, MsgId last = -1, int limit = -1); protected: - inline virtual void setConnectionProperties(const QVariantMap & /* properties */) {} - inline virtual QString driverName() { return "QSQLITE"; } - inline virtual QString databaseName() { return backlogFile(); } - virtual int installedSchemaVersion(); - virtual bool updateSchemaVersion(int newVersion); - virtual bool setupSchemaVersion(int version); - bool safeExec(QSqlQuery &query, int retryCount = 0); + inline virtual void setConnectionProperties(const QVariantMap & /* properties */) {} + inline virtual QString driverName() { return "QSQLITE"; } + inline virtual QString databaseName() { return backlogFile(); } + virtual int installedSchemaVersion(); + virtual bool updateSchemaVersion(int newVersion); + virtual bool setupSchemaVersion(int version); + bool safeExec(QSqlQuery &query, int retryCount = 0); private: - static QString backlogFile(); - void bindNetworkInfo(QSqlQuery &query, const NetworkInfo &info); - void bindServerInfo(QSqlQuery &query, const Network::Server &server); - - inline void lockForRead() { _dbLock.lockForRead(); } - inline void lockForWrite() { _dbLock.lockForWrite(); } - inline void unlock() { _dbLock.unlock(); } - QReadWriteLock _dbLock; - static int _maxRetryCount; + static QString backlogFile(); + void bindNetworkInfo(QSqlQuery &query, const NetworkInfo &info); + void bindServerInfo(QSqlQuery &query, const Network::Server &server); + + inline void lockForRead() { _dbLock.lockForRead(); } + inline void lockForWrite() { _dbLock.lockForWrite(); } + inline void unlock() { _dbLock.unlock(); } + QReadWriteLock _dbLock; + static int _maxRetryCount; }; + // ======================================== // SqliteMigration // ======================================== -class SqliteMigrationReader : public SqliteStorage, public AbstractSqlMigrationReader { - Q_OBJECT +class SqliteMigrationReader : public SqliteStorage, public AbstractSqlMigrationReader +{ + Q_OBJECT public: - SqliteMigrationReader(); + SqliteMigrationReader(); - virtual bool readMo(QuasselUserMO &user); - virtual bool readMo(SenderMO &sender); - virtual bool readMo(IdentityMO &identity); - virtual bool readMo(IdentityNickMO &identityNick); - virtual bool readMo(NetworkMO &network); - virtual bool readMo(BufferMO &buffer); - virtual bool readMo(BacklogMO &backlog); - virtual bool readMo(IrcServerMO &ircserver); - virtual bool readMo(UserSettingMO &userSetting); + virtual bool readMo(QuasselUserMO &user); + virtual bool readMo(SenderMO &sender); + virtual bool readMo(IdentityMO &identity); + virtual bool readMo(IdentityNickMO &identityNick); + virtual bool readMo(NetworkMO &network); + virtual bool readMo(BufferMO &buffer); + virtual bool readMo(BacklogMO &backlog); + virtual bool readMo(IrcServerMO &ircserver); + virtual bool readMo(UserSettingMO &userSetting); - virtual bool prepareQuery(MigrationObject mo); + virtual bool prepareQuery(MigrationObject mo); - inline int stepSize() { return 50000; } + inline int stepSize() { return 50000; } protected: - virtual inline bool transaction() { return logDb().transaction(); } - virtual inline void rollback() { logDb().rollback(); } - virtual inline bool commit() { return logDb().commit(); } + virtual inline bool transaction() { return logDb().transaction(); } + virtual inline void rollback() { logDb().rollback(); } + virtual inline bool commit() { return logDb().commit(); } private: - void setMaxId(MigrationObject mo); - int _maxId; + void setMaxId(MigrationObject mo); + int _maxId; }; -inline AbstractSqlMigrationReader *SqliteStorage::createMigrationReader() { - return new SqliteMigrationReader(); + +inline AbstractSqlMigrationReader *SqliteStorage::createMigrationReader() +{ + return new SqliteMigrationReader(); } + #endif diff --git a/src/core/sslserver.cpp b/src/core/sslserver.cpp index 987db4ba..c31b507f 100644 --- a/src/core/sslserver.cpp +++ b/src/core/sslserver.cpp @@ -32,98 +32,106 @@ #ifdef HAVE_SSL SslServer::SslServer(QObject *parent) - : QTcpServer(parent), - _isCertValid(false) + : QTcpServer(parent), + _isCertValid(false) { - static bool sslWarningShown = false; - if(!setCertificate(Quassel::configDirPath() + "quasselCert.pem")) { - if(!sslWarningShown) { - quWarning() - << "SslServer: Unable to set certificate file\n" - << " Quassel Core will still work, but cannot provide SSL for client connections.\n" - << " Please see http://quassel-irc.org/faq/cert to learn how to enable SSL support."; - sslWarningShown=true; + static bool sslWarningShown = false; + if (!setCertificate(Quassel::configDirPath() + "quasselCert.pem")) { + if (!sslWarningShown) { + quWarning() + << "SslServer: Unable to set certificate file\n" + << " Quassel Core will still work, but cannot provide SSL for client connections.\n" + << " Please see http://quassel-irc.org/faq/cert to learn how to enable SSL support."; + sslWarningShown = true; + } } - } } -QTcpSocket *SslServer::nextPendingConnection() { - if(_pendingConnections.isEmpty()) - return 0; - else - return _pendingConnections.takeFirst(); + +QTcpSocket *SslServer::nextPendingConnection() +{ + if (_pendingConnections.isEmpty()) + return 0; + else + return _pendingConnections.takeFirst(); } -void SslServer::incomingConnection(int socketDescriptor) { - QSslSocket *serverSocket = new QSslSocket(this); - if(serverSocket->setSocketDescriptor(socketDescriptor)) { - if(isCertValid()) { - serverSocket->setLocalCertificate(_cert); - serverSocket->setPrivateKey(_key); - serverSocket->addCaCertificates(_ca); + +void SslServer::incomingConnection(int socketDescriptor) +{ + QSslSocket *serverSocket = new QSslSocket(this); + if (serverSocket->setSocketDescriptor(socketDescriptor)) { + if (isCertValid()) { + serverSocket->setLocalCertificate(_cert); + serverSocket->setPrivateKey(_key); + serverSocket->addCaCertificates(_ca); + } + _pendingConnections << serverSocket; + emit newConnection(); + } + else { + delete serverSocket; } - _pendingConnections << serverSocket; - emit newConnection(); - } else { - delete serverSocket; - } } -bool SslServer::setCertificate(const QString &path) { - _isCertValid = false; - - if(path.isEmpty()) - return false; - - QFile certFile(path); - if(!certFile.exists()) { - quWarning() << "SslServer: Certificate file" << qPrintable(path) << "does not exist"; - return false; - } - - if(!certFile.open(QIODevice::ReadOnly)) { - quWarning() - << "SslServer: Failed to open certificate file" << qPrintable(path) - << "error:" << certFile.error(); - return false; - } - - QList certList = QSslCertificate::fromDevice(&certFile); - - if (certList.isEmpty()) { - quWarning() << "SslServer: Certificate file doesn't contain a certificate"; - return false; - } - - _cert = certList[0]; - certList.removeFirst(); // remove server cert - - // store CA and intermediates certs - _ca = certList; - - if(!certFile.reset()) { - quWarning() << "SslServer: IO error reading certificate file"; - return false; - } - - _key = QSslKey(&certFile, QSsl::Rsa); - certFile.close(); - - if(_cert.isNull()) { - quWarning() << "SslServer:" << qPrintable(path) << "contains no certificate data"; - return false; - } - if(!_cert.isValid()) { - quWarning() << "SslServer: Invalid certificate (most likely expired)"; - } - if(_key.isNull()) { - quWarning() << "SslServer:" << qPrintable(path) << "contains no key data"; - return false; - } - - _isCertValid = true; - - return _isCertValid; + +bool SslServer::setCertificate(const QString &path) +{ + _isCertValid = false; + + if (path.isEmpty()) + return false; + + QFile certFile(path); + if (!certFile.exists()) { + quWarning() << "SslServer: Certificate file" << qPrintable(path) << "does not exist"; + return false; + } + + if (!certFile.open(QIODevice::ReadOnly)) { + quWarning() + << "SslServer: Failed to open certificate file" << qPrintable(path) + << "error:" << certFile.error(); + return false; + } + + QList certList = QSslCertificate::fromDevice(&certFile); + + if (certList.isEmpty()) { + quWarning() << "SslServer: Certificate file doesn't contain a certificate"; + return false; + } + + _cert = certList[0]; + certList.removeFirst(); // remove server cert + + // store CA and intermediates certs + _ca = certList; + + if (!certFile.reset()) { + quWarning() << "SslServer: IO error reading certificate file"; + return false; + } + + _key = QSslKey(&certFile, QSsl::Rsa); + certFile.close(); + + if (_cert.isNull()) { + quWarning() << "SslServer:" << qPrintable(path) << "contains no certificate data"; + return false; + } + if (!_cert.isValid()) { + quWarning() << "SslServer: Invalid certificate (most likely expired)"; + } + if (_key.isNull()) { + quWarning() << "SslServer:" << qPrintable(path) << "contains no key data"; + return false; + } + + _isCertValid = true; + + return _isCertValid; } + #endif // HAVE_SSL diff --git a/src/core/sslserver.h b/src/core/sslserver.h index d0efde21..50b548c7 100644 --- a/src/core/sslserver.h +++ b/src/core/sslserver.h @@ -28,31 +28,33 @@ #include #include -class SslServer : public QTcpServer { - Q_OBJECT +class SslServer : public QTcpServer +{ + Q_OBJECT public: - SslServer(QObject *parent = 0); + SslServer(QObject *parent = 0); - virtual inline bool hasPendingConnections() const { return !_pendingConnections.isEmpty(); } - virtual QTcpSocket *nextPendingConnection(); + virtual inline bool hasPendingConnections() const { return !_pendingConnections.isEmpty(); } + virtual QTcpSocket *nextPendingConnection(); - virtual inline const QSslCertificate &certificate() const { return _cert; } - virtual inline const QSslKey &key() const { return _key; } - virtual inline bool isCertValid() const { return _isCertValid; } + virtual inline const QSslCertificate &certificate() const { return _cert; } + virtual inline const QSslKey &key() const { return _key; } + virtual inline bool isCertValid() const { return _isCertValid; } protected: - virtual void incomingConnection(int socketDescriptor); - virtual bool setCertificate(const QString &path); + virtual void incomingConnection(int socketDescriptor); + virtual bool setCertificate(const QString &path); private: - QLinkedList _pendingConnections; - QSslCertificate _cert; - QSslKey _key; - QList _ca; - bool _isCertValid; + QLinkedList _pendingConnections; + QSslCertificate _cert; + QSslKey _key; + QList _ca; + bool _isCertValid; }; + #endif //HAVE_SSL #endif //SSLSERVER_H diff --git a/src/core/storage.cpp b/src/core/storage.cpp index 0fbd3fc2..57c23ae5 100644 --- a/src/core/storage.cpp +++ b/src/core/storage.cpp @@ -23,10 +23,12 @@ #include Storage::Storage(QObject *parent) - : QObject(parent) + : QObject(parent) { } -QString Storage::cryptedPassword(const QString &password) { - return QString(QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Sha1).toHex()); + +QString Storage::cryptedPassword(const QString &password) +{ + return QString(QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Sha1).toHex()); } diff --git a/src/core/storage.h b/src/core/storage.h index 15616731..f5cf556e 100644 --- a/src/core/storage.h +++ b/src/core/storage.h @@ -28,394 +28,390 @@ #include "message.h" #include "network.h" -class Storage : public QObject { - Q_OBJECT +class Storage : public QObject +{ + Q_OBJECT public: - Storage(QObject *parent = 0); - virtual ~Storage() {}; + Storage(QObject *parent = 0); + virtual ~Storage() {}; - enum State { - IsReady, // ready to go - NeedsSetup, // need basic setup (ask the user for input) - NotAvailable // remove the storage backend from the list of avaliable backends - }; + enum State { + IsReady, // ready to go + NeedsSetup, // need basic setup (ask the user for input) + NotAvailable // remove the storage backend from the list of avaliable backends + }; public slots: - /* General */ - - //! Check if the storage type is available. - /** A storage subclass should return true if it can be successfully used, i.e. if all - * prerequisites are in place (e.g. we have an appropriate DB driver etc.). - * \return True if and only if the storage class can be successfully used. - */ - virtual bool isAvailable() const = 0; - - //! Returns the display name of the storage backend - /** \return A string that can be used by the client to name the storage backend */ - virtual QString displayName() const = 0; - - //! Returns a description of this storage backend - /** \return A string that can be displayed by the client to describe the storage backend */ - virtual QString description() const = 0; - - //! Returns a list of properties required to use the storage backend - virtual QStringList setupKeys() const = 0; - - //! Returns a map where the keys are are properties to use the storage backend - /* the values are QVariants with default values */ - virtual QVariantMap setupDefaults() const = 0; - - - //! Setup the storage provider. - /** This prepares the storage provider (e.g. create tables, etc.) for use within Quassel. - * \param settings Hostname, port, username, password, ... - * \return True if and only if the storage provider was initialized successfully. - */ - virtual bool setup(const QVariantMap &settings = QVariantMap()) = 0; - - //! Initialize the storage provider - /** \param settings Hostname, port, username, password, ... - * \return the State the storage backend is now in (see Storage::State) - */ - virtual State init(const QVariantMap &settings = QVariantMap()) = 0; - - //! Makes temp data persistent - /** This Method is periodically called by the Quassel Core to make temporary - * data persistant. This reduces the data loss drastically in the - * unlikely case of a Core crash. - */ - virtual void sync() = 0; - - // TODO: Add functions for configuring the backlog handling, i.e. defining auto-cleanup settings etc - - /* User handling */ - - //! Add a new core user to the storage. - /** \param user The username of the new user - * \param password The cleartext password for the new user - * \return The new user's UserId - */ - virtual UserId addUser(const QString &user, const QString &password) = 0; - - //! Update a core user's password. - /** \param user The user's id - * \param password The user's new password - * \return true on success. - */ - virtual bool updateUser(UserId user, const QString &password) = 0; - - //! Rename a user - /** \param user The user's id - * \param newName The user's new name - */ - virtual void renameUser(UserId user, const QString &newName) = 0; - - //! Validate a username with a given password. - /** \param user The username to validate - * \param password The user's alleged password - * \return A valid UserId if the password matches the username; 0 else - */ - virtual UserId validateUser(const QString &user, const QString &password) = 0; - - //! Check if a user with given username exists. Do not use for login purposes! - /** \param username The username to validate - * \return A valid UserId if the user exists; 0 else - */ - virtual UserId getUserId(const QString &username) = 0; - - //! Determine the UserId of the internal user - /** \return A valid UserId if the password matches the username; 0 else - */ - virtual UserId internalUser() = 0; - - //! Remove a core user from storage. - /** \param user The userid to delete - */ - virtual void delUser(UserId user) = 0; - - //! Store a user setting persistently - /** - * \param userId The users Id - * \param settingName The Name of the Setting - * \param data The Value - */ - virtual void setUserSetting(UserId userId, const QString &settingName, const QVariant &data) = 0; - - //! Retrieve a persistent user setting - /** - * \param userId The users Id - * \param settingName The Name of the Setting - * \param default Value to return in case it's unset. - * \return the Value of the Setting or the default value if it is unset. - */ - virtual QVariant getUserSetting(UserId userId, const QString &settingName, const QVariant &data = QVariant()) = 0; - - /* Identity handling */ - virtual IdentityId createIdentity(UserId user, CoreIdentity &identity) = 0; - virtual bool updateIdentity(UserId user, const CoreIdentity &identity) = 0; - virtual void removeIdentity(UserId user, IdentityId identityId) = 0; - virtual QList identities(UserId user) = 0; - - /* Network handling */ - - //! Create a new Network in the storage backend and return it unique Id - /** \param user The core user who owns this network - * \param networkInfo The networkInfo holding the network definition - * \return the NetworkId of the newly created Network. Possibly invalid. - */ - virtual NetworkId createNetwork(UserId user, const NetworkInfo &info) = 0; - - //! Apply the changes to NetworkInfo info to the storage engine - /** - * \param user The core user - * \param networkInfo The Updated NetworkInfo - * \return true if successfull. - */ - virtual bool updateNetwork(UserId user, const NetworkInfo &info) = 0; - - //! Permanently remove a Network and all the data associated with it. - /** \note This method is thredsafe. - * - * \param user The core user - * \param networkId The network to delete - * \return true if successfull. - */ - virtual bool removeNetwork(UserId user, const NetworkId &networkId) = 0; - - //! Returns a list of all NetworkInfos for the given UserId user - /** \note This method is thredsafe. - * - * \param user The core user - * \return QList. - */ - virtual QList networks(UserId user) = 0; - - //! Get a list of Networks to restore - /** Return a list of networks the user was connected at the time of core shutdown - * \note This method is threadsafe. - * - * \param user The User Id in question - */ - virtual QList connectedNetworks(UserId user) = 0; - - //! Update the connected state of a network - /** \note This method is threadsafe - * - * \param user The Id of the networks owner - * \param networkId The Id of the network - * \param isConnected whether the network is connected or not - */ - virtual void setNetworkConnected(UserId user, const NetworkId &networkId, bool isConnected) = 0; - - //! Get a hash of channels with their channel keys for a given network - /** The keys are channel names and values are passwords (possibly empty) - * \note This method is threadsafe - * - * \param user The id of the networks owner - * \param networkId The Id of the network - */ - virtual QHash persistentChannels(UserId user, const NetworkId &networkId) = 0; - - //! Update the connected state of a channel - /** \note This method is threadsafe - * - * \param user The Id of the networks owner - * \param networkId The Id of the network - * \param channel The name of the channel - * \param isJoined whether the channel is connected or not - */ - virtual void setChannelPersistent(UserId user, const NetworkId &networkId, const QString &channel, bool isJoined) = 0; - - //! Update the key of a channel - /** \note This method is threadsafe - * - * \param user The Id of the networks owner - * \param networkId The Id of the network - * \param channel The name of the channel - * \param key The key of the channel (possibly empty) - */ - virtual void setPersistentChannelKey(UserId user, const NetworkId &networkId, const QString &channel, const QString &key) = 0; - - //! retrieve last known away message for session restore - /** \note This method is threadsafe - * - * \param user The Id of the networks owner - * \param networkId The Id of the network - */ - virtual QString awayMessage(UserId user, NetworkId networkId) = 0; - - //! Make away message persistent for session restore - /** \note This method is threadsafe - * - * \param user The Id of the networks owner - * \param networkId The Id of the network - * \param awayMsg The current away message of own user - */ - virtual void setAwayMessage(UserId user, NetworkId networkId, const QString &awayMsg) = 0; - - - //! retrieve last known user mode for session restore - /** \note This method is threadsafe - * - * \param user The Id of the networks owner - * \param networkId The Id of the network - */ - virtual QString userModes(UserId user, NetworkId networkId) = 0; - - //! Make our user modes persistent for session restore - /** \note This method is threadsafe - * - * \param user The Id of the networks owner - * \param networkId The Id of the network - * \param userModes The current user modes of own user - */ - virtual void setUserModes(UserId user, NetworkId networkId, const QString &userModes) = 0; - - - /* Buffer handling */ - - //! Get the unique BufferInfo for the given combination of network and buffername for a user. - /** \param user The core user who owns this buffername - * \param networkId The network id - * \param type The type of the buffer (StatusBuffer, Channel, etc.) - * \param buffer The buffer name (if empty, the net's status buffer is returned) - * \param create Whether or not the buffer should be created if it doesnt exist - * \return The BufferInfo corresponding to the given network and buffer name, or an invalid BufferInfo if not found - */ - virtual BufferInfo bufferInfo(UserId user, const NetworkId &networkId, BufferInfo::Type type, const QString &buffer = "", bool create = true) = 0; - - //! Get the unique BufferInfo for a bufferId - /** \param user The core user who owns this buffername - * \param bufferId The id of the buffer - * \return The BufferInfo corresponding to the given buffer id, or an invalid BufferInfo if not found. - */ - virtual BufferInfo getBufferInfo(UserId user, const BufferId &bufferId) = 0; - - //! Request a list of all buffers known to a user. - /** This method is used to get a list of all buffers we have stored a backlog from. - * \param user The user whose buffers we request - * \return A list of the BufferInfos for all buffers as requested - */ - virtual QList requestBuffers(UserId user) = 0; - - //! Request a list of BufferIds for a given NetworkId - /** \note This method is threadsafe. - * - * \param user The user whose buffers we request - * \param networkId The NetworkId of the network in question - * \return List of BufferIds belonging to the Network - */ - virtual QList requestBufferIdsForNetwork(UserId user, NetworkId networkId) = 0; - - //! Remove permanently a buffer and it's content from the storage backend - /** This call cannot be reverted! - * \param user The user who is the owner of the buffer - * \param bufferId The bufferId - * \return true if successfull - */ - virtual bool removeBuffer(const UserId &user, const BufferId &bufferId) = 0; - - - //! Rename a Buffer - /** \note This method is threadsafe. - * \param user The id of the buffer owner - * \param bufferId The bufferId - * \param newName The new name of the buffer - * \return true if successfull - */ - virtual bool renameBuffer(const UserId &user, const BufferId &bufferId, const QString &newName) = 0; - - //! Merge the content of two Buffers permanently. This cannot be reversed! - /** \note This method is threadsafe. - * \param user The id of the buffer owner - * \param bufferId1 The bufferId of the remaining buffer - * \param bufferId2 The buffer that is about to be removed - * \return true if successfull - */ - virtual bool mergeBuffersPermanently(const UserId &user, const BufferId &bufferId1, const BufferId &bufferId2) = 0; - - //! Update the LastSeenDate for a Buffer - /** This Method is used to make the LastSeenDate of a Buffer persistent - * \param user The Owner of that Buffer - * \param bufferId The buffer id - * \param MsgId The Message id of the message that has been just seen - */ - virtual void setBufferLastSeenMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) = 0; - - //! Get a Hash of all last seen message ids - /** This Method is called when the Quassel Core is started to restore the lastSeenMsgIds - * \param user The Owner of the buffers - */ - virtual QHash bufferLastSeenMsgIds(UserId user) = 0; - - //! Update the MarkerLineMsgId for a Buffer - /** This Method is used to make the marker line position of a Buffer persistent - * \note This method is threadsafe. - * - * \param user The Owner of that Buffer - * \param bufferId The buffer id - * \param MsgId The Message id where the marker line should be placed - */ - virtual void setBufferMarkerLineMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) = 0; - - //! Get a Hash of all marker line message ids - /** This Method is called when the Quassel Core is started to restore the MarkerLineMsgIds - * \note This method is threadsafe. - * - * \param user The Owner of the buffers - */ - virtual QHash bufferMarkerLineMsgIds(UserId user) = 0; - - - /* Message handling */ - - //! Store a Message in the storage backend and set its unique Id. - /** \param msg The message object to be stored - * \return true on success - */ - virtual bool logMessage(Message &msg) = 0; - - //! Store a list of Messages in the storage backend and set their unique Id. - /** \param msgs The list message objects to be stored - * \return true on success - */ - virtual bool logMessages(MessageList &msgs) = 0; - - //! Request a certain number messages stored in a given buffer. - /** \param buffer The buffer we request messages from - * \param first if != -1 return only messages with a MsgId >= first - * \param last if != -1 return only messages with a MsgId < last - * \param limit if != -1 limit the returned list to a max of \limit entries - * \return The requested list of messages - */ - virtual QList requestMsgs(UserId user, BufferId bufferId, MsgId first = -1, MsgId last = -1, int limit = -1) = 0; - - //! Request a certain number of messages across all buffers - /** \param first if != -1 return only messages with a MsgId >= first - * \param last if != -1 return only messages with a MsgId < last - * \param limit Max amount of messages - * \return The requested list of messages - */ - virtual QList requestAllMsgs(UserId user, MsgId first = -1, MsgId last = -1, int limit = -1) = 0; + /* General */ + + //! Check if the storage type is available. + /** A storage subclass should return true if it can be successfully used, i.e. if all + * prerequisites are in place (e.g. we have an appropriate DB driver etc.). + * \return True if and only if the storage class can be successfully used. + */ + virtual bool isAvailable() const = 0; + + //! Returns the display name of the storage backend + /** \return A string that can be used by the client to name the storage backend */ + virtual QString displayName() const = 0; + + //! Returns a description of this storage backend + /** \return A string that can be displayed by the client to describe the storage backend */ + virtual QString description() const = 0; + + //! Returns a list of properties required to use the storage backend + virtual QStringList setupKeys() const = 0; + + //! Returns a map where the keys are are properties to use the storage backend + /* the values are QVariants with default values */ + virtual QVariantMap setupDefaults() const = 0; + + //! Setup the storage provider. + /** This prepares the storage provider (e.g. create tables, etc.) for use within Quassel. + * \param settings Hostname, port, username, password, ... + * \return True if and only if the storage provider was initialized successfully. + */ + virtual bool setup(const QVariantMap &settings = QVariantMap()) = 0; + + //! Initialize the storage provider + /** \param settings Hostname, port, username, password, ... + * \return the State the storage backend is now in (see Storage::State) + */ + virtual State init(const QVariantMap &settings = QVariantMap()) = 0; + + //! Makes temp data persistent + /** This Method is periodically called by the Quassel Core to make temporary + * data persistant. This reduces the data loss drastically in the + * unlikely case of a Core crash. + */ + virtual void sync() = 0; + + // TODO: Add functions for configuring the backlog handling, i.e. defining auto-cleanup settings etc + + /* User handling */ + + //! Add a new core user to the storage. + /** \param user The username of the new user + * \param password The cleartext password for the new user + * \return The new user's UserId + */ + virtual UserId addUser(const QString &user, const QString &password) = 0; + + //! Update a core user's password. + /** \param user The user's id + * \param password The user's new password + * \return true on success. + */ + virtual bool updateUser(UserId user, const QString &password) = 0; + + //! Rename a user + /** \param user The user's id + * \param newName The user's new name + */ + virtual void renameUser(UserId user, const QString &newName) = 0; + + //! Validate a username with a given password. + /** \param user The username to validate + * \param password The user's alleged password + * \return A valid UserId if the password matches the username; 0 else + */ + virtual UserId validateUser(const QString &user, const QString &password) = 0; + + //! Check if a user with given username exists. Do not use for login purposes! + /** \param username The username to validate + * \return A valid UserId if the user exists; 0 else + */ + virtual UserId getUserId(const QString &username) = 0; + + //! Determine the UserId of the internal user + /** \return A valid UserId if the password matches the username; 0 else + */ + virtual UserId internalUser() = 0; + + //! Remove a core user from storage. + /** \param user The userid to delete + */ + virtual void delUser(UserId user) = 0; + + //! Store a user setting persistently + /** + * \param userId The users Id + * \param settingName The Name of the Setting + * \param data The Value + */ + virtual void setUserSetting(UserId userId, const QString &settingName, const QVariant &data) = 0; + + //! Retrieve a persistent user setting + /** + * \param userId The users Id + * \param settingName The Name of the Setting + * \param default Value to return in case it's unset. + * \return the Value of the Setting or the default value if it is unset. + */ + virtual QVariant getUserSetting(UserId userId, const QString &settingName, const QVariant &data = QVariant()) = 0; + + /* Identity handling */ + virtual IdentityId createIdentity(UserId user, CoreIdentity &identity) = 0; + virtual bool updateIdentity(UserId user, const CoreIdentity &identity) = 0; + virtual void removeIdentity(UserId user, IdentityId identityId) = 0; + virtual QList identities(UserId user) = 0; + + /* Network handling */ + + //! Create a new Network in the storage backend and return it unique Id + /** \param user The core user who owns this network + * \param networkInfo The networkInfo holding the network definition + * \return the NetworkId of the newly created Network. Possibly invalid. + */ + virtual NetworkId createNetwork(UserId user, const NetworkInfo &info) = 0; + + //! Apply the changes to NetworkInfo info to the storage engine + /** + * \param user The core user + * \param networkInfo The Updated NetworkInfo + * \return true if successfull. + */ + virtual bool updateNetwork(UserId user, const NetworkInfo &info) = 0; + + //! Permanently remove a Network and all the data associated with it. + /** \note This method is thredsafe. + * + * \param user The core user + * \param networkId The network to delete + * \return true if successfull. + */ + virtual bool removeNetwork(UserId user, const NetworkId &networkId) = 0; + + //! Returns a list of all NetworkInfos for the given UserId user + /** \note This method is thredsafe. + * + * \param user The core user + * \return QList. + */ + virtual QList networks(UserId user) = 0; + + //! Get a list of Networks to restore + /** Return a list of networks the user was connected at the time of core shutdown + * \note This method is threadsafe. + * + * \param user The User Id in question + */ + virtual QList connectedNetworks(UserId user) = 0; + + //! Update the connected state of a network + /** \note This method is threadsafe + * + * \param user The Id of the networks owner + * \param networkId The Id of the network + * \param isConnected whether the network is connected or not + */ + virtual void setNetworkConnected(UserId user, const NetworkId &networkId, bool isConnected) = 0; + + //! Get a hash of channels with their channel keys for a given network + /** The keys are channel names and values are passwords (possibly empty) + * \note This method is threadsafe + * + * \param user The id of the networks owner + * \param networkId The Id of the network + */ + virtual QHash persistentChannels(UserId user, const NetworkId &networkId) = 0; + + //! Update the connected state of a channel + /** \note This method is threadsafe + * + * \param user The Id of the networks owner + * \param networkId The Id of the network + * \param channel The name of the channel + * \param isJoined whether the channel is connected or not + */ + virtual void setChannelPersistent(UserId user, const NetworkId &networkId, const QString &channel, bool isJoined) = 0; + + //! Update the key of a channel + /** \note This method is threadsafe + * + * \param user The Id of the networks owner + * \param networkId The Id of the network + * \param channel The name of the channel + * \param key The key of the channel (possibly empty) + */ + virtual void setPersistentChannelKey(UserId user, const NetworkId &networkId, const QString &channel, const QString &key) = 0; + + //! retrieve last known away message for session restore + /** \note This method is threadsafe + * + * \param user The Id of the networks owner + * \param networkId The Id of the network + */ + virtual QString awayMessage(UserId user, NetworkId networkId) = 0; + + //! Make away message persistent for session restore + /** \note This method is threadsafe + * + * \param user The Id of the networks owner + * \param networkId The Id of the network + * \param awayMsg The current away message of own user + */ + virtual void setAwayMessage(UserId user, NetworkId networkId, const QString &awayMsg) = 0; + + //! retrieve last known user mode for session restore + /** \note This method is threadsafe + * + * \param user The Id of the networks owner + * \param networkId The Id of the network + */ + virtual QString userModes(UserId user, NetworkId networkId) = 0; + + //! Make our user modes persistent for session restore + /** \note This method is threadsafe + * + * \param user The Id of the networks owner + * \param networkId The Id of the network + * \param userModes The current user modes of own user + */ + virtual void setUserModes(UserId user, NetworkId networkId, const QString &userModes) = 0; + + /* Buffer handling */ + + //! Get the unique BufferInfo for the given combination of network and buffername for a user. + /** \param user The core user who owns this buffername + * \param networkId The network id + * \param type The type of the buffer (StatusBuffer, Channel, etc.) + * \param buffer The buffer name (if empty, the net's status buffer is returned) + * \param create Whether or not the buffer should be created if it doesnt exist + * \return The BufferInfo corresponding to the given network and buffer name, or an invalid BufferInfo if not found + */ + virtual BufferInfo bufferInfo(UserId user, const NetworkId &networkId, BufferInfo::Type type, const QString &buffer = "", bool create = true) = 0; + + //! Get the unique BufferInfo for a bufferId + /** \param user The core user who owns this buffername + * \param bufferId The id of the buffer + * \return The BufferInfo corresponding to the given buffer id, or an invalid BufferInfo if not found. + */ + virtual BufferInfo getBufferInfo(UserId user, const BufferId &bufferId) = 0; + + //! Request a list of all buffers known to a user. + /** This method is used to get a list of all buffers we have stored a backlog from. + * \param user The user whose buffers we request + * \return A list of the BufferInfos for all buffers as requested + */ + virtual QList requestBuffers(UserId user) = 0; + + //! Request a list of BufferIds for a given NetworkId + /** \note This method is threadsafe. + * + * \param user The user whose buffers we request + * \param networkId The NetworkId of the network in question + * \return List of BufferIds belonging to the Network + */ + virtual QList requestBufferIdsForNetwork(UserId user, NetworkId networkId) = 0; + + //! Remove permanently a buffer and it's content from the storage backend + /** This call cannot be reverted! + * \param user The user who is the owner of the buffer + * \param bufferId The bufferId + * \return true if successfull + */ + virtual bool removeBuffer(const UserId &user, const BufferId &bufferId) = 0; + + //! Rename a Buffer + /** \note This method is threadsafe. + * \param user The id of the buffer owner + * \param bufferId The bufferId + * \param newName The new name of the buffer + * \return true if successfull + */ + virtual bool renameBuffer(const UserId &user, const BufferId &bufferId, const QString &newName) = 0; + + //! Merge the content of two Buffers permanently. This cannot be reversed! + /** \note This method is threadsafe. + * \param user The id of the buffer owner + * \param bufferId1 The bufferId of the remaining buffer + * \param bufferId2 The buffer that is about to be removed + * \return true if successfull + */ + virtual bool mergeBuffersPermanently(const UserId &user, const BufferId &bufferId1, const BufferId &bufferId2) = 0; + + //! Update the LastSeenDate for a Buffer + /** This Method is used to make the LastSeenDate of a Buffer persistent + * \param user The Owner of that Buffer + * \param bufferId The buffer id + * \param MsgId The Message id of the message that has been just seen + */ + virtual void setBufferLastSeenMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) = 0; + + //! Get a Hash of all last seen message ids + /** This Method is called when the Quassel Core is started to restore the lastSeenMsgIds + * \param user The Owner of the buffers + */ + virtual QHash bufferLastSeenMsgIds(UserId user) = 0; + + //! Update the MarkerLineMsgId for a Buffer + /** This Method is used to make the marker line position of a Buffer persistent + * \note This method is threadsafe. + * + * \param user The Owner of that Buffer + * \param bufferId The buffer id + * \param MsgId The Message id where the marker line should be placed + */ + virtual void setBufferMarkerLineMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) = 0; + + //! Get a Hash of all marker line message ids + /** This Method is called when the Quassel Core is started to restore the MarkerLineMsgIds + * \note This method is threadsafe. + * + * \param user The Owner of the buffers + */ + virtual QHash bufferMarkerLineMsgIds(UserId user) = 0; + + /* Message handling */ + + //! Store a Message in the storage backend and set its unique Id. + /** \param msg The message object to be stored + * \return true on success + */ + virtual bool logMessage(Message &msg) = 0; + + //! Store a list of Messages in the storage backend and set their unique Id. + /** \param msgs The list message objects to be stored + * \return true on success + */ + virtual bool logMessages(MessageList &msgs) = 0; + + //! Request a certain number messages stored in a given buffer. + /** \param buffer The buffer we request messages from + * \param first if != -1 return only messages with a MsgId >= first + * \param last if != -1 return only messages with a MsgId < last + * \param limit if != -1 limit the returned list to a max of \limit entries + * \return The requested list of messages + */ + virtual QList requestMsgs(UserId user, BufferId bufferId, MsgId first = -1, MsgId last = -1, int limit = -1) = 0; + + //! Request a certain number of messages across all buffers + /** \param first if != -1 return only messages with a MsgId >= first + * \param last if != -1 return only messages with a MsgId < last + * \param limit Max amount of messages + * \return The requested list of messages + */ + virtual QList requestAllMsgs(UserId user, MsgId first = -1, MsgId last = -1, int limit = -1) = 0; signals: - //! Sent when a new BufferInfo is created, or an existing one changed somehow. - void bufferInfoUpdated(UserId user, const BufferInfo &); - //! Sent when a Buffer was renamed - void bufferRenamed(const QString &newName, const QString &oldName); - //! Sent when a new user has been added - void userAdded(UserId, const QString &username); - //! Sent when a user has been renamed - void userRenamed(UserId, const QString &newname); - //! Sent when a user has been removed - void userRemoved(UserId); + //! Sent when a new BufferInfo is created, or an existing one changed somehow. + void bufferInfoUpdated(UserId user, const BufferInfo &); + //! Sent when a Buffer was renamed + void bufferRenamed(const QString &newName, const QString &oldName); + //! Sent when a new user has been added + void userAdded(UserId, const QString &username); + //! Sent when a user has been renamed + void userRenamed(UserId, const QString &newname); + //! Sent when a user has been removed + void userRemoved(UserId); protected: - //! when implementing a storage handler, use this method to crypt user passwords. - /** This guarantees compatibility with other storage handlers and allows easy migration - */ - QString cryptedPassword(const QString &password); + //! when implementing a storage handler, use this method to crypt user passwords. + /** This guarantees compatibility with other storage handlers and allows easy migration + */ + QString cryptedPassword(const QString &password); }; diff --git a/src/qtui/aboutdlg.cpp b/src/qtui/aboutdlg.cpp index 23f58d22..2d6b30c6 100644 --- a/src/qtui/aboutdlg.cpp +++ b/src/qtui/aboutdlg.cpp @@ -25,147 +25,156 @@ #include "iconloader.h" #include "quassel.h" -AboutDlg::AboutDlg(QWidget *parent) : QDialog(parent) { - ui.setupUi(this); - ui.quasselLogo->setPixmap(DesktopIcon("quassel", IconLoader::SizeHuge)); - - ui.versionLabel->setText(QString(tr("Version: %1
Protocol version: %2
Built: %3")) - .arg(Quassel::buildInfo().fancyVersionString) - .arg(Quassel::buildInfo().protocolVersion) - .arg(Quassel::buildInfo().buildDate)); - ui.aboutTextBrowser->setHtml(about()); - ui.authorTextBrowser->setHtml(authors()); - ui.contributorTextBrowser->setHtml(contributors()); - ui.thanksToTextBrowser->setHtml(thanksTo()); - - setWindowIcon(Icon("quassel")); +AboutDlg::AboutDlg(QWidget *parent) : QDialog(parent) +{ + ui.setupUi(this); + ui.quasselLogo->setPixmap(DesktopIcon("quassel", IconLoader::SizeHuge)); + + ui.versionLabel->setText(QString(tr("Version: %1
Protocol version: %2
Built: %3")) + .arg(Quassel::buildInfo().fancyVersionString) + .arg(Quassel::buildInfo().protocolVersion) + .arg(Quassel::buildInfo().buildDate)); + ui.aboutTextBrowser->setHtml(about()); + ui.authorTextBrowser->setHtml(authors()); + ui.contributorTextBrowser->setHtml(contributors()); + ui.thanksToTextBrowser->setHtml(thanksTo()); + + setWindowIcon(Icon("quassel")); } -QString AboutDlg::about() const { - QString res; - res = tr("A modern, distributed IRC Client

" - "©2005-2012 by the Quassel Project
" - "
http://quassel-irc.org
" - "#quassel on Freenode

" - "Quassel IRC is dual-licensed under GPLv2 and " - "GPLv3.
" - "Most icons are © by the Oxygen Team and used under the " - "LGPL.

" - "Please use http://bugs.quassel-irc.org to report bugs." - ); - - return res; + +QString AboutDlg::about() const +{ + QString res; + res = tr("A modern, distributed IRC Client

" + "©2005-2012 by the Quassel Project
" + "http://quassel-irc.org
" + "#quassel on Freenode

" + "Quassel IRC is dual-licensed under GPLv2 and " + "GPLv3.
" + "Most icons are © by the Oxygen Team and used under the " + "LGPL.

" + "Please use http://bugs.quassel-irc.org to report bugs." + ); + + return res; } -QString AboutDlg::authors() const { - QString res; - res = tr("Quassel IRC is mainly developed by:") + - "
" - "
Manuel \"Sputnick\" Nickschas
sput@quassel-irc.org
" - "Project Founder, Lead Developer
" - "
Marcus \"EgS\" Eggenberger
egs@quassel-irc.org
" - "Project Motivator, Lead Developer, Mac Maintainer
" - "
Alexander \"phon\" von Renteln
phon@quassel-irc.org
" - "Developer, Windows Maintainer
" - "
"; - - return res; + +QString AboutDlg::authors() const +{ + QString res; + res = tr("Quassel IRC is mainly developed by:") + + "
" + "
Manuel \"Sputnick\" Nickschas
sput@quassel-irc.org
" + "Project Founder, Lead Developer
" + "
Marcus \"EgS\" Eggenberger
egs@quassel-irc.org
" + "Project Motivator, Lead Developer, Mac Maintainer
" + "
Alexander \"phon\" von Renteln
phon@quassel-irc.org
" + "Developer, Windows Maintainer
" + "
"; + + return res; } -QString AboutDlg::contributors() const { - QString res; - res = tr("We would like to thank the following contributors (in alphabetical order) and everybody we forgot to mention here:") - + QString::fromUtf8("
" - "
" - "
Daniel \"al\" Albers
Master Of Translation, many fixes and enhancements
" - "
Terje \"tan\" Andersen
Norwegian translation, documentation
" - "
Jens \"amiconn\" Arnold
Postgres migration fixes
" - "
Rafael \"EagleScreen\" Belmonte
Spanish translation
" - "
Bruno Brigras
Crash fixes
" - "
Theo \"tampakrap\" Chatzimichos
Greek translation
" - "
Yuri Chornoivan
Ukrainian translation
" - "
Tomáš \"scarabeus\" Chvátal
Czech translation
" - "
\"Condex\"
Galician translation
" - "
Joshua \"tvakah\" Corbin
Various fixes
" - "
Matthias \"pennywise\" Coy
German translation
" - "
Chris \"stitch\" Fuenty
SASL support
" - "
Kevin \"KRF\" Funk
German translation
" - "
Fabiano \"elbryan\" Francesconi
Italian translation
" - "
Aurélien \"agateau\" Gâteau
Message Indicator support
" - "
Marco \"kaffeedoktor\" Genise
Ideas, hacking, motivation
" - "
Sjors \"dazjorz\" Gielen
Fixes
" - "
Sebastian \"seezer\" Goth
Many improvements and features
" - "
Michael \"brot\" Groh
German translation, fixes
" - "
H. İbrahim \"igungor\" Güngör
Turkish translation
" - "
Edward Hades
Russian translation
" - "
John \"nox\" Hand
Former All-Seeing Eye logo
" - "
Jonas \"Dante\" Heese
Project founder, various improvements
" - "
Thomas \"Datafreak\" Hogh
Windows builder
" - "
Johannes \"j0hu\" Huber
Many fixes and features, bug triaging
" - "
Scott \"ScottK\" Kitterman
Kubuntu nightly packager, (packaging/build system) bughunter
" - "
Paul \"Haudrauf\" Klumpp
Initial design and mainwindow layout
" - "
Maia Kozheva
Russian translation
" - "
Patrick \"bonsaikitten\" Lauer
Gentoo packaging
" - "
Chris \"Fish-Face\" Le Sueur
Various fixes and improvements
" - "
Hendrik \"nevcairiel\" Leppkes
Various features
" - "
Martin \"m4yer\" Mayer
German translation
" - "
Daniel E. Moctezuma
Japanese translation
" - "
Chris \"kode54\" Moeller
Various fixes and improvements
" - "
Thomas Müller
Fixes, Debian packaging
" - "
Gábor \"ELITE_x\" Németh
Hungarian translation
" - "
Marco \"Quizzlo\" Paolone
Italian translation
" - "
Bas \"Tucos\" Pape
Various fixes and improvements
" - "
Bruno Patri
French translation
" - "
Drew \"LinuxDolt\" Patridge
BluesTheme stylesheet
" - "
Celeste \"seele\" Paul
Usability Queen
" - "
David Planella
Translation fixes
" - "
Regis \"ZRegis\" Perrin
French translation
" - "
Diego \"Flameeyes\" Pettenò
Gentoo maintainer, build system improvements
" - "
Daniel \"billie\" Pielmeier
Gentoo maintainer
" - "
Nuno \"pinheiro\" Pinheiro
Tons of Oxygen icons including our application icon
" - "
David Planella
Translation system fixes
" - "
Jure \"JLP\" Repinc
Slovenian translation
" - "
Patrick \"TheOneRing\" von Reth
MinGW support, Windows packager
" - "
Dirk \"MarcLandis\" Rettschlag
Various fixes and new features
" - "
Jaak Ristioja
Fixes
" - "
Henning \"honk\" Rohlfs
Various fixes
" - "
Martin \"sandsmark\" Sandsmark
Core fixes, Quasseldroid
" - "
Dennis \"DevUrandom\" Schridde
D-Bus notifications
" - "
Jussi \"jussi01\" Schultink
Tireless tester, {ku|U}buntu tester and lobbyist, liters of delicious Finnish alcohol
" - "
Tim \"xAFFE\" Schumacher
Fixes and feedback
" - "
Harald \"apachelogger\" Sitter
{ku|U}buntu packager, motivator, promoter
" - "
Stefanos Sofroniou
Greek translation
" - "
Rüdiger \"ruediger\" Sonderfeld
Emacs keybindings
" - "
Alexander Stein
Tray icon fix
" - "
Daniel \"son\" Steinmetz
Early beta tester and bughunter (on Vista™!)
" - "
Jesper Thomschütz
Various fixes
" - "
Edward \"Aides\" Toroshchin
Russian translation
" - "
Adam \"adamt\" Tulinius
Early beta tester and bughunter, Danish translation
" - "
Frederik M.J. \"freqmod\" Vestre
Norwegian translation
" - "
Atte Virtanen
Finnish translation
" - "
Pavel \"int\" Volkovitskiy
Early beta tester and bughunter
" - "
Roscoe van Wyk
Fixes
" - "
Benjamin \"zbenjamin\" Zeller
Windows build system fixes
" - "
Zé
Portuguese translation
" - "

" - "...and anybody else finding and reporting bugs, giving feedback, helping others and being part of the community!"); - - return res; + +QString AboutDlg::contributors() const +{ + QString res; + res = tr("We would like to thank the following contributors (in alphabetical order) and everybody we forgot to mention here:") + + QString::fromUtf8("
" + "
" + "
Daniel \"al\" Albers
Master Of Translation, many fixes and enhancements
" + "
Terje \"tan\" Andersen
Norwegian translation, documentation
" + "
Jens \"amiconn\" Arnold
Postgres migration fixes
" + "
Rafael \"EagleScreen\" Belmonte
Spanish translation
" + "
Bruno Brigras
Crash fixes
" + "
Theo \"tampakrap\" Chatzimichos
Greek translation
" + "
Yuri Chornoivan
Ukrainian translation
" + "
Tomáš \"scarabeus\" Chvátal
Czech translation
" + "
\"Condex\"
Galician translation
" + "
Joshua \"tvakah\" Corbin
Various fixes
" + "
Matthias \"pennywise\" Coy
German translation
" + "
Chris \"stitch\" Fuenty
SASL support
" + "
Kevin \"KRF\" Funk
German translation
" + "
Fabiano \"elbryan\" Francesconi
Italian translation
" + "
Aurélien \"agateau\" Gâteau
Message Indicator support
" + "
Marco \"kaffeedoktor\" Genise
Ideas, hacking, motivation
" + "
Sjors \"dazjorz\" Gielen
Fixes
" + "
Sebastian \"seezer\" Goth
Many improvements and features
" + "
Michael \"brot\" Groh
German translation, fixes
" + "
H. İbrahim \"igungor\" Güngör
Turkish translation
" + "
Edward Hades
Russian translation
" + "
John \"nox\" Hand
Former All-Seeing Eye logo
" + "
Jonas \"Dante\" Heese
Project founder, various improvements
" + "
Thomas \"Datafreak\" Hogh
Windows builder
" + "
Johannes \"j0hu\" Huber
Many fixes and features, bug triaging
" + "
Scott \"ScottK\" Kitterman
Kubuntu nightly packager, (packaging/build system) bughunter
" + "
Paul \"Haudrauf\" Klumpp
Initial design and mainwindow layout
" + "
Maia Kozheva
Russian translation
" + "
Patrick \"bonsaikitten\" Lauer
Gentoo packaging
" + "
Chris \"Fish-Face\" Le Sueur
Various fixes and improvements
" + "
Hendrik \"nevcairiel\" Leppkes
Various features
" + "
Martin \"m4yer\" Mayer
German translation
" + "
Daniel E. Moctezuma
Japanese translation
" + "
Chris \"kode54\" Moeller
Various fixes and improvements
" + "
Thomas Müller
Fixes, Debian packaging
" + "
Gábor \"ELITE_x\" Németh
Hungarian translation
" + "
Marco \"Quizzlo\" Paolone
Italian translation
" + "
Bas \"Tucos\" Pape
Various fixes and improvements
" + "
Bruno Patri
French translation
" + "
Drew \"LinuxDolt\" Patridge
BluesTheme stylesheet
" + "
Celeste \"seele\" Paul
Usability Queen
" + "
David Planella
Translation fixes
" + "
Regis \"ZRegis\" Perrin
French translation
" + "
Diego \"Flameeyes\" Pettenò
Gentoo maintainer, build system improvements
" + "
Daniel \"billie\" Pielmeier
Gentoo maintainer
" + "
Nuno \"pinheiro\" Pinheiro
Tons of Oxygen icons including our application icon
" + "
David Planella
Translation system fixes
" + "
Jure \"JLP\" Repinc
Slovenian translation
" + "
Patrick \"TheOneRing\" von Reth
MinGW support, Windows packager
" + "
Dirk \"MarcLandis\" Rettschlag
Various fixes and new features
" + "
Jaak Ristioja
Fixes
" + "
Henning \"honk\" Rohlfs
Various fixes
" + "
Martin \"sandsmark\" Sandsmark
Core fixes, Quasseldroid
" + "
Dennis \"DevUrandom\" Schridde
D-Bus notifications
" + "
Jussi \"jussi01\" Schultink
Tireless tester, {ku|U}buntu tester and lobbyist, liters of delicious Finnish alcohol
" + "
Tim \"xAFFE\" Schumacher
Fixes and feedback
" + "
Harald \"apachelogger\" Sitter
{ku|U}buntu packager, motivator, promoter
" + "
Stefanos Sofroniou
Greek translation
" + "
Rüdiger \"ruediger\" Sonderfeld
Emacs keybindings
" + "
Alexander Stein
Tray icon fix
" + "
Daniel \"son\" Steinmetz
Early beta tester and bughunter (on Vista™!)
" + "
Jesper Thomschütz
Various fixes
" + "
Edward \"Aides\" Toroshchin
Russian translation
" + "
Adam \"adamt\" Tulinius
Early beta tester and bughunter, Danish translation
" + "
Frederik M.J. \"freqmod\" Vestre
Norwegian translation
" + "
Atte Virtanen
Finnish translation
" + "
Pavel \"int\" Volkovitskiy
Early beta tester and bughunter
" + "
Roscoe van Wyk
Fixes
" + "
Benjamin \"zbenjamin\" Zeller
Windows build system fixes
" + "
Zé
Portuguese translation
" + "

" + "...and anybody else finding and reporting bugs, giving feedback, helping others and being part of the community!"); + + return res; } -QString AboutDlg::thanksTo() const { - QString res; - res = tr("Special thanks goes to:
" - "
" - "
 John \"nox\" Hand
" - "
for the original Quassel icon - The All-Seeing Eye" - "
 The Oxygen Team
" - "
for creating all the artwork you see throughout Quassel
" - "
 Qt Software formerly known as Trolltech
" - "
for creating Qt and Qtopia, and for sponsoring development of QuasselTopia with Greenphones and more
" - "
" - "
for keeping Qt alive, and for sponsoring development of Quassel Mobile with N810s
" - ); - - return res; + +QString AboutDlg::thanksTo() const +{ + QString res; + res = tr("Special thanks goes to:
" + "
" + "
 John \"nox\" Hand
" + "
for the original Quassel icon - The All-Seeing Eye" + "
 The Oxygen Team
" + "
for creating all the artwork you see throughout Quassel
" + "
 Qt Software formerly known as Trolltech
" + "
for creating Qt and Qtopia, and for sponsoring development of QuasselTopia with Greenphones and more
" + "
" + "
for keeping Qt alive, and for sponsoring development of Quassel Mobile with N810s
" + ); + + return res; } diff --git a/src/qtui/aboutdlg.h b/src/qtui/aboutdlg.h index a723e0b1..0bfe2bf5 100644 --- a/src/qtui/aboutdlg.h +++ b/src/qtui/aboutdlg.h @@ -25,20 +25,20 @@ #include "ui_aboutdlg.h" -class AboutDlg : public QDialog { - Q_OBJECT +class AboutDlg : public QDialog +{ + Q_OBJECT - public: +public: AboutDlg(QWidget *parent = 0); - private: +private: Ui::AboutDlg ui; QString about() const; QString authors() const; QString contributors() const; QString thanksTo() const; - }; diff --git a/src/qtui/awaylogfilter.cpp b/src/qtui/awaylogfilter.cpp index 8e5366b0..6cd5f4ac 100644 --- a/src/qtui/awaylogfilter.cpp +++ b/src/qtui/awaylogfilter.cpp @@ -21,36 +21,40 @@ #include "awaylogfilter.h" AwayLogFilter::AwayLogFilter(MessageModel *model, QObject *parent) - : ChatMonitorFilter(model, parent) + : ChatMonitorFilter(model, parent) { } -bool AwayLogFilter::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { - Q_UNUSED(sourceParent) - QModelIndex source_index = sourceModel()->index(sourceRow, 0); +bool AwayLogFilter::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +{ + Q_UNUSED(sourceParent) + + QModelIndex source_index = sourceModel()->index(sourceRow, 0); - Message::Flags flags = (Message::Flags)sourceModel()->data(source_index, MessageModel::FlagsRole).toInt(); - if(!(flags & Message::Backlog && flags & Message::Highlight)) - return false; + Message::Flags flags = (Message::Flags)sourceModel()->data(source_index, MessageModel::FlagsRole).toInt(); + if (!(flags & Message::Backlog && flags & Message::Highlight)) + return false; - BufferId bufferId = sourceModel()->data(source_index, MessageModel::BufferIdRole).value(); - if(!bufferId.isValid()) { - return false; - } + BufferId bufferId = sourceModel()->data(source_index, MessageModel::BufferIdRole).value(); + if (!bufferId.isValid()) { + return false; + } - if(Client::networkModel()->lastSeenMsgId(bufferId) >= sourceModel()->data(source_index, MessageModel::MsgIdRole).value()) - return false; + if (Client::networkModel()->lastSeenMsgId(bufferId) >= sourceModel()->data(source_index, MessageModel::MsgIdRole).value()) + return false; - return true; + return true; } -QVariant AwayLogFilter::data(const QModelIndex &index, int role) const { - if(role != MessageModel::FlagsRole) - return ChatMonitorFilter::data(index, role); - QModelIndex source_index = mapToSource(index); - Message::Flags flags = (Message::Flags)sourceModel()->data(source_index, MessageModel::FlagsRole).toInt(); - flags &= ~Message::Highlight; - return (int)flags; +QVariant AwayLogFilter::data(const QModelIndex &index, int role) const +{ + if (role != MessageModel::FlagsRole) + return ChatMonitorFilter::data(index, role); + + QModelIndex source_index = mapToSource(index); + Message::Flags flags = (Message::Flags)sourceModel()->data(source_index, MessageModel::FlagsRole).toInt(); + flags &= ~Message::Highlight; + return (int)flags; } diff --git a/src/qtui/awaylogfilter.h b/src/qtui/awaylogfilter.h index d188cab5..ba63d603 100644 --- a/src/qtui/awaylogfilter.h +++ b/src/qtui/awaylogfilter.h @@ -23,15 +23,17 @@ #include "chatmonitorfilter.h" -class AwayLogFilter : public ChatMonitorFilter { - Q_OBJECT +class AwayLogFilter : public ChatMonitorFilter +{ + Q_OBJECT public: - AwayLogFilter(MessageModel *model, QObject *parent = 0); + AwayLogFilter(MessageModel *model, QObject *parent = 0); - virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; - virtual QString idString() const { return "AwayLog"; } - virtual QVariant data(const QModelIndex &index, int role) const; + virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; + virtual QString idString() const { return "AwayLog"; } + virtual QVariant data(const QModelIndex &index, int role) const; }; + #endif //AWAYLOGFILTER_H diff --git a/src/qtui/awaylogview.cpp b/src/qtui/awaylogview.cpp index ed87085c..a09d1988 100644 --- a/src/qtui/awaylogview.cpp +++ b/src/qtui/awaylogview.cpp @@ -28,27 +28,29 @@ #include "chatscene.h" AwayLogView::AwayLogView(AwayLogFilter *filter, QWidget *parent) - : ChatMonitorView(filter, parent) + : ChatMonitorView(filter, parent) { - setWindowTitle(tr("Away Log")); + setWindowTitle(tr("Away Log")); } -void AwayLogView::addActionsToMenu(QMenu *menu, const QPointF &pos) { - ChatView::addActionsToMenu(menu, pos); - if(!menu->isEmpty()) - menu->addSeparator(); - if(scene()->columnByScenePos(pos) == ChatLineModel::SenderColumn) { - menu->addSeparator(); - - QAction *showNetworkAction = menu->addAction(tr("Show Network Name"), this, SLOT(showFieldsChanged(bool))); - showNetworkAction->setCheckable(true); - showNetworkAction->setChecked(filter()->showFields() & ChatMonitorFilter::NetworkField); - showNetworkAction->setData(ChatMonitorFilter::NetworkField); - - QAction *showBufferAction = menu->addAction(tr("Show Buffer Name"), this, SLOT(showFieldsChanged(bool))); - showBufferAction->setCheckable(true); - showBufferAction->setChecked(filter()->showFields() & ChatMonitorFilter::BufferField); - showBufferAction->setData(ChatMonitorFilter::BufferField); - } +void AwayLogView::addActionsToMenu(QMenu *menu, const QPointF &pos) +{ + ChatView::addActionsToMenu(menu, pos); + if (!menu->isEmpty()) + menu->addSeparator(); + + if (scene()->columnByScenePos(pos) == ChatLineModel::SenderColumn) { + menu->addSeparator(); + + QAction *showNetworkAction = menu->addAction(tr("Show Network Name"), this, SLOT(showFieldsChanged(bool))); + showNetworkAction->setCheckable(true); + showNetworkAction->setChecked(filter()->showFields() & ChatMonitorFilter::NetworkField); + showNetworkAction->setData(ChatMonitorFilter::NetworkField); + + QAction *showBufferAction = menu->addAction(tr("Show Buffer Name"), this, SLOT(showFieldsChanged(bool))); + showBufferAction->setCheckable(true); + showBufferAction->setChecked(filter()->showFields() & ChatMonitorFilter::BufferField); + showBufferAction->setData(ChatMonitorFilter::BufferField); + } } diff --git a/src/qtui/awaylogview.h b/src/qtui/awaylogview.h index 542d8ead..14833dcb 100644 --- a/src/qtui/awaylogview.h +++ b/src/qtui/awaylogview.h @@ -25,12 +25,14 @@ class AwayLogFilter; -class AwayLogView : public ChatMonitorView { - Q_OBJECT +class AwayLogView : public ChatMonitorView +{ + Q_OBJECT public: - AwayLogView(AwayLogFilter *filter, QWidget *parent = 0); - virtual void addActionsToMenu(QMenu *menu, const QPointF &pos); + AwayLogView(AwayLogFilter *filter, QWidget *parent = 0); + virtual void addActionsToMenu(QMenu *menu, const QPointF &pos); }; + #endif //AWAYLOGVIEW_H diff --git a/src/qtui/bufferwidget.cpp b/src/qtui/bufferwidget.cpp index 7b4e9545..8590f28c 100644 --- a/src/qtui/bufferwidget.cpp +++ b/src/qtui/bufferwidget.cpp @@ -37,229 +37,257 @@ #include "qtui.h" #include "settings.h" - BufferWidget::BufferWidget(QWidget *parent) - : AbstractBufferContainer(parent), + : AbstractBufferContainer(parent), _chatViewSearchController(new ChatViewSearchController(this)), _autoMarkerLine(true) { - ui.setupUi(this); - layout()->setContentsMargins(0, 0, 0, 0); - layout()->setSpacing(0); - // ui.searchBar->hide(); - - _chatViewSearchController->setCaseSensitive(ui.searchBar->caseSensitiveBox()->isChecked()); - _chatViewSearchController->setSearchSenders(ui.searchBar->searchSendersBox()->isChecked()); - _chatViewSearchController->setSearchMsgs(ui.searchBar->searchMsgsBox()->isChecked()); - _chatViewSearchController->setSearchOnlyRegularMsgs(ui.searchBar->searchOnlyRegularMsgsBox()->isChecked()); - - connect(ui.searchBar, SIGNAL(searchChanged(const QString &)), - _chatViewSearchController, SLOT(setSearchString(const QString &))); - connect(ui.searchBar->caseSensitiveBox(), SIGNAL(toggled(bool)), - _chatViewSearchController, SLOT(setCaseSensitive(bool))); - connect(ui.searchBar->searchSendersBox(), SIGNAL(toggled(bool)), - _chatViewSearchController, SLOT(setSearchSenders(bool))); - connect(ui.searchBar->searchMsgsBox(), SIGNAL(toggled(bool)), - _chatViewSearchController, SLOT(setSearchMsgs(bool))); - connect(ui.searchBar->searchOnlyRegularMsgsBox(), SIGNAL(toggled(bool)), - _chatViewSearchController, SLOT(setSearchOnlyRegularMsgs(bool))); - connect(ui.searchBar->searchUpButton(), SIGNAL(clicked()), - _chatViewSearchController, SLOT(highlightPrev())); - connect(ui.searchBar->searchDownButton(), SIGNAL(clicked()), - _chatViewSearchController, SLOT(highlightNext())); - - connect(ui.searchBar, SIGNAL(hidden()), this, SLOT(setFocus())); - - connect(_chatViewSearchController, SIGNAL(newCurrentHighlight(QGraphicsItem *)), - this, SLOT(scrollToHighlight(QGraphicsItem *))); - - ActionCollection *coll = QtUi::actionCollection(); - - Action *zoomInChatview = coll->add("ZoomInChatView", this, SLOT(zoomIn())); - zoomInChatview->setText(tr("Zoom In")); - zoomInChatview->setIcon(SmallIcon("zoom-in")); - zoomInChatview->setShortcut(QKeySequence::ZoomIn); - - Action *zoomOutChatview = coll->add("ZoomOutChatView", this, SLOT(zoomOut())); - zoomOutChatview->setIcon(SmallIcon("zoom-out")); - zoomOutChatview->setText(tr("Zoom Out")); - zoomOutChatview->setShortcut(QKeySequence::ZoomOut); - - Action *zoomOriginalChatview = coll->add("ZoomOriginalChatView", this, SLOT(zoomOriginal())); - zoomOriginalChatview->setIcon(SmallIcon("zoom-original")); - zoomOriginalChatview->setText(tr("Actual Size")); - //zoomOriginalChatview->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_0)); // used for RTS switching - - Action *setMarkerLine = coll->add("SetMarkerLineToBottom", this, SLOT(setMarkerLine())); - setMarkerLine->setText(tr("Set Marker Line")); - setMarkerLine->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_R)); - - Action *jumpToMarkerLine = QtUi::actionCollection("Navigation")->add("JumpToMarkerLine", this, SLOT(jumpToMarkerLine())); - jumpToMarkerLine->setText(tr("Go to Marker Line")); - jumpToMarkerLine->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_K)); - - ChatViewSettings s; - s.initAndNotify("AutoMarkerLine", this, SLOT(setAutoMarkerLine(QVariant)), true); + ui.setupUi(this); + layout()->setContentsMargins(0, 0, 0, 0); + layout()->setSpacing(0); + // ui.searchBar->hide(); + + _chatViewSearchController->setCaseSensitive(ui.searchBar->caseSensitiveBox()->isChecked()); + _chatViewSearchController->setSearchSenders(ui.searchBar->searchSendersBox()->isChecked()); + _chatViewSearchController->setSearchMsgs(ui.searchBar->searchMsgsBox()->isChecked()); + _chatViewSearchController->setSearchOnlyRegularMsgs(ui.searchBar->searchOnlyRegularMsgsBox()->isChecked()); + + connect(ui.searchBar, SIGNAL(searchChanged(const QString &)), + _chatViewSearchController, SLOT(setSearchString(const QString &))); + connect(ui.searchBar->caseSensitiveBox(), SIGNAL(toggled(bool)), + _chatViewSearchController, SLOT(setCaseSensitive(bool))); + connect(ui.searchBar->searchSendersBox(), SIGNAL(toggled(bool)), + _chatViewSearchController, SLOT(setSearchSenders(bool))); + connect(ui.searchBar->searchMsgsBox(), SIGNAL(toggled(bool)), + _chatViewSearchController, SLOT(setSearchMsgs(bool))); + connect(ui.searchBar->searchOnlyRegularMsgsBox(), SIGNAL(toggled(bool)), + _chatViewSearchController, SLOT(setSearchOnlyRegularMsgs(bool))); + connect(ui.searchBar->searchUpButton(), SIGNAL(clicked()), + _chatViewSearchController, SLOT(highlightPrev())); + connect(ui.searchBar->searchDownButton(), SIGNAL(clicked()), + _chatViewSearchController, SLOT(highlightNext())); + + connect(ui.searchBar, SIGNAL(hidden()), this, SLOT(setFocus())); + + connect(_chatViewSearchController, SIGNAL(newCurrentHighlight(QGraphicsItem *)), + this, SLOT(scrollToHighlight(QGraphicsItem *))); + + ActionCollection *coll = QtUi::actionCollection(); + + Action *zoomInChatview = coll->add("ZoomInChatView", this, SLOT(zoomIn())); + zoomInChatview->setText(tr("Zoom In")); + zoomInChatview->setIcon(SmallIcon("zoom-in")); + zoomInChatview->setShortcut(QKeySequence::ZoomIn); + + Action *zoomOutChatview = coll->add("ZoomOutChatView", this, SLOT(zoomOut())); + zoomOutChatview->setIcon(SmallIcon("zoom-out")); + zoomOutChatview->setText(tr("Zoom Out")); + zoomOutChatview->setShortcut(QKeySequence::ZoomOut); + + Action *zoomOriginalChatview = coll->add("ZoomOriginalChatView", this, SLOT(zoomOriginal())); + zoomOriginalChatview->setIcon(SmallIcon("zoom-original")); + zoomOriginalChatview->setText(tr("Actual Size")); + //zoomOriginalChatview->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_0)); // used for RTS switching + + Action *setMarkerLine = coll->add("SetMarkerLineToBottom", this, SLOT(setMarkerLine())); + setMarkerLine->setText(tr("Set Marker Line")); + setMarkerLine->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_R)); + + Action *jumpToMarkerLine = QtUi::actionCollection("Navigation")->add("JumpToMarkerLine", this, SLOT(jumpToMarkerLine())); + jumpToMarkerLine->setText(tr("Go to Marker Line")); + jumpToMarkerLine->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_K)); + + ChatViewSettings s; + s.initAndNotify("AutoMarkerLine", this, SLOT(setAutoMarkerLine(QVariant)), true); } -BufferWidget::~BufferWidget() { - delete _chatViewSearchController; - _chatViewSearchController = 0; -} -void BufferWidget::setAutoMarkerLine(const QVariant &v) { - _autoMarkerLine = v.toBool(); +BufferWidget::~BufferWidget() +{ + delete _chatViewSearchController; + _chatViewSearchController = 0; } -AbstractChatView *BufferWidget::createChatView(BufferId id) { - ChatView *chatView; - chatView = new ChatView(id, this); - chatView->setBufferContainer(this); - _chatViews[id] = chatView; - ui.stackedWidget->addWidget(chatView); - chatView->setFocusProxy(this); - return chatView; + +void BufferWidget::setAutoMarkerLine(const QVariant &v) +{ + _autoMarkerLine = v.toBool(); } -void BufferWidget::removeChatView(BufferId id) { - QWidget *view = _chatViews.value(id, 0); - if(!view) return; - ui.stackedWidget->removeWidget(view); - view->deleteLater(); - _chatViews.take(id); + +AbstractChatView *BufferWidget::createChatView(BufferId id) +{ + ChatView *chatView; + chatView = new ChatView(id, this); + chatView->setBufferContainer(this); + _chatViews[id] = chatView; + ui.stackedWidget->addWidget(chatView); + chatView->setFocusProxy(this); + return chatView; } -void BufferWidget::showChatView(BufferId id) { - if(!id.isValid()) { - ui.stackedWidget->setCurrentWidget(ui.page); - } else { - ChatView *view = qobject_cast(_chatViews.value(id)); - Q_ASSERT(view); - ui.stackedWidget->setCurrentWidget(view); - _chatViewSearchController->setScene(view->scene()); - } + +void BufferWidget::removeChatView(BufferId id) +{ + QWidget *view = _chatViews.value(id, 0); + if (!view) return; + ui.stackedWidget->removeWidget(view); + view->deleteLater(); + _chatViews.take(id); } -void BufferWidget::scrollToHighlight(QGraphicsItem *highlightItem) { - ChatView *view = qobject_cast(ui.stackedWidget->currentWidget()); - if(view) { - view->centerOn(highlightItem); - } + +void BufferWidget::showChatView(BufferId id) +{ + if (!id.isValid()) { + ui.stackedWidget->setCurrentWidget(ui.page); + } + else { + ChatView *view = qobject_cast(_chatViews.value(id)); + Q_ASSERT(view); + ui.stackedWidget->setCurrentWidget(view); + _chatViewSearchController->setScene(view->scene()); + } } -void BufferWidget::zoomIn() { - ChatView *view = qobject_cast(ui.stackedWidget->currentWidget()); - if(view) - view->zoomIn(); + +void BufferWidget::scrollToHighlight(QGraphicsItem *highlightItem) +{ + ChatView *view = qobject_cast(ui.stackedWidget->currentWidget()); + if (view) { + view->centerOn(highlightItem); + } } -void BufferWidget::zoomOut() { - ChatView *view = qobject_cast(ui.stackedWidget->currentWidget()); - if(view) - view->zoomOut(); + +void BufferWidget::zoomIn() +{ + ChatView *view = qobject_cast(ui.stackedWidget->currentWidget()); + if (view) + view->zoomIn(); } -void BufferWidget::zoomOriginal() { - ChatView *view = qobject_cast(ui.stackedWidget->currentWidget()); - if(view) - view->zoomOriginal(); + +void BufferWidget::zoomOut() +{ + ChatView *view = qobject_cast(ui.stackedWidget->currentWidget()); + if (view) + view->zoomOut(); } -void BufferWidget::addActionsToMenu(QMenu *menu, const QPointF &pos) { - Q_UNUSED(pos); - ActionCollection *coll = QtUi::actionCollection(); - menu->addSeparator(); - menu->addAction(coll->action("ZoomInChatView")); - menu->addAction(coll->action("ZoomOutChatView")); - menu->addAction(coll->action("ZoomOriginalChatView")); + +void BufferWidget::zoomOriginal() +{ + ChatView *view = qobject_cast(ui.stackedWidget->currentWidget()); + if (view) + view->zoomOriginal(); } -bool BufferWidget::eventFilter(QObject *watched, QEvent *event) { - if(event->type() != QEvent::KeyPress) - return false; - QKeyEvent *keyEvent = static_cast(event); +void BufferWidget::addActionsToMenu(QMenu *menu, const QPointF &pos) +{ + Q_UNUSED(pos); + ActionCollection *coll = QtUi::actionCollection(); + menu->addSeparator(); + menu->addAction(coll->action("ZoomInChatView")); + menu->addAction(coll->action("ZoomOutChatView")); + menu->addAction(coll->action("ZoomOriginalChatView")); +} - MultiLineEdit *inputLine = qobject_cast(watched); - if(!inputLine) - return false; - // Intercept copy key presses - if(keyEvent == QKeySequence::Copy) { - if(inputLine->hasSelectedText()) - return false; - ChatView *view = qobject_cast(ui.stackedWidget->currentWidget()); - if(view) - view->scene()->selectionToClipboard(); - return true; - } - - // We don't want to steal cursor movement keys if the input line is in multiline mode - if(!inputLine->isSingleLine()) - return false; - - switch(keyEvent->key()) { - case Qt::Key_Up: - case Qt::Key_Down: - if(!(keyEvent->modifiers() & Qt::ShiftModifier)) - return false; - case Qt::Key_PageUp: - case Qt::Key_PageDown: - // static cast to access public qobject::event - return static_cast(ui.stackedWidget->currentWidget())->event(event); - default: - return false; - } +bool BufferWidget::eventFilter(QObject *watched, QEvent *event) +{ + if (event->type() != QEvent::KeyPress) + return false; + + QKeyEvent *keyEvent = static_cast(event); + + MultiLineEdit *inputLine = qobject_cast(watched); + if (!inputLine) + return false; + + // Intercept copy key presses + if (keyEvent == QKeySequence::Copy) { + if (inputLine->hasSelectedText()) + return false; + ChatView *view = qobject_cast(ui.stackedWidget->currentWidget()); + if (view) + view->scene()->selectionToClipboard(); + return true; + } + + // We don't want to steal cursor movement keys if the input line is in multiline mode + if (!inputLine->isSingleLine()) + return false; + + switch (keyEvent->key()) { + case Qt::Key_Up: + case Qt::Key_Down: + if (!(keyEvent->modifiers() & Qt::ShiftModifier)) + return false; + case Qt::Key_PageUp: + case Qt::Key_PageDown: + // static cast to access public qobject::event + return static_cast(ui.stackedWidget->currentWidget())->event(event); + default: + return false; + } } -void BufferWidget::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { - ChatView *prevView = qobject_cast(ui.stackedWidget->currentWidget()); - - AbstractBufferContainer::currentChanged(current, previous); // switch first to avoid a redraw - - // we need to hide the marker line if it's already/still at the bottom of the view (and not scrolled up) - ChatView *curView = qobject_cast(ui.stackedWidget->currentWidget()); - if(curView) { - BufferId curBufferId = current.data(NetworkModel::BufferIdRole).value(); - if(curBufferId.isValid()) { - MsgId markerMsgId = Client::networkModel()->markerLineMsgId(curBufferId); - if(markerMsgId == curView->lastMsgId() && markerMsgId == curView->lastVisibleMsgId()) - curView->setMarkerLineVisible(false); - else - curView->setMarkerLineVisible(true); + +void BufferWidget::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) +{ + ChatView *prevView = qobject_cast(ui.stackedWidget->currentWidget()); + + AbstractBufferContainer::currentChanged(current, previous); // switch first to avoid a redraw + + // we need to hide the marker line if it's already/still at the bottom of the view (and not scrolled up) + ChatView *curView = qobject_cast(ui.stackedWidget->currentWidget()); + if (curView) { + BufferId curBufferId = current.data(NetworkModel::BufferIdRole).value(); + if (curBufferId.isValid()) { + MsgId markerMsgId = Client::networkModel()->markerLineMsgId(curBufferId); + if (markerMsgId == curView->lastMsgId() && markerMsgId == curView->lastVisibleMsgId()) + curView->setMarkerLineVisible(false); + else + curView->setMarkerLineVisible(true); + } } - } - if(prevView && autoMarkerLine()) - setMarkerLine(prevView, false); + if (prevView && autoMarkerLine()) + setMarkerLine(prevView, false); } -void BufferWidget::setMarkerLine(ChatView *view, bool allowGoingBack) { - if(!view) - view = qobject_cast(ui.stackedWidget->currentWidget()); - if(!view) - return; - - ChatLine *lastLine = view->lastVisibleChatLine(); - if(lastLine) { - QModelIndex idx = lastLine->index(); - MsgId msgId = idx.data(MessageModel::MsgIdRole).value(); - - if(!allowGoingBack) { - BufferId bufId = view->scene()->singleBufferId(); - MsgId oldMsgId = Client::markerLine(bufId); - if(oldMsgId.isValid() && msgId <= oldMsgId) + +void BufferWidget::setMarkerLine(ChatView *view, bool allowGoingBack) +{ + if (!view) + view = qobject_cast(ui.stackedWidget->currentWidget()); + if (!view) return; + + ChatLine *lastLine = view->lastVisibleChatLine(); + if (lastLine) { + QModelIndex idx = lastLine->index(); + MsgId msgId = idx.data(MessageModel::MsgIdRole).value(); + + if (!allowGoingBack) { + BufferId bufId = view->scene()->singleBufferId(); + MsgId oldMsgId = Client::markerLine(bufId); + if (oldMsgId.isValid() && msgId <= oldMsgId) + return; + } + view->setMarkerLine(msgId); } - view->setMarkerLine(msgId); - } } -void BufferWidget::jumpToMarkerLine(ChatView *view, bool requestBacklog) { - if(!view) - view = qobject_cast(ui.stackedWidget->currentWidget()); - if(!view) - return; - view->jumpToMarkerLine(requestBacklog); +void BufferWidget::jumpToMarkerLine(ChatView *view, bool requestBacklog) +{ + if (!view) + view = qobject_cast(ui.stackedWidget->currentWidget()); + if (!view) + return; + + view->jumpToMarkerLine(requestBacklog); } diff --git a/src/qtui/bufferwidget.h b/src/qtui/bufferwidget.h index 4eb8b6d9..b47cfe84 100644 --- a/src/qtui/bufferwidget.h +++ b/src/qtui/bufferwidget.h @@ -30,46 +30,48 @@ class ChatView; class ChatViewSearchBar; class ChatViewSearchController; -class BufferWidget : public AbstractBufferContainer { - Q_OBJECT +class BufferWidget : public AbstractBufferContainer +{ + Q_OBJECT public: - BufferWidget(QWidget *parent); - ~BufferWidget(); + BufferWidget(QWidget *parent); + ~BufferWidget(); - virtual bool eventFilter(QObject *watched, QEvent *event); + virtual bool eventFilter(QObject *watched, QEvent *event); - inline ChatViewSearchBar *searchBar() const { return ui.searchBar; } - void addActionsToMenu(QMenu *, const QPointF &pos); + inline ChatViewSearchBar *searchBar() const { return ui.searchBar; } + void addActionsToMenu(QMenu *, const QPointF &pos); public slots: - virtual void setMarkerLine(ChatView *view = 0, bool allowGoingBack = true); - virtual void jumpToMarkerLine(ChatView *view = 0, bool requestBacklog = true); + virtual void setMarkerLine(ChatView *view = 0, bool allowGoingBack = true); + virtual void jumpToMarkerLine(ChatView *view = 0, bool requestBacklog = true); protected: - virtual AbstractChatView *createChatView(BufferId); - virtual void removeChatView(BufferId); - virtual inline bool autoMarkerLine() const { return _autoMarkerLine; } + virtual AbstractChatView *createChatView(BufferId); + virtual void removeChatView(BufferId); + virtual inline bool autoMarkerLine() const { return _autoMarkerLine; } protected slots: - virtual void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); - virtual void showChatView(BufferId); + virtual void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); + virtual void showChatView(BufferId); private slots: - void scrollToHighlight(QGraphicsItem *highlightItem); - void zoomIn(); - void zoomOut(); - void zoomOriginal(); + void scrollToHighlight(QGraphicsItem *highlightItem); + void zoomIn(); + void zoomOut(); + void zoomOriginal(); - void setAutoMarkerLine(const QVariant &); + void setAutoMarkerLine(const QVariant &); private: - Ui::BufferWidget ui; - QHash _chatViews; + Ui::BufferWidget ui; + QHash _chatViews; - ChatViewSearchController *_chatViewSearchController; + ChatViewSearchController *_chatViewSearchController; - bool _autoMarkerLine; + bool _autoMarkerLine; }; + #endif diff --git a/src/qtui/channellistdlg.cpp b/src/qtui/channellistdlg.cpp index 18bc5ef7..8e47e267 100644 --- a/src/qtui/channellistdlg.cpp +++ b/src/qtui/channellistdlg.cpp @@ -30,130 +30,150 @@ #include "iconloader.h" ChannelListDlg::ChannelListDlg(QWidget *parent) - : QDialog(parent), + : QDialog(parent), _listFinished(true), _ircListModel(this), _sortFilter(this), _simpleModeSpacer(0), _advancedMode(false) { - _sortFilter.setSourceModel(&_ircListModel); - _sortFilter.setFilterCaseSensitivity(Qt::CaseInsensitive); - _sortFilter.setFilterKeyColumn(-1); - - ui.setupUi(this); - ui.advancedModeLabel->setPixmap(BarIcon("edit-rename")); - - ui.channelListView->setSelectionBehavior(QAbstractItemView::SelectRows); - ui.channelListView->setSelectionMode(QAbstractItemView::SingleSelection); - ui.channelListView->setAlternatingRowColors(true); - ui.channelListView->setTabKeyNavigation(false); - ui.channelListView->setModel(&_sortFilter); - ui.channelListView->setSortingEnabled(true); - ui.channelListView->verticalHeader()->hide(); - ui.channelListView->horizontalHeader()->setStretchLastSection(true); - - ui.searchChannelsButton->setAutoDefault(false); - - setWindowIcon(Icon("format-list-unordered")); - - connect(ui.advancedModeLabel, SIGNAL(clicked()), this, SLOT(toggleMode())); - connect(ui.searchChannelsButton, SIGNAL(clicked()), this, SLOT(requestSearch())); - connect(ui.channelNameLineEdit, SIGNAL(returnPressed()), this, SLOT(requestSearch())); - connect(ui.filterLineEdit, SIGNAL(textChanged(QString)), &_sortFilter, SLOT(setFilterFixedString(QString))); - connect(Client::ircListHelper(), SIGNAL(channelListReceived(const NetworkId &, const QStringList &, QList)), - this, SLOT(receiveChannelList(NetworkId , QStringList, QList))); - connect(Client::ircListHelper(), SIGNAL(finishedListReported(const NetworkId &)), this, SLOT(reportFinishedList())); - connect(Client::ircListHelper(), SIGNAL(errorReported(const QString &)), this, SLOT(showError(const QString &))); - connect(ui.channelListView, SIGNAL(activated(QModelIndex)), this, SLOT(joinChannel(QModelIndex))); - - setAdvancedMode(false); - enableQuery(true); - showFilterLine(false); - showErrors(false); + _sortFilter.setSourceModel(&_ircListModel); + _sortFilter.setFilterCaseSensitivity(Qt::CaseInsensitive); + _sortFilter.setFilterKeyColumn(-1); + + ui.setupUi(this); + ui.advancedModeLabel->setPixmap(BarIcon("edit-rename")); + + ui.channelListView->setSelectionBehavior(QAbstractItemView::SelectRows); + ui.channelListView->setSelectionMode(QAbstractItemView::SingleSelection); + ui.channelListView->setAlternatingRowColors(true); + ui.channelListView->setTabKeyNavigation(false); + ui.channelListView->setModel(&_sortFilter); + ui.channelListView->setSortingEnabled(true); + ui.channelListView->verticalHeader()->hide(); + ui.channelListView->horizontalHeader()->setStretchLastSection(true); + + ui.searchChannelsButton->setAutoDefault(false); + + setWindowIcon(Icon("format-list-unordered")); + + connect(ui.advancedModeLabel, SIGNAL(clicked()), this, SLOT(toggleMode())); + connect(ui.searchChannelsButton, SIGNAL(clicked()), this, SLOT(requestSearch())); + connect(ui.channelNameLineEdit, SIGNAL(returnPressed()), this, SLOT(requestSearch())); + connect(ui.filterLineEdit, SIGNAL(textChanged(QString)), &_sortFilter, SLOT(setFilterFixedString(QString))); + connect(Client::ircListHelper(), SIGNAL(channelListReceived(const NetworkId &, const QStringList &, QList )), + this, SLOT(receiveChannelList(NetworkId, QStringList, QList ))); + connect(Client::ircListHelper(), SIGNAL(finishedListReported(const NetworkId &)), this, SLOT(reportFinishedList())); + connect(Client::ircListHelper(), SIGNAL(errorReported(const QString &)), this, SLOT(showError(const QString &))); + connect(ui.channelListView, SIGNAL(activated(QModelIndex)), this, SLOT(joinChannel(QModelIndex))); + + setAdvancedMode(false); + enableQuery(true); + showFilterLine(false); + showErrors(false); } -void ChannelListDlg::setNetwork(NetworkId netId) { - if(_netId == netId) - return; - _netId = netId; - _ircListModel.setChannelList(); - showFilterLine(false); +void ChannelListDlg::setNetwork(NetworkId netId) +{ + if (_netId == netId) + return; + + _netId = netId; + _ircListModel.setChannelList(); + showFilterLine(false); } -void ChannelListDlg::requestSearch() { - _listFinished = false; - enableQuery(false); - showErrors(false); - QStringList channelFilters; - channelFilters << ui.channelNameLineEdit->text().trimmed(); - Client::ircListHelper()->requestChannelList(_netId, channelFilters); + +void ChannelListDlg::requestSearch() +{ + _listFinished = false; + enableQuery(false); + showErrors(false); + QStringList channelFilters; + channelFilters << ui.channelNameLineEdit->text().trimmed(); + Client::ircListHelper()->requestChannelList(_netId, channelFilters); } -void ChannelListDlg::receiveChannelList(const NetworkId &netId, const QStringList &channelFilters, const QList &channelList) { - Q_UNUSED(channelFilters) - if(netId != _netId) - return; - showFilterLine(!channelList.isEmpty()); - _ircListModel.setChannelList(channelList); - enableQuery(_listFinished); +void ChannelListDlg::receiveChannelList(const NetworkId &netId, const QStringList &channelFilters, const QList &channelList) +{ + Q_UNUSED(channelFilters) + if (netId != _netId) + return; + + showFilterLine(!channelList.isEmpty()); + _ircListModel.setChannelList(channelList); + enableQuery(_listFinished); } -void ChannelListDlg::showFilterLine(bool show) { - ui.line->setVisible(show); - ui.filterLabel->setVisible(show); - ui.filterLineEdit->setVisible(show); + +void ChannelListDlg::showFilterLine(bool show) +{ + ui.line->setVisible(show); + ui.filterLabel->setVisible(show); + ui.filterLineEdit->setVisible(show); } -void ChannelListDlg::enableQuery(bool enable) { - ui.channelNameLineEdit->setEnabled(enable); - ui.searchChannelsButton->setEnabled(enable); + +void ChannelListDlg::enableQuery(bool enable) +{ + ui.channelNameLineEdit->setEnabled(enable); + ui.searchChannelsButton->setEnabled(enable); } -void ChannelListDlg::setAdvancedMode(bool advanced) { - _advancedMode = advanced; - if(advanced) { - if(_simpleModeSpacer) { - ui.searchLayout->removeItem(_simpleModeSpacer); - delete _simpleModeSpacer; - _simpleModeSpacer = 0; +void ChannelListDlg::setAdvancedMode(bool advanced) +{ + _advancedMode = advanced; + + if (advanced) { + if (_simpleModeSpacer) { + ui.searchLayout->removeItem(_simpleModeSpacer); + delete _simpleModeSpacer; + _simpleModeSpacer = 0; + } + ui.advancedModeLabel->setPixmap(BarIcon("edit-clear-locationbar-rtl")); } - ui.advancedModeLabel->setPixmap(BarIcon("edit-clear-locationbar-rtl")); - } else { - if(!_simpleModeSpacer) { - _simpleModeSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - ui.searchLayout->insertSpacerItem(0, _simpleModeSpacer); + else { + if (!_simpleModeSpacer) { + _simpleModeSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + ui.searchLayout->insertSpacerItem(0, _simpleModeSpacer); + } + ui.advancedModeLabel->setPixmap(BarIcon("edit-rename")); } - ui.advancedModeLabel->setPixmap(BarIcon("edit-rename")); - } - ui.channelNameLineEdit->clear(); - ui.channelNameLineEdit->setVisible(advanced); - ui.searchPatternLabel->setVisible(advanced); + ui.channelNameLineEdit->clear(); + ui.channelNameLineEdit->setVisible(advanced); + ui.searchPatternLabel->setVisible(advanced); } -void ChannelListDlg::showErrors(bool show) { - if(!show) { - ui.errorTextEdit->clear(); - } - ui.errorLabel->setVisible(show); - ui.errorTextEdit->setVisible(show); + +void ChannelListDlg::showErrors(bool show) +{ + if (!show) { + ui.errorTextEdit->clear(); + } + ui.errorLabel->setVisible(show); + ui.errorTextEdit->setVisible(show); } -void ChannelListDlg::reportFinishedList() { - _listFinished = true; +void ChannelListDlg::reportFinishedList() +{ + _listFinished = true; } -void ChannelListDlg::showError(const QString &error) { - showErrors(true); - ui.errorTextEdit->moveCursor(QTextCursor::End); - ui.errorTextEdit->insertPlainText(error + "\n"); + +void ChannelListDlg::showError(const QString &error) +{ + showErrors(true); + ui.errorTextEdit->moveCursor(QTextCursor::End); + ui.errorTextEdit->insertPlainText(error + "\n"); } -void ChannelListDlg::joinChannel(const QModelIndex &index) { - Client::instance()->userInput(BufferInfo::fakeStatusBuffer(_netId), QString("/JOIN %1").arg(index.sibling(index.row(), 0).data().toString())); + +void ChannelListDlg::joinChannel(const QModelIndex &index) +{ + Client::instance()->userInput(BufferInfo::fakeStatusBuffer(_netId), QString("/JOIN %1").arg(index.sibling(index.row(), 0).data().toString())); } diff --git a/src/qtui/channellistdlg.h b/src/qtui/channellistdlg.h index 939d00e4..f48d7cc3 100644 --- a/src/qtui/channellistdlg.h +++ b/src/qtui/channellistdlg.h @@ -31,38 +31,40 @@ class QSpacerItem; -class ChannelListDlg : public QDialog { - Q_OBJECT +class ChannelListDlg : public QDialog +{ + Q_OBJECT public: - ChannelListDlg(QWidget *parent = 0); + ChannelListDlg(QWidget *parent = 0); - void setNetwork(NetworkId netId); + void setNetwork(NetworkId netId); protected slots: - void requestSearch(); - void receiveChannelList(const NetworkId &netId, const QStringList &channelFilters, const QList &channelList); - void reportFinishedList(); - void joinChannel(const QModelIndex &); + void requestSearch(); + void receiveChannelList(const NetworkId &netId, const QStringList &channelFilters, const QList &channelList); + void reportFinishedList(); + void joinChannel(const QModelIndex &); private slots: - inline void toggleMode() { setAdvancedMode(!_advancedMode); } - void showError(const QString &error); + inline void toggleMode() { setAdvancedMode(!_advancedMode); } + void showError(const QString &error); private: - void showFilterLine(bool show); - void showErrors(bool show); - void enableQuery(bool enable); - void setAdvancedMode(bool advanced); + void showFilterLine(bool show); + void showErrors(bool show); + void enableQuery(bool enable); + void setAdvancedMode(bool advanced); - Ui::ChannelListDlg ui; + Ui::ChannelListDlg ui; - bool _listFinished; - NetworkId _netId; - IrcListModel _ircListModel; - QSortFilterProxyModel _sortFilter; - QSpacerItem *_simpleModeSpacer; - bool _advancedMode; + bool _listFinished; + NetworkId _netId; + IrcListModel _ircListModel; + QSortFilterProxyModel _sortFilter; + QSpacerItem *_simpleModeSpacer; + bool _advancedMode; }; + #endif //CHANNELLIST_H diff --git a/src/qtui/chatitem.cpp b/src/qtui/chatitem.cpp index fe2bd563..21ce46fe 100644 --- a/src/qtui/chatitem.cpp +++ b/src/qtui/chatitem.cpp @@ -41,433 +41,517 @@ #include "qtuistyle.h" ChatItem::ChatItem(const QRectF &boundingRect, ChatLine *parent) -: _parent(parent), - _boundingRect(boundingRect), - _selectionMode(NoSelection), - _selectionStart(-1), - _cachedLayout(0) + : _parent(parent), + _boundingRect(boundingRect), + _selectionMode(NoSelection), + _selectionStart(-1), + _cachedLayout(0) { - } -ChatItem::~ChatItem() { - delete _cachedLayout; + +ChatItem::~ChatItem() +{ + delete _cachedLayout; } -ChatLine *ChatItem::chatLine() const { - return _parent; + +ChatLine *ChatItem::chatLine() const +{ + return _parent; } -ChatScene *ChatItem::chatScene() const { - return chatLine()->chatScene(); + +ChatScene *ChatItem::chatScene() const +{ + return chatLine()->chatScene(); } -ChatView *ChatItem::chatView() const { - return chatScene()->chatView(); + +ChatView *ChatItem::chatView() const +{ + return chatScene()->chatView(); } -const QAbstractItemModel *ChatItem::model() const { - return chatLine()->model(); + +const QAbstractItemModel *ChatItem::model() const +{ + return chatLine()->model(); } -int ChatItem::row() const { - return chatLine()->row(); + +int ChatItem::row() const +{ + return chatLine()->row(); } -QPointF ChatItem::mapToLine(const QPointF &p) const { - return p + pos(); + +QPointF ChatItem::mapToLine(const QPointF &p) const +{ + return p + pos(); } -QPointF ChatItem::mapFromLine(const QPointF &p) const { - return p - pos(); + +QPointF ChatItem::mapFromLine(const QPointF &p) const +{ + return p - pos(); } + // relative to the ChatLine -QPointF ChatItem::mapToScene(const QPointF &p) const { - return chatLine()->mapToScene(p /* + pos() */); +QPointF ChatItem::mapToScene(const QPointF &p) const +{ + return chatLine()->mapToScene(p /* + pos() */); } -QPointF ChatItem::mapFromScene(const QPointF &p) const { - return chatLine()->mapFromScene(p) /* - pos() */; + +QPointF ChatItem::mapFromScene(const QPointF &p) const +{ + return chatLine()->mapFromScene(p) /* - pos() */; } -QVariant ChatItem::data(int role) const { - QModelIndex index = model()->index(row(), column()); - if(!index.isValid()) { - qWarning() << "ChatItem::data(): model index is invalid!" << index; - return QVariant(); - } - return model()->data(index, role); + +QVariant ChatItem::data(int role) const +{ + QModelIndex index = model()->index(row(), column()); + if (!index.isValid()) { + qWarning() << "ChatItem::data(): model index is invalid!" << index; + return QVariant(); + } + return model()->data(index, role); } -QTextLayout *ChatItem::layout() const { - if(_cachedLayout) - return _cachedLayout; - _cachedLayout = new QTextLayout; - initLayout(_cachedLayout); - chatView()->setHasCache(chatLine()); - return _cachedLayout; +QTextLayout *ChatItem::layout() const +{ + if (_cachedLayout) + return _cachedLayout; + + _cachedLayout = new QTextLayout; + initLayout(_cachedLayout); + chatView()->setHasCache(chatLine()); + return _cachedLayout; } -void ChatItem::clearCache() { - delete _cachedLayout; - _cachedLayout = 0; + +void ChatItem::clearCache() +{ + delete _cachedLayout; + _cachedLayout = 0; } -void ChatItem::initLayoutHelper(QTextLayout *layout, QTextOption::WrapMode wrapMode, Qt::Alignment alignment) const { - Q_ASSERT(layout); - layout->setText(data(MessageModel::DisplayRole).toString()); +void ChatItem::initLayoutHelper(QTextLayout *layout, QTextOption::WrapMode wrapMode, Qt::Alignment alignment) const +{ + Q_ASSERT(layout); + + layout->setText(data(MessageModel::DisplayRole).toString()); - QTextOption option; - option.setWrapMode(wrapMode); - option.setAlignment(alignment); - layout->setTextOption(option); + QTextOption option; + option.setWrapMode(wrapMode); + option.setAlignment(alignment); + layout->setTextOption(option); - QList formatRanges - = QtUi::style()->toTextLayoutList(formatList(), layout->text().length(), data(ChatLineModel::MsgLabelRole).toUInt()); - layout->setAdditionalFormats(formatRanges); + QList formatRanges + = QtUi::style()->toTextLayoutList(formatList(), layout->text().length(), data(ChatLineModel::MsgLabelRole).toUInt()); + layout->setAdditionalFormats(formatRanges); } -void ChatItem::initLayout(QTextLayout *layout) const { - initLayoutHelper(layout, QTextOption::NoWrap); - doLayout(layout); + +void ChatItem::initLayout(QTextLayout *layout) const +{ + initLayoutHelper(layout, QTextOption::NoWrap); + doLayout(layout); } -void ChatItem::doLayout(QTextLayout *layout) const { - layout->beginLayout(); - QTextLine line = layout->createLine(); - if(line.isValid()) { - line.setLineWidth(width()); - line.setPosition(QPointF(0,0)); - } - layout->endLayout(); + +void ChatItem::doLayout(QTextLayout *layout) const +{ + layout->beginLayout(); + QTextLine line = layout->createLine(); + if (line.isValid()) { + line.setLineWidth(width()); + line.setPosition(QPointF(0, 0)); + } + layout->endLayout(); } -UiStyle::FormatList ChatItem::formatList() const { - return data(MessageModel::FormatRole).value(); + +UiStyle::FormatList ChatItem::formatList() const +{ + return data(MessageModel::FormatRole).value(); } -qint16 ChatItem::posToCursor(const QPointF &posInLine) const { - QPointF pos = mapFromLine(posInLine); - if(pos.y() > height()) - return data(MessageModel::DisplayRole).toString().length(); - if(pos.y() < 0) - return 0; - for(int l = layout()->lineCount() - 1; l >= 0; l--) { - QTextLine line = layout()->lineAt(l); - if(pos.y() >= line.y()) { - return line.xToCursor(pos.x(), QTextLine::CursorOnCharacter); +qint16 ChatItem::posToCursor(const QPointF &posInLine) const +{ + QPointF pos = mapFromLine(posInLine); + if (pos.y() > height()) + return data(MessageModel::DisplayRole).toString().length(); + if (pos.y() < 0) + return 0; + + for (int l = layout()->lineCount() - 1; l >= 0; l--) { + QTextLine line = layout()->lineAt(l); + if (pos.y() >= line.y()) { + return line.xToCursor(pos.x(), QTextLine::CursorOnCharacter); + } } - } - return 0; + return 0; } -void ChatItem::paintBackground(QPainter *painter) { - QVariant bgBrush; - if(_selectionMode == FullSelection) - bgBrush = data(ChatLineModel::SelectedBackgroundRole); - else - bgBrush = data(ChatLineModel::BackgroundRole); - if(bgBrush.isValid()) - painter->fillRect(boundingRect(), bgBrush.value()); + +void ChatItem::paintBackground(QPainter *painter) +{ + QVariant bgBrush; + if (_selectionMode == FullSelection) + bgBrush = data(ChatLineModel::SelectedBackgroundRole); + else + bgBrush = data(ChatLineModel::BackgroundRole); + if (bgBrush.isValid()) + painter->fillRect(boundingRect(), bgBrush.value()); } + // NOTE: This is not the most time-efficient implementation, but it saves space by not caching unnecessary data // This is a deliberate trade-off. (-> selectFmt creation, data() call) -void ChatItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { - Q_UNUSED(option); Q_UNUSED(widget); - painter->save(); - painter->setClipRect(boundingRect()); - paintBackground(painter); +void ChatItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(option); Q_UNUSED(widget); + painter->save(); + painter->setClipRect(boundingRect()); + paintBackground(painter); - layout()->draw(painter, pos(), additionalFormats(), boundingRect()); + layout()->draw(painter, pos(), additionalFormats(), boundingRect()); - // layout()->draw(painter, QPointF(0,0), formats, boundingRect()); + // layout()->draw(painter, QPointF(0,0), formats, boundingRect()); - // Debuging Stuff - // uncomment partially or all of the following stuff: - // - // 0) alternativ painter color for debug stuff + // Debuging Stuff + // uncomment partially or all of the following stuff: + // + // 0) alternativ painter color for debug stuff // if(row() % 2) // painter->setPen(Qt::red); // else // painter->setPen(Qt::blue); - // 1) draw wordwrap points in the first line +// 1) draw wordwrap points in the first line // if(column() == 2) { // ChatLineModel::WrapList wrapList = data(ChatLineModel::WrapListRole).value(); // foreach(ChatLineModel::Word word, wrapList) { // if(word.endX > width()) -// break; +// break; // painter->drawLine(word.endX, 0, word.endX, height()); // } // } - // 2) draw MsgId over the time column +// 2) draw MsgId over the time column // if(column() == 0) { // QString msgIdString = QString::number(data(MessageModel::MsgIdRole).value().toInt()); // QPointF bottomPoint = boundingRect().bottomLeft(); // bottomPoint.ry() -= 2; // painter->drawText(bottomPoint, msgIdString); // } - // 3) draw bounding rect +// 3) draw bounding rect // painter->drawRect(_boundingRect.adjusted(0, 0, -1, -1)); - painter->restore(); + painter->restore(); } -void ChatItem::overlayFormat(UiStyle::FormatList &fmtList, int start, int end, quint32 overlayFmt) const { - for(int i = 0; i < fmtList.count(); i++) { - int fmtStart = fmtList.at(i).first; - int fmtEnd = (i < fmtList.count()-1 ? fmtList.at(i+1).first : data(MessageModel::DisplayRole).toString().length()); - - if(fmtEnd <= start) - continue; - if(fmtStart >= end) - break; - // split the format if necessary - if(fmtStart < start) { - fmtList.insert(i, fmtList.at(i)); - fmtList[++i].first = start; - } - if(end < fmtEnd) { - fmtList.insert(i, fmtList.at(i)); - fmtList[i+1].first = end; +void ChatItem::overlayFormat(UiStyle::FormatList &fmtList, int start, int end, quint32 overlayFmt) const +{ + for (int i = 0; i < fmtList.count(); i++) { + int fmtStart = fmtList.at(i).first; + int fmtEnd = (i < fmtList.count()-1 ? fmtList.at(i+1).first : data(MessageModel::DisplayRole).toString().length()); + + if (fmtEnd <= start) + continue; + if (fmtStart >= end) + break; + + // split the format if necessary + if (fmtStart < start) { + fmtList.insert(i, fmtList.at(i)); + fmtList[++i].first = start; + } + if (end < fmtEnd) { + fmtList.insert(i, fmtList.at(i)); + fmtList[i+1].first = end; + } + + fmtList[i].second |= overlayFmt; } - - fmtList[i].second |= overlayFmt; - } } -QVector ChatItem::additionalFormats() const { - return selectionFormats(); + +QVector ChatItem::additionalFormats() const +{ + return selectionFormats(); } -QVector ChatItem::selectionFormats() const { - if(!hasSelection()) - return QVector(); - int start, end; - if(_selectionMode == FullSelection) { - start = 0; - end = data(MessageModel::DisplayRole).toString().length(); - } else { - start = qMin(_selectionStart, _selectionEnd); - end = qMax(_selectionStart, _selectionEnd); - } +QVector ChatItem::selectionFormats() const +{ + if (!hasSelection()) + return QVector(); - UiStyle::FormatList fmtList = formatList(); + int start, end; + if (_selectionMode == FullSelection) { + start = 0; + end = data(MessageModel::DisplayRole).toString().length(); + } + else { + start = qMin(_selectionStart, _selectionEnd); + end = qMax(_selectionStart, _selectionEnd); + } - while(fmtList.count() > 1 && fmtList.at(1).first <= start) - fmtList.removeFirst(); + UiStyle::FormatList fmtList = formatList(); - fmtList.first().first = start; + while (fmtList.count() > 1 && fmtList.at(1).first <= start) + fmtList.removeFirst(); - while(fmtList.count() > 1 && fmtList.last().first >= end) - fmtList.removeLast(); + fmtList.first().first = start; - return QtUi::style()->toTextLayoutList(fmtList, end, UiStyle::Selected|data(ChatLineModel::MsgLabelRole).toUInt()).toVector(); -} + while (fmtList.count() > 1 && fmtList.last().first >= end) + fmtList.removeLast(); -bool ChatItem::hasSelection() const { - if(_selectionMode == NoSelection) - return false; - if(_selectionMode == FullSelection) - return true; - // partial - return _selectionStart != _selectionEnd; + return QtUi::style()->toTextLayoutList(fmtList, end, UiStyle::Selected|data(ChatLineModel::MsgLabelRole).toUInt()).toVector(); } -QString ChatItem::selection() const { - if(_selectionMode == FullSelection) - return data(MessageModel::DisplayRole).toString(); - if(_selectionMode == PartialSelection) - return data(MessageModel::DisplayRole).toString().mid(qMin(_selectionStart, _selectionEnd), qAbs(_selectionStart - _selectionEnd)); - return QString(); -} -void ChatItem::setSelection(SelectionMode mode, qint16 start, qint16 end) { - _selectionMode = mode; - _selectionStart = start; - _selectionEnd = end; - chatLine()->update(); +bool ChatItem::hasSelection() const +{ + if (_selectionMode == NoSelection) + return false; + if (_selectionMode == FullSelection) + return true; + // partial + return _selectionStart != _selectionEnd; } -void ChatItem::setFullSelection() { - if(_selectionMode != FullSelection) { - _selectionMode = FullSelection; - chatLine()->update(); - } + +QString ChatItem::selection() const +{ + if (_selectionMode == FullSelection) + return data(MessageModel::DisplayRole).toString(); + if (_selectionMode == PartialSelection) + return data(MessageModel::DisplayRole).toString().mid(qMin(_selectionStart, _selectionEnd), qAbs(_selectionStart - _selectionEnd)); + return QString(); } -void ChatItem::clearSelection() { - if(_selectionMode != NoSelection) { - _selectionMode = NoSelection; + +void ChatItem::setSelection(SelectionMode mode, qint16 start, qint16 end) +{ + _selectionMode = mode; + _selectionStart = start; + _selectionEnd = end; chatLine()->update(); - } } -void ChatItem::continueSelecting(const QPointF &pos) { - _selectionMode = PartialSelection; - _selectionEnd = posToCursor(pos); - chatLine()->update(); + +void ChatItem::setFullSelection() +{ + if (_selectionMode != FullSelection) { + _selectionMode = FullSelection; + chatLine()->update(); + } } -bool ChatItem::isPosOverSelection(const QPointF &pos) const { - if(_selectionMode == FullSelection) - return true; - if(_selectionMode == PartialSelection) { - int cursor = posToCursor(pos); - return cursor >= qMin(_selectionStart, _selectionEnd) && cursor <= qMax(_selectionStart, _selectionEnd); - } - return false; + +void ChatItem::clearSelection() +{ + if (_selectionMode != NoSelection) { + _selectionMode = NoSelection; + chatLine()->update(); + } } -QList ChatItem::findWords(const QString &searchWord, Qt::CaseSensitivity caseSensitive) { - QList resultList; - const QAbstractItemModel *model_ = model(); - if(!model_) - return resultList; - QString plainText = model_->data(model_->index(row(), column()), MessageModel::DisplayRole).toString(); - QList indexList; - int searchIdx = plainText.indexOf(searchWord, 0, caseSensitive); - while(searchIdx != -1) { - indexList << searchIdx; - searchIdx = plainText.indexOf(searchWord, searchIdx + 1, caseSensitive); - } - - foreach(int idx, indexList) { - QTextLine line = layout()->lineForTextPosition(idx); - qreal x = line.cursorToX(idx); - qreal width = line.cursorToX(idx + searchWord.count()) - x; - qreal height = line.height(); - qreal y = height * line.lineNumber(); - resultList << QRectF(x, y, width, height); - } +void ChatItem::continueSelecting(const QPointF &pos) +{ + _selectionMode = PartialSelection; + _selectionEnd = posToCursor(pos); + chatLine()->update(); +} - return resultList; + +bool ChatItem::isPosOverSelection(const QPointF &pos) const +{ + if (_selectionMode == FullSelection) + return true; + if (_selectionMode == PartialSelection) { + int cursor = posToCursor(pos); + return cursor >= qMin(_selectionStart, _selectionEnd) && cursor <= qMax(_selectionStart, _selectionEnd); + } + return false; } -void ChatItem::handleClick(const QPointF &pos, ChatScene::ClickMode clickMode) { - // single clicks are already handled by the scene (for clearing the selection) - if(clickMode == ChatScene::DragStartClick) { - chatScene()->setSelectingItem(this); - _selectionStart = _selectionEnd = posToCursor(pos); - _selectionMode = NoSelection; // will be set to PartialSelection by mouseMoveEvent - chatLine()->update(); - } + +QList ChatItem::findWords(const QString &searchWord, Qt::CaseSensitivity caseSensitive) +{ + QList resultList; + const QAbstractItemModel *model_ = model(); + if (!model_) + return resultList; + + QString plainText = model_->data(model_->index(row(), column()), MessageModel::DisplayRole).toString(); + QList indexList; + int searchIdx = plainText.indexOf(searchWord, 0, caseSensitive); + while (searchIdx != -1) { + indexList << searchIdx; + searchIdx = plainText.indexOf(searchWord, searchIdx + 1, caseSensitive); + } + + foreach(int idx, indexList) { + QTextLine line = layout()->lineForTextPosition(idx); + qreal x = line.cursorToX(idx); + qreal width = line.cursorToX(idx + searchWord.count()) - x; + qreal height = line.height(); + qreal y = height * line.lineNumber(); + resultList << QRectF(x, y, width, height); + } + + return resultList; } -void ChatItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { - if(event->buttons() == Qt::LeftButton) { - if(boundingRect().contains(event->pos())) { - qint16 end = posToCursor(event->pos()); - if(end != _selectionEnd) { - _selectionEnd = end; - _selectionMode = (_selectionStart != _selectionEnd ? PartialSelection : NoSelection); + +void ChatItem::handleClick(const QPointF &pos, ChatScene::ClickMode clickMode) +{ + // single clicks are already handled by the scene (for clearing the selection) + if (clickMode == ChatScene::DragStartClick) { + chatScene()->setSelectingItem(this); + _selectionStart = _selectionEnd = posToCursor(pos); + _selectionMode = NoSelection; // will be set to PartialSelection by mouseMoveEvent chatLine()->update(); - } - } else { - setFullSelection(); - chatScene()->startGlobalSelection(this, event->pos()); } - event->accept(); - } else { - event->ignore(); - } } -void ChatItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { - if(event->buttons() == Qt::LeftButton) - event->accept(); - else - event->ignore(); + +void ChatItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + if (event->buttons() == Qt::LeftButton) { + if (boundingRect().contains(event->pos())) { + qint16 end = posToCursor(event->pos()); + if (end != _selectionEnd) { + _selectionEnd = end; + _selectionMode = (_selectionStart != _selectionEnd ? PartialSelection : NoSelection); + chatLine()->update(); + } + } + else { + setFullSelection(); + chatScene()->startGlobalSelection(this, event->pos()); + } + event->accept(); + } + else { + event->ignore(); + } } -void ChatItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { - if(_selectionMode != NoSelection && event->button() == Qt::LeftButton) { - chatScene()->selectionToClipboard(QClipboard::Selection); - event->accept(); - } else - event->ignore(); + +void ChatItem::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + if (event->buttons() == Qt::LeftButton) + event->accept(); + else + event->ignore(); +} + + +void ChatItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + if (_selectionMode != NoSelection && event->button() == Qt::LeftButton) { + chatScene()->selectionToClipboard(QClipboard::Selection); + event->accept(); + } + else + event->ignore(); } -void ChatItem::addActionsToMenu(QMenu *menu, const QPointF &pos) { - Q_UNUSED(pos); - GraphicalUi::contextMenuActionProvider()->addActions(menu, chatScene()->filter(), data(MessageModel::BufferIdRole).value()); +void ChatItem::addActionsToMenu(QMenu *menu, const QPointF &pos) +{ + Q_UNUSED(pos); + + GraphicalUi::contextMenuActionProvider()->addActions(menu, chatScene()->filter(), data(MessageModel::BufferIdRole).value()); } + // ************************************************************ // SenderChatItem // ************************************************************ -void SenderChatItem::initLayout(QTextLayout *layout) const { - initLayoutHelper(layout, QTextOption::ManualWrap, Qt::AlignRight); - doLayout(layout); -} - -void SenderChatItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { - Q_UNUSED(option); Q_UNUSED(widget); - painter->save(); - painter->setClipRect(boundingRect()); - paintBackground(painter); - - qreal layoutWidth = layout()->minimumWidth(); - qreal offset = 0; - if(chatScene()->senderCutoffMode() == ChatScene::CutoffLeft) - offset = qMin(width() - layoutWidth, (qreal)0); - else - offset = qMax(layoutWidth - width(), (qreal)0); - - if(layoutWidth > width()) { - // Draw a nice gradient for longer items - // Qt's text drawing with a gradient brush sucks, so we use an alpha-channeled pixmap instead - QPixmap pixmap(layout()->boundingRect().toRect().size()); - pixmap.fill(Qt::transparent); - QPainter pixPainter(&pixmap); - layout()->draw(&pixPainter, QPointF(qMax(offset, (qreal)0), 0), additionalFormats()); - pixPainter.end(); - - // Create alpha channel mask - QPixmap mask(pixmap.size()); - QPainter maskPainter(&mask); - QLinearGradient gradient; - if(offset < 0) { - gradient.setStart(0, 0); - gradient.setFinalStop(12, 0); - gradient.setColorAt(0, Qt::black); - gradient.setColorAt(1, Qt::white); - } else { - gradient.setStart(width()-10, 0); - gradient.setFinalStop(width(), 0); - gradient.setColorAt(0, Qt::white); - gradient.setColorAt(1, Qt::black); - } - maskPainter.fillRect(0, 0, pixmap.width(), pixmap.height(), gradient); - pixmap.setAlphaChannel(mask); - painter->drawPixmap(pos(), pixmap); - } else { - layout()->draw(painter, pos(), additionalFormats(), boundingRect()); - } - painter->restore(); -} - -void SenderChatItem::handleClick(const QPointF &pos, ChatScene::ClickMode clickMode) { - if(clickMode == ChatScene::DoubleClick) { - BufferInfo curBufInfo = Client::networkModel()->bufferInfo(data(MessageModel::BufferIdRole).value()); - QString nick = data(MessageModel::EditRole).toString(); - // check if the nick is a valid ircUser - if(!nick.isEmpty() && Client::network(curBufInfo.networkId())->ircUser(nick)) - Client::bufferModel()->switchToOrStartQuery(curBufInfo.networkId(), nick); - } - else - ChatItem::handleClick(pos, clickMode); +void SenderChatItem::initLayout(QTextLayout *layout) const +{ + initLayoutHelper(layout, QTextOption::ManualWrap, Qt::AlignRight); + doLayout(layout); +} + + +void SenderChatItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(option); Q_UNUSED(widget); + painter->save(); + painter->setClipRect(boundingRect()); + paintBackground(painter); + + qreal layoutWidth = layout()->minimumWidth(); + qreal offset = 0; + if (chatScene()->senderCutoffMode() == ChatScene::CutoffLeft) + offset = qMin(width() - layoutWidth, (qreal)0); + else + offset = qMax(layoutWidth - width(), (qreal)0); + + if (layoutWidth > width()) { + // Draw a nice gradient for longer items + // Qt's text drawing with a gradient brush sucks, so we use an alpha-channeled pixmap instead + QPixmap pixmap(layout()->boundingRect().toRect().size()); + pixmap.fill(Qt::transparent); + QPainter pixPainter(&pixmap); + layout()->draw(&pixPainter, QPointF(qMax(offset, (qreal)0), 0), additionalFormats()); + pixPainter.end(); + + // Create alpha channel mask + QPixmap mask(pixmap.size()); + QPainter maskPainter(&mask); + QLinearGradient gradient; + if (offset < 0) { + gradient.setStart(0, 0); + gradient.setFinalStop(12, 0); + gradient.setColorAt(0, Qt::black); + gradient.setColorAt(1, Qt::white); + } + else { + gradient.setStart(width()-10, 0); + gradient.setFinalStop(width(), 0); + gradient.setColorAt(0, Qt::white); + gradient.setColorAt(1, Qt::black); + } + maskPainter.fillRect(0, 0, pixmap.width(), pixmap.height(), gradient); + pixmap.setAlphaChannel(mask); + painter->drawPixmap(pos(), pixmap); + } + else { + layout()->draw(painter, pos(), additionalFormats(), boundingRect()); + } + painter->restore(); } + +void SenderChatItem::handleClick(const QPointF &pos, ChatScene::ClickMode clickMode) +{ + if (clickMode == ChatScene::DoubleClick) { + BufferInfo curBufInfo = Client::networkModel()->bufferInfo(data(MessageModel::BufferIdRole).value()); + QString nick = data(MessageModel::EditRole).toString(); + // check if the nick is a valid ircUser + if (!nick.isEmpty() && Client::network(curBufInfo.networkId())->ircUser(nick)) + Client::bufferModel()->switchToOrStartQuery(curBufInfo.networkId(), nick); + } + else + ChatItem::handleClick(pos, clickMode); +} + + // ************************************************************ // ContentsChatItem // ************************************************************ @@ -475,274 +559,319 @@ void SenderChatItem::handleClick(const QPointF &pos, ChatScene::ClickMode clickM ContentsChatItem::ActionProxy ContentsChatItem::_actionProxy; ContentsChatItem::ContentsChatItem(const QPointF &pos, const qreal &width, ChatLine *parent) - : ChatItem(QRectF(pos, QSizeF(width, 0)), parent), + : ChatItem(QRectF(pos, QSizeF(width, 0)), parent), _data(0) { - setPos(pos); - setGeometryByWidth(width); + setPos(pos); + setGeometryByWidth(width); } -QFontMetricsF *ContentsChatItem::fontMetrics() const { - return QtUi::style()->fontMetrics(data(ChatLineModel::FormatRole).value().at(0).second, 0); + +QFontMetricsF *ContentsChatItem::fontMetrics() const +{ + return QtUi::style()->fontMetrics(data(ChatLineModel::FormatRole).value().at(0).second, 0); } -ContentsChatItem::~ContentsChatItem() { - delete _data; + +ContentsChatItem::~ContentsChatItem() +{ + delete _data; } -void ContentsChatItem::clearCache() { - delete _data; - _data = 0; - ChatItem::clearCache(); + +void ContentsChatItem::clearCache() +{ + delete _data; + _data = 0; + ChatItem::clearCache(); } -ContentsChatItemPrivate *ContentsChatItem::privateData() const { - if(!_data) { - ContentsChatItem *that = const_cast(this); - that->_data = new ContentsChatItemPrivate(ClickableList::fromString(data(ChatLineModel::DisplayRole).toString()), that); - } - return _data; + +ContentsChatItemPrivate *ContentsChatItem::privateData() const +{ + if (!_data) { + ContentsChatItem *that = const_cast(this); + that->_data = new ContentsChatItemPrivate(ClickableList::fromString(data(ChatLineModel::DisplayRole).toString()), that); + } + return _data; } -qreal ContentsChatItem::setGeometryByWidth(qreal w) { - // We use this for reloading layout info as well, so we can't bail out if the width doesn't change - // compute height - int lines = 1; - WrapColumnFinder finder(this); - while(finder.nextWrapColumn(w) > 0) - lines++; - qreal spacing = qMax(fontMetrics()->lineSpacing(), fontMetrics()->height()); // cope with negative leading() - qreal h = lines * spacing; - delete _data; - _data = 0; +qreal ContentsChatItem::setGeometryByWidth(qreal w) +{ + // We use this for reloading layout info as well, so we can't bail out if the width doesn't change + + // compute height + int lines = 1; + WrapColumnFinder finder(this); + while (finder.nextWrapColumn(w) > 0) + lines++; + qreal spacing = qMax(fontMetrics()->lineSpacing(), fontMetrics()->height()); // cope with negative leading() + qreal h = lines * spacing; + delete _data; + _data = 0; - if(w != width() || h != height()) - setGeometry(w, h); + if (w != width() || h != height()) + setGeometry(w, h); - return h; + return h; } -void ContentsChatItem::initLayout(QTextLayout *layout) const { - initLayoutHelper(layout, QTextOption::WrapAtWordBoundaryOrAnywhere); - doLayout(layout); + +void ContentsChatItem::initLayout(QTextLayout *layout) const +{ + initLayoutHelper(layout, QTextOption::WrapAtWordBoundaryOrAnywhere); + doLayout(layout); } -void ContentsChatItem::doLayout(QTextLayout *layout) const { - ChatLineModel::WrapList wrapList = data(ChatLineModel::WrapListRole).value(); - if(!wrapList.count()) return; // empty chatitem - qreal h = 0; - qreal spacing = qMax(fontMetrics()->lineSpacing(), fontMetrics()->height()); // cope with negative leading() - WrapColumnFinder finder(this); - layout->beginLayout(); - forever { - QTextLine line = layout->createLine(); - if(!line.isValid()) - break; +void ContentsChatItem::doLayout(QTextLayout *layout) const +{ + ChatLineModel::WrapList wrapList = data(ChatLineModel::WrapListRole).value(); + if (!wrapList.count()) return; // empty chatitem + + qreal h = 0; + qreal spacing = qMax(fontMetrics()->lineSpacing(), fontMetrics()->height()); // cope with negative leading() + WrapColumnFinder finder(this); + layout->beginLayout(); + forever { + QTextLine line = layout->createLine(); + if (!line.isValid()) + break; + + int col = finder.nextWrapColumn(width()); + if (col < 0) + col = layout->text().length(); + int num = col - line.textStart(); + + line.setNumColumns(num); + + // Sometimes, setNumColumns will create a line that's too long (cf. Qt bug 238249) + // We verify this and try setting the width again, making it shorter each time until the lengths match. + // Dead fugly, but seems to work… + for (int i = line.textLength()-1; i >= 0 && line.textLength() > num; i--) { + line.setNumColumns(i); + } + if (num != line.textLength()) { + qWarning() << "WARNING: Layout engine couldn't workaround Qt bug 238249, please report!"; + // qDebug() << num << line.textLength() << t.mid(line.textStart(), line.textLength()) << t.mid(line.textStart() + line.textLength()); + } + + line.setPosition(QPointF(0, h)); + h += spacing; + } + layout->endLayout(); +} - int col = finder.nextWrapColumn(width()); - if(col < 0) - col = layout->text().length(); - int num = col - line.textStart(); - line.setNumColumns(num); +Clickable ContentsChatItem::clickableAt(const QPointF &pos) const +{ + return privateData()->clickables.atCursorPos(posToCursor(pos)); +} - // Sometimes, setNumColumns will create a line that's too long (cf. Qt bug 238249) - // We verify this and try setting the width again, making it shorter each time until the lengths match. - // Dead fugly, but seems to work… - for(int i = line.textLength()-1; i >= 0 && line.textLength() > num; i--) { - line.setNumColumns(i); - } - if(num != line.textLength()) { - qWarning() << "WARNING: Layout engine couldn't workaround Qt bug 238249, please report!"; - // qDebug() << num << line.textLength() << t.mid(line.textStart(), line.textLength()) << t.mid(line.textStart() + line.textLength()); + +UiStyle::FormatList ContentsChatItem::formatList() const +{ + UiStyle::FormatList fmtList = ChatItem::formatList(); + for (int i = 0; i < privateData()->clickables.count(); i++) { + Clickable click = privateData()->clickables.at(i); + if (click.type() == Clickable::Url) { + overlayFormat(fmtList, click.start(), click.start() + click.length(), UiStyle::Url); + } } + return fmtList; +} + - line.setPosition(QPointF(0, h)); - h += spacing; - } - layout->endLayout(); +QVector ContentsChatItem::additionalFormats() const +{ + QVector fmt = ChatItem::additionalFormats(); + // mark a clickable if hovered upon + if (privateData()->currentClickable.isValid()) { + Clickable click = privateData()->currentClickable; + QTextLayout::FormatRange f; + f.start = click.start(); + f.length = click.length(); + f.format.setFontUnderline(true); + fmt.append(f); + } + return fmt; } -Clickable ContentsChatItem::clickableAt(const QPointF &pos) const { - return privateData()->clickables.atCursorPos(posToCursor(pos)); + +void ContentsChatItem::endHoverMode() +{ + if (privateData()) { + if (privateData()->currentClickable.isValid()) { + chatLine()->unsetCursor(); + privateData()->currentClickable = Clickable(); + } + clearWebPreview(); + chatLine()->update(); + } } -UiStyle::FormatList ContentsChatItem::formatList() const { - UiStyle::FormatList fmtList = ChatItem::formatList(); - for(int i = 0; i < privateData()->clickables.count(); i++) { - Clickable click = privateData()->clickables.at(i); - if(click.type() == Clickable::Url) { - overlayFormat(fmtList, click.start(), click.start() + click.length(), UiStyle::Url); + +void ContentsChatItem::handleClick(const QPointF &pos, ChatScene::ClickMode clickMode) +{ + if (clickMode == ChatScene::SingleClick) { + qint16 idx = posToCursor(pos); + Clickable foo = privateData()->clickables.atCursorPos(idx); + if (foo.isValid()) { + NetworkId networkId = Client::networkModel()->networkId(data(MessageModel::BufferIdRole).value()); + QString text = data(ChatLineModel::DisplayRole).toString(); + foo.activate(networkId, text); + } + } + else if (clickMode == ChatScene::DoubleClick) { + chatScene()->setSelectingItem(this); + setSelectionMode(PartialSelection); + Clickable click = clickableAt(pos); + if (click.isValid()) { + setSelectionStart(click.start()); + setSelectionEnd(click.start() + click.length()); + } + else { + // find word boundary + QString str = data(ChatLineModel::DisplayRole).toString(); + qint16 cursor = posToCursor(pos); + qint16 start = str.lastIndexOf(QRegExp("\\W"), cursor) + 1; + qint16 end = qMin(str.indexOf(QRegExp("\\W"), cursor), str.length()); + if (end < 0) end = str.length(); + setSelectionStart(start); + setSelectionEnd(end); + } + chatLine()->update(); } - } - return fmtList; + else if (clickMode == ChatScene::TripleClick) { + setSelection(PartialSelection, 0, data(ChatLineModel::DisplayRole).toString().length()); + } + ChatItem::handleClick(pos, clickMode); +} + + +void ContentsChatItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + // mouse move events always mean we're not hovering anymore... + endHoverMode(); + ChatItem::mouseMoveEvent(event); +} + + +void ContentsChatItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) +{ + endHoverMode(); + event->accept(); } -QVector ContentsChatItem::additionalFormats() const { - QVector fmt = ChatItem::additionalFormats(); - // mark a clickable if hovered upon - if(privateData()->currentClickable.isValid()) { - Clickable click = privateData()->currentClickable; - QTextLayout::FormatRange f; - f.start = click.start(); - f.length = click.length(); - f.format.setFontUnderline(true); - fmt.append(f); - } - return fmt; + +void ContentsChatItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) +{ + bool onClickable = false; + Clickable click = clickableAt(event->pos()); + if (click.isValid()) { + if (click.type() == Clickable::Url) { + onClickable = true; + showWebPreview(click); + } + else if (click.type() == Clickable::Channel) { + QString name = data(ChatLineModel::DisplayRole).toString().mid(click.start(), click.length()); + // don't make clickable if it's our own name + BufferId myId = data(MessageModel::BufferIdRole).value(); + if (Client::networkModel()->bufferName(myId) != name) + onClickable = true; + } + if (onClickable) { + chatLine()->setCursor(Qt::PointingHandCursor); + privateData()->currentClickable = click; + chatLine()->update(); + return; + } + } + if (!onClickable) endHoverMode(); + event->accept(); } -void ContentsChatItem::endHoverMode() { - if(privateData()) { - if(privateData()->currentClickable.isValid()) { - chatLine()->unsetCursor(); - privateData()->currentClickable = Clickable(); + +void ContentsChatItem::addActionsToMenu(QMenu *menu, const QPointF &pos) +{ + if (privateData()->currentClickable.isValid()) { + Clickable click = privateData()->currentClickable; + switch (click.type()) { + case Clickable::Url: + privateData()->activeClickable = click; + menu->addAction(SmallIcon("edit-copy"), tr("Copy Link Address"), + &_actionProxy, SLOT(copyLinkToClipboard()))->setData(QVariant::fromValue(this)); + break; + case Clickable::Channel: + { + // Hide existing menu actions, they confuse us when right-clicking on a clickable + foreach(QAction *action, menu->actions()) + action->setVisible(false); + QString name = data(ChatLineModel::DisplayRole).toString().mid(click.start(), click.length()); + GraphicalUi::contextMenuActionProvider()->addActions(menu, chatScene()->filter(), data(MessageModel::BufferIdRole).value(), name); + break; + } + default: + break; + } } - clearWebPreview(); - chatLine()->update(); - } -} - -void ContentsChatItem::handleClick(const QPointF &pos, ChatScene::ClickMode clickMode) { - if(clickMode == ChatScene::SingleClick) { - qint16 idx = posToCursor(pos); - Clickable foo = privateData()->clickables.atCursorPos(idx); - if(foo.isValid()) { - NetworkId networkId = Client::networkModel()->networkId(data(MessageModel::BufferIdRole).value()); - QString text = data(ChatLineModel::DisplayRole).toString(); - foo.activate(networkId, text); - } - } else if(clickMode == ChatScene::DoubleClick) { - chatScene()->setSelectingItem(this); - setSelectionMode(PartialSelection); - Clickable click = clickableAt(pos); - if(click.isValid()) { - setSelectionStart(click.start()); - setSelectionEnd(click.start() + click.length()); - } else { - // find word boundary - QString str = data(ChatLineModel::DisplayRole).toString(); - qint16 cursor = posToCursor(pos); - qint16 start = str.lastIndexOf(QRegExp("\\W"), cursor) + 1; - qint16 end = qMin(str.indexOf(QRegExp("\\W"), cursor), str.length()); - if(end < 0) end = str.length(); - setSelectionStart(start); - setSelectionEnd(end); + else { + // Buffer-specific actions + ChatItem::addActionsToMenu(menu, pos); + } +} + + +void ContentsChatItem::copyLinkToClipboard() +{ + Clickable click = privateData()->activeClickable; + if (click.isValid() && click.type() == Clickable::Url) { + QString url = data(ChatLineModel::DisplayRole).toString().mid(click.start(), click.length()); + if (!url.contains("://")) + url = "http://" + url; + chatScene()->stringToClipboard(url); } - chatLine()->update(); - } else if(clickMode == ChatScene::TripleClick) { - setSelection(PartialSelection, 0, data(ChatLineModel::DisplayRole).toString().length()); - } - ChatItem::handleClick(pos, clickMode); -} - -void ContentsChatItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { - // mouse move events always mean we're not hovering anymore... - endHoverMode(); - ChatItem::mouseMoveEvent(event); -} - -void ContentsChatItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { - endHoverMode(); - event->accept(); -} - -void ContentsChatItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { - bool onClickable = false; - Clickable click = clickableAt(event->pos()); - if(click.isValid()) { - if(click.type() == Clickable::Url) { - onClickable = true; - showWebPreview(click); - } else if(click.type() == Clickable::Channel) { - QString name = data(ChatLineModel::DisplayRole).toString().mid(click.start(), click.length()); - // don't make clickable if it's our own name - BufferId myId = data(MessageModel::BufferIdRole).value(); - if(Client::networkModel()->bufferName(myId) != name) - onClickable = true; - } - if(onClickable) { - chatLine()->setCursor(Qt::PointingHandCursor); - privateData()->currentClickable = click; - chatLine()->update(); - return; - } - } - if(!onClickable) endHoverMode(); - event->accept(); -} - -void ContentsChatItem::addActionsToMenu(QMenu *menu, const QPointF &pos) { - if(privateData()->currentClickable.isValid()) { - Clickable click = privateData()->currentClickable; - switch(click.type()) { - case Clickable::Url: - privateData()->activeClickable = click; - menu->addAction(SmallIcon("edit-copy"), tr("Copy Link Address"), - &_actionProxy, SLOT(copyLinkToClipboard()))->setData(QVariant::fromValue(this)); - break; - case Clickable::Channel: { - // Hide existing menu actions, they confuse us when right-clicking on a clickable - foreach(QAction *action, menu->actions()) - action->setVisible(false); - QString name = data(ChatLineModel::DisplayRole).toString().mid(click.start(), click.length()); - GraphicalUi::contextMenuActionProvider()->addActions(menu, chatScene()->filter(), data(MessageModel::BufferIdRole).value(), name); - break; - } - default: - break; - } - } else { - // Buffer-specific actions - ChatItem::addActionsToMenu(menu, pos); - } -} - -void ContentsChatItem::copyLinkToClipboard() { - Clickable click = privateData()->activeClickable; - if(click.isValid() && click.type() == Clickable::Url) { - QString url = data(ChatLineModel::DisplayRole).toString().mid(click.start(), click.length()); - if(!url.contains("://")) - url = "http://" + url; - chatScene()->stringToClipboard(url); - } } + /******** WEB PREVIEW *****************************************************************************/ -void ContentsChatItem::showWebPreview(const Clickable &click) { +void ContentsChatItem::showWebPreview(const Clickable &click) +{ #ifndef HAVE_WEBKIT - Q_UNUSED(click); + Q_UNUSED(click); #else - QTextLine line = layout()->lineForTextPosition(click.start()); - qreal x = line.cursorToX(click.start()); - qreal width = line.cursorToX(click.start() + click.length()) - x; - qreal height = line.height(); - qreal y = height * line.lineNumber(); - - QPointF topLeft = mapToScene(pos()) + QPointF(x, y); - QRectF urlRect = QRectF(topLeft.x(), topLeft.y(), width, height); - - QString urlstr = data(ChatLineModel::DisplayRole).toString().mid(click.start(), click.length()); - if(!urlstr.contains("://")) - urlstr= "http://" + urlstr; - QUrl url = QUrl::fromEncoded(urlstr.toUtf8(), QUrl::TolerantMode); - chatScene()->loadWebPreview(this, url, urlRect); + QTextLine line = layout()->lineForTextPosition(click.start()); + qreal x = line.cursorToX(click.start()); + qreal width = line.cursorToX(click.start() + click.length()) - x; + qreal height = line.height(); + qreal y = height * line.lineNumber(); + + QPointF topLeft = mapToScene(pos()) + QPointF(x, y); + QRectF urlRect = QRectF(topLeft.x(), topLeft.y(), width, height); + + QString urlstr = data(ChatLineModel::DisplayRole).toString().mid(click.start(), click.length()); + if (!urlstr.contains("://")) + urlstr = "http://" + urlstr; + QUrl url = QUrl::fromEncoded(urlstr.toUtf8(), QUrl::TolerantMode); + chatScene()->loadWebPreview(this, url, urlRect); #endif } -void ContentsChatItem::clearWebPreview() { + +void ContentsChatItem::clearWebPreview() +{ #ifdef HAVE_WEBKIT - chatScene()->clearWebPreview(this); + chatScene()->clearWebPreview(this); #endif } + /*************************************************************************************************/ ContentsChatItem::WrapColumnFinder::WrapColumnFinder(const ChatItem *_item) - : item(_item), + : item(_item), wrapList(item->data(ChatLineModel::WrapListRole).value()), wordidx(0), lineCount(0), @@ -750,57 +879,62 @@ ContentsChatItem::WrapColumnFinder::WrapColumnFinder(const ChatItem *_item) { } -ContentsChatItem::WrapColumnFinder::~WrapColumnFinder() { -} - -qint16 ContentsChatItem::WrapColumnFinder::nextWrapColumn(qreal width) { - if(wordidx >= wrapList.count()) - return -1; - - lineCount++; - qreal targetWidth = lineCount * width + choppedTrailing; - - qint16 start = wordidx; - qint16 end = wrapList.count() - 1; - - // check if the whole line fits - if(wrapList.at(end).endX <= targetWidth) // || start == end) - return -1; - - // check if we have a very long word that needs inter word wrap - if(wrapList.at(start).endX > targetWidth) { - if(!line.isValid()) { - item->initLayoutHelper(&layout, QTextOption::NoWrap); - layout.beginLayout(); - line = layout.createLine(); - layout.endLayout(); - } - return line.xToCursor(targetWidth, QTextLine::CursorOnCharacter); - } - while(true) { - if(start + 1 == end) { - wordidx = end; - const ChatLineModel::Word &lastWord = wrapList.at(start); // the last word we were able to squeeze in +ContentsChatItem::WrapColumnFinder::~WrapColumnFinder() +{ +} - // both cases should be cought preliminary - Q_ASSERT(lastWord.endX <= targetWidth); // ensure that "start" really fits in - Q_ASSERT(end < wrapList.count()); // ensure that start isn't the last word - choppedTrailing += lastWord.trailing - (targetWidth - lastWord.endX); - return wrapList.at(wordidx).start; +qint16 ContentsChatItem::WrapColumnFinder::nextWrapColumn(qreal width) +{ + if (wordidx >= wrapList.count()) + return -1; + + lineCount++; + qreal targetWidth = lineCount * width + choppedTrailing; + + qint16 start = wordidx; + qint16 end = wrapList.count() - 1; + + // check if the whole line fits + if (wrapList.at(end).endX <= targetWidth) // || start == end) + return -1; + + // check if we have a very long word that needs inter word wrap + if (wrapList.at(start).endX > targetWidth) { + if (!line.isValid()) { + item->initLayoutHelper(&layout, QTextOption::NoWrap); + layout.beginLayout(); + line = layout.createLine(); + layout.endLayout(); + } + return line.xToCursor(targetWidth, QTextLine::CursorOnCharacter); } - qint16 pivot = (end + start) / 2; - if(wrapList.at(pivot).endX > targetWidth) { - end = pivot; - } else { - start = pivot; + while (true) { + if (start + 1 == end) { + wordidx = end; + const ChatLineModel::Word &lastWord = wrapList.at(start); // the last word we were able to squeeze in + + // both cases should be cought preliminary + Q_ASSERT(lastWord.endX <= targetWidth); // ensure that "start" really fits in + Q_ASSERT(end < wrapList.count()); // ensure that start isn't the last word + + choppedTrailing += lastWord.trailing - (targetWidth - lastWord.endX); + return wrapList.at(wordidx).start; + } + + qint16 pivot = (end + start) / 2; + if (wrapList.at(pivot).endX > targetWidth) { + end = pivot; + } + else { + start = pivot; + } } - } - Q_ASSERT(false); - return -1; + Q_ASSERT(false); + return -1; } -/*************************************************************************************************/ +/*************************************************************************************************/ diff --git a/src/qtui/chatitem.h b/src/qtui/chatitem.h index af0540e3..7b9d6512 100644 --- a/src/qtui/chatitem.h +++ b/src/qtui/chatitem.h @@ -38,248 +38,261 @@ class ChatView; /* All external positions are relative to the parent ChatLine */ /* Yes, that's also true for the boundingRect() and related things */ -class ChatItem { +class ChatItem +{ protected: - // boundingRect is relative to the parent ChatLine - ChatItem(const QRectF &boundingRect, ChatLine *parent); - virtual ~ChatItem(); + // boundingRect is relative to the parent ChatLine + ChatItem(const QRectF &boundingRect, ChatLine *parent); + virtual ~ChatItem(); public: - const QAbstractItemModel *model() const; - ChatLine *chatLine() const; - ChatScene *chatScene() const; - ChatView *chatView() const; - int row() const; - virtual ChatLineModel::ColumnType column() const = 0; - - // The boundingRect() is relative to the parent ChatLine - inline QRectF boundingRect() const; - inline qreal width() const; - inline qreal height() const; - inline QPointF pos() const; - inline qreal x() const; - inline qreal y() const; - - QPointF mapToLine(const QPointF &) const; - QPointF mapFromLine(const QPointF &) const; - QPointF mapToScene(const QPointF &) const; - QPointF mapFromScene(const QPointF &) const; - - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - virtual inline int type() const { return ChatScene::ChatItemType; } - - QVariant data(int role) const; - - // selection stuff, to be called by the scene - QString selection() const; - void clearSelection(); - void setFullSelection(); - void continueSelecting(const QPointF &pos); - bool hasSelection() const; - bool isPosOverSelection(const QPointF &pos) const; - - QList findWords(const QString &searchWord, Qt::CaseSensitivity caseSensitive); - - virtual void addActionsToMenu(QMenu *menu, const QPointF &itemPos); - virtual void handleClick(const QPointF &pos, ChatScene::ClickMode); - - void initLayoutHelper(QTextLayout *layout, QTextOption::WrapMode, Qt::Alignment = Qt::AlignLeft) const; - - //! Remove internally cached data - /** This removes e.g. the cached QTextLayout to avoid wasting space for nonvisible ChatLines - */ - virtual void clearCache(); + const QAbstractItemModel *model() const; + ChatLine *chatLine() const; + ChatScene *chatScene() const; + ChatView *chatView() const; + int row() const; + virtual ChatLineModel::ColumnType column() const = 0; + + // The boundingRect() is relative to the parent ChatLine + inline QRectF boundingRect() const; + inline qreal width() const; + inline qreal height() const; + inline QPointF pos() const; + inline qreal x() const; + inline qreal y() const; + + QPointF mapToLine(const QPointF &) const; + QPointF mapFromLine(const QPointF &) const; + QPointF mapToScene(const QPointF &) const; + QPointF mapFromScene(const QPointF &) const; + + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); + virtual inline int type() const { return ChatScene::ChatItemType; } + + QVariant data(int role) const; + + // selection stuff, to be called by the scene + QString selection() const; + void clearSelection(); + void setFullSelection(); + void continueSelecting(const QPointF &pos); + bool hasSelection() const; + bool isPosOverSelection(const QPointF &pos) const; + + QList findWords(const QString &searchWord, Qt::CaseSensitivity caseSensitive); + + virtual void addActionsToMenu(QMenu *menu, const QPointF &itemPos); + virtual void handleClick(const QPointF &pos, ChatScene::ClickMode); + + void initLayoutHelper(QTextLayout *layout, QTextOption::WrapMode, Qt::Alignment = Qt::AlignLeft) const; + + //! Remove internally cached data + /** This removes e.g. the cached QTextLayout to avoid wasting space for nonvisible ChatLines + */ + virtual void clearCache(); protected: - enum SelectionMode { - NoSelection, - PartialSelection, - FullSelection - }; - - virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); - virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); - virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); - virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *) {} - virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *) {} - virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *) {} - - QTextLayout *layout() const; - - virtual void initLayout(QTextLayout *layout) const; - virtual void doLayout(QTextLayout *) const; - virtual UiStyle::FormatList formatList() const; - - void paintBackground(QPainter *); - QVector selectionFormats() const; - virtual QVector additionalFormats() const; - void overlayFormat(UiStyle::FormatList &fmtList, int start, int end, quint32 overlayFmt) const; - - inline qint16 selectionStart() const { return _selectionStart; } - inline void setSelectionStart(qint16 start) { _selectionStart = start; } - inline qint16 selectionEnd() const { return _selectionEnd; } - inline void setSelectionEnd(qint16 end) { _selectionEnd = end; } - inline SelectionMode selectionMode() const { return _selectionMode; } - inline void setSelectionMode(SelectionMode mode) { _selectionMode = mode; } - void setSelection(SelectionMode mode, qint16 selectionStart, qint16 selectionEnd); - - qint16 posToCursor(const QPointF &pos) const; - - inline void setGeometry(qreal width, qreal height) { clearCache(); _boundingRect.setSize(QSizeF(width, height)); } - inline void setHeight(const qreal &height) { clearCache(); _boundingRect.setHeight(height); } - inline void setWidth(const qreal &width) { clearCache(); _boundingRect.setWidth(width); } - inline void setPos(const QPointF &pos) { _boundingRect.moveTopLeft(pos); } + enum SelectionMode { + NoSelection, + PartialSelection, + FullSelection + }; + + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *) {} + virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *) {} + virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *) {} + + QTextLayout *layout() const; + + virtual void initLayout(QTextLayout *layout) const; + virtual void doLayout(QTextLayout *) const; + virtual UiStyle::FormatList formatList() const; + + void paintBackground(QPainter *); + QVector selectionFormats() const; + virtual QVector additionalFormats() const; + void overlayFormat(UiStyle::FormatList &fmtList, int start, int end, quint32 overlayFmt) const; + + inline qint16 selectionStart() const { return _selectionStart; } + inline void setSelectionStart(qint16 start) { _selectionStart = start; } + inline qint16 selectionEnd() const { return _selectionEnd; } + inline void setSelectionEnd(qint16 end) { _selectionEnd = end; } + inline SelectionMode selectionMode() const { return _selectionMode; } + inline void setSelectionMode(SelectionMode mode) { _selectionMode = mode; } + void setSelection(SelectionMode mode, qint16 selectionStart, qint16 selectionEnd); + + qint16 posToCursor(const QPointF &pos) const; + + inline void setGeometry(qreal width, qreal height) { clearCache(); _boundingRect.setSize(QSizeF(width, height)); } + inline void setHeight(const qreal &height) { clearCache(); _boundingRect.setHeight(height); } + inline void setWidth(const qreal &width) { clearCache(); _boundingRect.setWidth(width); } + inline void setPos(const QPointF &pos) { _boundingRect.moveTopLeft(pos); } private: - ChatLine *_parent; - QRectF _boundingRect; + ChatLine *_parent; + QRectF _boundingRect; - SelectionMode _selectionMode; - qint16 _selectionStart, _selectionEnd; + SelectionMode _selectionMode; + qint16 _selectionStart, _selectionEnd; - mutable QTextLayout *_cachedLayout; + mutable QTextLayout *_cachedLayout; - // internal selection stuff - void setSelection(int start, int length); + // internal selection stuff + void setSelection(int start, int length); - friend class ChatLine; + friend class ChatLine; }; + // ************************************************************ // TimestampChatItem // ************************************************************ //! A ChatItem for the timestamp column -class TimestampChatItem : public ChatItem { +class TimestampChatItem : public ChatItem +{ public: - TimestampChatItem(const QRectF &boundingRect, ChatLine *parent) : ChatItem(boundingRect, parent) {} - virtual inline int type() const { return ChatScene::TimestampChatItemType; } - virtual inline ChatLineModel::ColumnType column() const { return ChatLineModel::TimestampColumn; } + TimestampChatItem(const QRectF &boundingRect, ChatLine *parent) : ChatItem(boundingRect, parent) {} + virtual inline int type() const { return ChatScene::TimestampChatItemType; } + virtual inline ChatLineModel::ColumnType column() const { return ChatLineModel::TimestampColumn; } }; + // ************************************************************ // SenderChatItem // ************************************************************ //! A ChatItem for the sender column -class SenderChatItem : public ChatItem { +class SenderChatItem : public ChatItem +{ public: - SenderChatItem(const QRectF &boundingRect, ChatLine *parent) : ChatItem(boundingRect, parent) {} - virtual inline ChatLineModel::ColumnType column() const { return ChatLineModel::SenderColumn; } - virtual void handleClick(const QPointF &pos, ChatScene::ClickMode clickMode); + SenderChatItem(const QRectF &boundingRect, ChatLine *parent) : ChatItem(boundingRect, parent) {} + virtual inline ChatLineModel::ColumnType column() const { return ChatLineModel::SenderColumn; } + virtual void handleClick(const QPointF &pos, ChatScene::ClickMode clickMode); protected: - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - virtual inline int type() const { return ChatScene::SenderChatItemType; } - virtual void initLayout(QTextLayout *layout) const; + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); + virtual inline int type() const { return ChatScene::SenderChatItemType; } + virtual void initLayout(QTextLayout *layout) const; }; + // ************************************************************ // ContentsChatItem // ************************************************************ struct ContentsChatItemPrivate; //! A ChatItem for the contents column -class ContentsChatItem : public ChatItem { - Q_DECLARE_TR_FUNCTIONS(ContentsChatItem) +class ContentsChatItem : public ChatItem +{ + Q_DECLARE_TR_FUNCTIONS(ContentsChatItem) public: - ContentsChatItem(const QPointF &pos, const qreal &width, ChatLine *parent); - ~ContentsChatItem(); + ContentsChatItem(const QPointF &pos, const qreal &width, ChatLine *parent); + ~ContentsChatItem(); - virtual inline int type() const { return ChatScene::ContentsChatItemType; } + virtual inline int type() const { return ChatScene::ContentsChatItemType; } - inline ChatLineModel::ColumnType column() const { return ChatLineModel::ContentsColumn; } - QFontMetricsF *fontMetrics() const; + inline ChatLineModel::ColumnType column() const { return ChatLineModel::ContentsColumn; } + QFontMetricsF *fontMetrics() const; - virtual void clearCache(); + virtual void clearCache(); protected: - virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); - virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); - virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event); - virtual void handleClick(const QPointF &pos, ChatScene::ClickMode clickMode); + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); + virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event); + virtual void handleClick(const QPointF &pos, ChatScene::ClickMode clickMode); - virtual void addActionsToMenu(QMenu *menu, const QPointF &itemPos); - virtual void copyLinkToClipboard(); + virtual void addActionsToMenu(QMenu *menu, const QPointF &itemPos); + virtual void copyLinkToClipboard(); - virtual QVector additionalFormats() const; + virtual QVector additionalFormats() const; - virtual void initLayout(QTextLayout *layout) const; - virtual void doLayout(QTextLayout *layout) const; - virtual UiStyle::FormatList formatList() const; + virtual void initLayout(QTextLayout *layout) const; + virtual void doLayout(QTextLayout *layout) const; + virtual UiStyle::FormatList formatList() const; private: - class ActionProxy; - class WrapColumnFinder; + class ActionProxy; + class WrapColumnFinder; - mutable ContentsChatItemPrivate *_data; - ContentsChatItemPrivate *privateData() const; + mutable ContentsChatItemPrivate *_data; + ContentsChatItemPrivate *privateData() const; - Clickable clickableAt(const QPointF &pos) const; + Clickable clickableAt(const QPointF &pos) const; - void endHoverMode(); - void showWebPreview(const Clickable &click); - void clearWebPreview(); + void endHoverMode(); + void showWebPreview(const Clickable &click); + void clearWebPreview(); - qreal setGeometryByWidth(qreal w); + qreal setGeometryByWidth(qreal w); - QFontMetricsF *_fontMetrics; + QFontMetricsF *_fontMetrics; - // we need a receiver for Action signals - static ActionProxy _actionProxy; + // we need a receiver for Action signals + static ActionProxy _actionProxy; - friend class ChatLine; - friend struct ContentsChatItemPrivate; + friend class ChatLine; + friend struct ContentsChatItemPrivate; }; + struct ContentsChatItemPrivate { - ContentsChatItem *contentsItem; - ClickableList clickables; - Clickable currentClickable; - Clickable activeClickable; + ContentsChatItem *contentsItem; + ClickableList clickables; + Clickable currentClickable; + Clickable activeClickable; - ContentsChatItemPrivate(const ClickableList &c, ContentsChatItem *parent) : contentsItem(parent), clickables(c) {} + ContentsChatItemPrivate(const ClickableList &c, ContentsChatItem *parent) : contentsItem(parent), clickables(c) {} }; -class ContentsChatItem::WrapColumnFinder { +class ContentsChatItem::WrapColumnFinder +{ public: - WrapColumnFinder(const ChatItem *parent); - ~WrapColumnFinder(); + WrapColumnFinder(const ChatItem *parent); + ~WrapColumnFinder(); - qint16 nextWrapColumn(qreal width); + qint16 nextWrapColumn(qreal width); private: - const ChatItem *item; - QTextLayout layout; - QTextLine line; - ChatLineModel::WrapList wrapList; - qint16 wordidx; - qint16 lineCount; - qreal choppedTrailing; + const ChatItem *item; + QTextLayout layout; + QTextLine line; + ChatLineModel::WrapList wrapList; + qint16 wordidx; + qint16 lineCount; + qreal choppedTrailing; }; + //! Acts as a proxy for Action signals targetted at a ContentsChatItem /** Since a ChatItem is not a QObject, hence cannot receive signals, we use a static ActionProxy * as a receiver instead. This avoids having to handle ChatItem actions (e.g. context menu entries) * outside the ChatItem. */ -class ContentsChatItem::ActionProxy : public QObject { - Q_OBJECT +class ContentsChatItem::ActionProxy : public QObject +{ + Q_OBJECT public slots: - inline void copyLinkToClipboard() { item()->copyLinkToClipboard(); } + inline void copyLinkToClipboard() { item()->copyLinkToClipboard(); } private: - /// Returns the ContentsChatItem that should receive the action event. - /** For efficiency reasons, values are not checked for validity. You gotta make sure that you set the data() member - * in the Action correctly. - * @return The ChatItem from which the sending Action originated - */ - inline ContentsChatItem *item() const { - return static_cast(qobject_cast(sender())->data().value()); - } + /// Returns the ContentsChatItem that should receive the action event. + /** For efficiency reasons, values are not checked for validity. You gotta make sure that you set the data() member + * in the Action correctly. + * @return The ChatItem from which the sending Action originated + */ + inline ContentsChatItem *item() const + { + return static_cast(qobject_cast(sender())->data().value()); + } }; + /*************************************************************************************************/ // Inlines diff --git a/src/qtui/chatline.cpp b/src/qtui/chatline.cpp index 50616e8c..6956d2ad 100644 --- a/src/qtui/chatline.cpp +++ b/src/qtui/chatline.cpp @@ -37,11 +37,11 @@ #include "qtuistyle.h" ChatLine::ChatLine(int row, QAbstractItemModel *model, - const qreal &width, - const qreal ×tampWidth, const qreal &senderWidth, const qreal &contentsWidth, - const QPointF &senderPos, const QPointF &contentsPos, - QGraphicsItem *parent) - : QGraphicsItem(parent), + const qreal &width, + const qreal ×tampWidth, const qreal &senderWidth, const qreal &contentsWidth, + const QPointF &senderPos, const QPointF &contentsPos, + QGraphicsItem *parent) + : QGraphicsItem(parent), _row(row), // needs to be set before the items _model(model), _contentsItem(contentsPos, contentsWidth, this), @@ -53,208 +53,248 @@ ChatLine::ChatLine(int row, QAbstractItemModel *model, _mouseGrabberItem(0), _hoverItem(0) { - Q_ASSERT(model); - QModelIndex index = model->index(row, ChatLineModel::ContentsColumn); - setZValue(0); - setAcceptHoverEvents(true); - setHighlighted(index.data(MessageModel::FlagsRole).toInt() & Message::Highlight); + Q_ASSERT(model); + QModelIndex index = model->index(row, ChatLineModel::ContentsColumn); + setZValue(0); + setAcceptHoverEvents(true); + setHighlighted(index.data(MessageModel::FlagsRole).toInt() & Message::Highlight); } -ChatLine::~ChatLine() { - if(chatView()) - chatView()->setHasCache(this, false); + +ChatLine::~ChatLine() +{ + if (chatView()) + chatView()->setHasCache(this, false); } -ChatItem *ChatLine::item(ChatLineModel::ColumnType column) { - switch(column) { + +ChatItem *ChatLine::item(ChatLineModel::ColumnType column) +{ + switch (column) { case ChatLineModel::TimestampColumn: - return &_timestampItem; + return &_timestampItem; case ChatLineModel::SenderColumn: - return &_senderItem; + return &_senderItem; case ChatLineModel::ContentsColumn: - return &_contentsItem; - default: - return 0; - } + return &_contentsItem; + default: + return 0; + } } -ChatItem *ChatLine::itemAt(const QPointF &pos) { - if(_contentsItem.boundingRect().contains(pos)) - return &_contentsItem; - if(_senderItem.boundingRect().contains(pos)) - return &_senderItem; - if(_timestampItem.boundingRect().contains(pos)) - return &_timestampItem; - return 0; + +ChatItem *ChatLine::itemAt(const QPointF &pos) +{ + if (_contentsItem.boundingRect().contains(pos)) + return &_contentsItem; + if (_senderItem.boundingRect().contains(pos)) + return &_senderItem; + if (_timestampItem.boundingRect().contains(pos)) + return &_timestampItem; + return 0; } -void ChatLine::clearCache() { - _timestampItem.clearCache(); - _senderItem.clearCache(); - _contentsItem.clearCache(); + +void ChatLine::clearCache() +{ + _timestampItem.clearCache(); + _senderItem.clearCache(); + _contentsItem.clearCache(); } -void ChatLine::setMouseGrabberItem(ChatItem *item) { - _mouseGrabberItem = item; + +void ChatLine::setMouseGrabberItem(ChatItem *item) +{ + _mouseGrabberItem = item; } -bool ChatLine::sceneEvent(QEvent *event) { - if(event->type() == QEvent::GrabMouse) { - // get mouse cursor pos relative to us - ChatView *view = chatScene()->chatView(); - QPointF linePos = mapFromScene(view->mapToScene(view->mapFromGlobal(QCursor::pos()))); - setMouseGrabberItem(itemAt(linePos)); - } else if(event->type() == QEvent::UngrabMouse) { - setMouseGrabberItem(0); - } - return QGraphicsItem::sceneEvent(event); + +bool ChatLine::sceneEvent(QEvent *event) +{ + if (event->type() == QEvent::GrabMouse) { + // get mouse cursor pos relative to us + ChatView *view = chatScene()->chatView(); + QPointF linePos = mapFromScene(view->mapToScene(view->mapFromGlobal(QCursor::pos()))); + setMouseGrabberItem(itemAt(linePos)); + } + else if (event->type() == QEvent::UngrabMouse) { + setMouseGrabberItem(0); + } + return QGraphicsItem::sceneEvent(event); } -void ChatLine::setFirstColumn(const qreal ×tampWidth, const qreal &senderWidth, const QPointF &senderPos) { - _timestampItem.setGeometry(timestampWidth, _height); - _senderItem.setGeometry(senderWidth, _height); - _senderItem.setPos(senderPos); + +void ChatLine::setFirstColumn(const qreal ×tampWidth, const qreal &senderWidth, const QPointF &senderPos) +{ + _timestampItem.setGeometry(timestampWidth, _height); + _senderItem.setGeometry(senderWidth, _height); + _senderItem.setPos(senderPos); } -void ChatLine::setSecondColumn(const qreal &senderWidth, const qreal &contentsWidth, const QPointF &contentsPos, qreal &linePos) { - // linepos is the *bottom* position for the line - qreal height = _contentsItem.setGeometryByWidth(contentsWidth); - linePos -= height; - bool needGeometryChange = (height != _height); - _timestampItem.setHeight(height); - _senderItem.setGeometry(senderWidth, height); - _contentsItem.setPos(contentsPos); +void ChatLine::setSecondColumn(const qreal &senderWidth, const qreal &contentsWidth, const QPointF &contentsPos, qreal &linePos) +{ + // linepos is the *bottom* position for the line + qreal height = _contentsItem.setGeometryByWidth(contentsWidth); + linePos -= height; + bool needGeometryChange = (height != _height); - if(needGeometryChange) - prepareGeometryChange(); + _timestampItem.setHeight(height); + _senderItem.setGeometry(senderWidth, height); + _contentsItem.setPos(contentsPos); - _height = height; + if (needGeometryChange) + prepareGeometryChange(); - setPos(0, linePos); + _height = height; + + setPos(0, linePos); } -void ChatLine::setGeometryByWidth(const qreal &width, const qreal &contentsWidth, qreal &linePos) { - // linepos is the *bottom* position for the line - qreal height = _contentsItem.setGeometryByWidth(contentsWidth); - linePos -= height; - bool needGeometryChange = (height != _height || width != _width); - if(height != _height) { - _timestampItem.setHeight(height); - _senderItem.setHeight(height); - } +void ChatLine::setGeometryByWidth(const qreal &width, const qreal &contentsWidth, qreal &linePos) +{ + // linepos is the *bottom* position for the line + qreal height = _contentsItem.setGeometryByWidth(contentsWidth); + linePos -= height; + bool needGeometryChange = (height != _height || width != _width); + + if (height != _height) { + _timestampItem.setHeight(height); + _senderItem.setHeight(height); + } - if(needGeometryChange) { - prepareGeometryChange(); - _height = height; - _width = width; - } + if (needGeometryChange) { + prepareGeometryChange(); + _height = height; + _width = width; + } - setPos(0, linePos); // set pos is _very_ cheap if nothing changes. + setPos(0, linePos); // set pos is _very_ cheap if nothing changes. } -void ChatLine::setSelected(bool selected, ChatLineModel::ColumnType minColumn) { - if(selected) { - quint8 sel = (_selection & Highlighted) | Selected | minColumn; - if(sel != _selection) { - _selection = sel; - for(int i = 0; i < minColumn; i++) - item((ChatLineModel::ColumnType)i)->clearSelection(); - for(int i = minColumn; i <= ChatLineModel::ContentsColumn; i++) - item((ChatLineModel::ColumnType)i)->setFullSelection(); - update(); + +void ChatLine::setSelected(bool selected, ChatLineModel::ColumnType minColumn) +{ + if (selected) { + quint8 sel = (_selection & Highlighted) | Selected | minColumn; + if (sel != _selection) { + _selection = sel; + for (int i = 0; i < minColumn; i++) + item((ChatLineModel::ColumnType)i)->clearSelection(); + for (int i = minColumn; i <= ChatLineModel::ContentsColumn; i++) + item((ChatLineModel::ColumnType)i)->setFullSelection(); + update(); + } } - } else { - quint8 sel = _selection & Highlighted; - if(sel != _selection) { - _selection = sel; - for(int i = 0; i <= ChatLineModel::ContentsColumn; i++) - item((ChatLineModel::ColumnType)i)->clearSelection(); - update(); + else { + quint8 sel = _selection & Highlighted; + if (sel != _selection) { + _selection = sel; + for (int i = 0; i <= ChatLineModel::ContentsColumn; i++) + item((ChatLineModel::ColumnType)i)->clearSelection(); + update(); + } } - } } -void ChatLine::setHighlighted(bool highlighted) { - if(highlighted) _selection |= Highlighted; - else _selection &= ~Highlighted; - update(); + +void ChatLine::setHighlighted(bool highlighted) +{ + if (highlighted) _selection |= Highlighted; + else _selection &= ~Highlighted; + update(); } -void ChatLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { - Q_UNUSED(option); - Q_UNUSED(widget); - - const QAbstractItemModel *model_ = model(); - QModelIndex myIdx = model_->index(row(), 0); - Message::Type type = (Message::Type)myIdx.data(MessageModel::TypeRole).toInt(); - UiStyle::MessageLabel label = (UiStyle::MessageLabel)myIdx.data(ChatLineModel::MsgLabelRole).toInt(); - - QTextCharFormat msgFmt = QtUi::style()->format(UiStyle::formatType(type), label); - if(msgFmt.hasProperty(QTextFormat::BackgroundBrush)) { - painter->fillRect(boundingRect(), msgFmt.background()); - } - - if(_selection & Selected) { - QTextCharFormat selFmt = QtUi::style()->format(UiStyle::formatType(type), label | UiStyle::Selected); - if(selFmt.hasProperty(QTextFormat::BackgroundBrush)) { - qreal left = item((ChatLineModel::ColumnType)(_selection & ItemMask))->pos().x(); - QRectF selectRect(left, 0, width() - left, height()); - painter->fillRect(selectRect, selFmt.background()); + +void ChatLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(option); + Q_UNUSED(widget); + + const QAbstractItemModel *model_ = model(); + QModelIndex myIdx = model_->index(row(), 0); + Message::Type type = (Message::Type)myIdx.data(MessageModel::TypeRole).toInt(); + UiStyle::MessageLabel label = (UiStyle::MessageLabel)myIdx.data(ChatLineModel::MsgLabelRole).toInt(); + + QTextCharFormat msgFmt = QtUi::style()->format(UiStyle::formatType(type), label); + if (msgFmt.hasProperty(QTextFormat::BackgroundBrush)) { + painter->fillRect(boundingRect(), msgFmt.background()); + } + + if (_selection & Selected) { + QTextCharFormat selFmt = QtUi::style()->format(UiStyle::formatType(type), label | UiStyle::Selected); + if (selFmt.hasProperty(QTextFormat::BackgroundBrush)) { + qreal left = item((ChatLineModel::ColumnType)(_selection & ItemMask))->pos().x(); + QRectF selectRect(left, 0, width() - left, height()); + painter->fillRect(selectRect, selFmt.background()); + } } - } - // draw chatitems - // the items draw themselves at the correct position - timestampItem()->paint(painter, option, widget); - senderItem()->paint(painter, option, widget); - contentsItem()->paint(painter, option, widget); + // draw chatitems + // the items draw themselves at the correct position + timestampItem()->paint(painter, option, widget); + senderItem()->paint(painter, option, widget); + contentsItem()->paint(painter, option, widget); } + // We need to dispatch all mouse-related events to the appropriate (mouse grabbing) ChatItem -ChatItem *ChatLine::mouseEventTargetItem(const QPointF &pos) { - if(mouseGrabberItem()) - return mouseGrabberItem(); - return itemAt(pos); +ChatItem *ChatLine::mouseEventTargetItem(const QPointF &pos) +{ + if (mouseGrabberItem()) + return mouseGrabberItem(); + return itemAt(pos); } -void ChatLine::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { - ChatItem *item = mouseEventTargetItem(event->pos()); - if(item) - item->mouseMoveEvent(event); + +void ChatLine::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + ChatItem *item = mouseEventTargetItem(event->pos()); + if (item) + item->mouseMoveEvent(event); } -void ChatLine::mousePressEvent(QGraphicsSceneMouseEvent *event) { - ChatItem *item = mouseEventTargetItem(event->pos()); - if(item) - item->mousePressEvent(event); + +void ChatLine::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + ChatItem *item = mouseEventTargetItem(event->pos()); + if (item) + item->mousePressEvent(event); } -void ChatLine::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { - ChatItem *item = mouseEventTargetItem(event->pos()); - if(item) - item->mouseReleaseEvent(event); + +void ChatLine::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + ChatItem *item = mouseEventTargetItem(event->pos()); + if (item) + item->mouseReleaseEvent(event); } -void ChatLine::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { - ChatItem *item = mouseEventTargetItem(event->pos()); - if(item && !_hoverItem) { - _hoverItem = item; - item->hoverEnterEvent(event); - } + +void ChatLine::hoverEnterEvent(QGraphicsSceneHoverEvent *event) +{ + ChatItem *item = mouseEventTargetItem(event->pos()); + if (item && !_hoverItem) { + _hoverItem = item; + item->hoverEnterEvent(event); + } } -void ChatLine::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { - if(_hoverItem) { - _hoverItem->hoverLeaveEvent(event); - _hoverItem = 0; - } + +void ChatLine::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) +{ + if (_hoverItem) { + _hoverItem->hoverLeaveEvent(event); + _hoverItem = 0; + } } -void ChatLine::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { - ChatItem *item = mouseEventTargetItem(event->pos()); - if(item) - item->hoverMoveEvent(event); + +void ChatLine::hoverMoveEvent(QGraphicsSceneHoverEvent *event) +{ + ChatItem *item = mouseEventTargetItem(event->pos()); + if (item) + item->hoverMoveEvent(event); } diff --git a/src/qtui/chatline.h b/src/qtui/chatline.h index 06be6f68..a3fef26a 100644 --- a/src/qtui/chatline.h +++ b/src/qtui/chatline.h @@ -27,90 +27,91 @@ #include "chatitem.h" #include "chatscene.h" -class ChatLine : public QGraphicsItem { +class ChatLine : public QGraphicsItem +{ public: - ChatLine(int row, QAbstractItemModel *model, - const qreal &width, - const qreal ×tampWidth, const qreal &senderWidth, const qreal &contentsWidth, - const QPointF &senderPos, const QPointF &contentsPos, - QGraphicsItem *parent = 0); + ChatLine(int row, QAbstractItemModel *model, + const qreal &width, + const qreal ×tampWidth, const qreal &senderWidth, const qreal &contentsWidth, + const QPointF &senderPos, const QPointF &contentsPos, + QGraphicsItem *parent = 0); - virtual ~ChatLine(); + virtual ~ChatLine(); - virtual inline QRectF boundingRect () const { return QRectF(0, 0, _width, _height); } + virtual inline QRectF boundingRect() const { return QRectF(0, 0, _width, _height); } - inline QModelIndex index() const { return model()->index(row(), 0); } - inline MsgId msgId() const { return index().data(MessageModel::MsgIdRole).value(); } - inline Message::Type msgType() const { return (Message::Type)index().data(MessageModel::TypeRole).toInt(); } + inline QModelIndex index() const { return model()->index(row(), 0); } + inline MsgId msgId() const { return index().data(MessageModel::MsgIdRole).value(); } + inline Message::Type msgType() const { return (Message::Type)index().data(MessageModel::TypeRole).toInt(); } - inline int row() const { return _row; } - inline void setRow(int row) { _row = row; } + inline int row() const { return _row; } + inline void setRow(int row) { _row = row; } - inline const QAbstractItemModel *model() const { return _model; } - inline ChatScene *chatScene() const { return qobject_cast(scene()); } - inline ChatView *chatView() const { return chatScene() ? chatScene()->chatView() : 0; } + inline const QAbstractItemModel *model() const { return _model; } + inline ChatScene *chatScene() const { return qobject_cast(scene()); } + inline ChatView *chatView() const { return chatScene() ? chatScene()->chatView() : 0; } - inline qreal width() const { return _width; } - inline qreal height() const { return _height; } + inline qreal width() const { return _width; } + inline qreal height() const { return _height; } - ChatItem *item(ChatLineModel::ColumnType); - ChatItem *itemAt(const QPointF &pos); - inline ChatItem *timestampItem() { return &_timestampItem; } - inline ChatItem *senderItem() { return &_senderItem; } - inline ContentsChatItem *contentsItem() { return &_contentsItem; } + ChatItem *item(ChatLineModel::ColumnType); + ChatItem *itemAt(const QPointF &pos); + inline ChatItem *timestampItem() { return &_timestampItem; } + inline ChatItem *senderItem() { return &_senderItem; } + inline ContentsChatItem *contentsItem() { return &_contentsItem; } - virtual void paint (QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - enum { Type = ChatScene::ChatLineType }; - virtual inline int type() const { return Type; } + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); + enum { Type = ChatScene::ChatLineType }; + virtual inline int type() const { return Type; } - // pos is relative to the parent ChatLine - void setFirstColumn(const qreal ×tampWidth, const qreal &senderWidth, const QPointF &senderPos); - // setSecondColumn and setGeometryByWidth both also relocate the chatline. - // the _bottom_ position is passed via linePos. linePos is updated to the top of the chatLine. - void setSecondColumn(const qreal &senderWidth, const qreal &contentsWidth, const QPointF &contentsPos, qreal &linePos); - void setGeometryByWidth(const qreal &width, const qreal &contentsWidth, qreal &linePos); + // pos is relative to the parent ChatLine + void setFirstColumn(const qreal ×tampWidth, const qreal &senderWidth, const QPointF &senderPos); + // setSecondColumn and setGeometryByWidth both also relocate the chatline. + // the _bottom_ position is passed via linePos. linePos is updated to the top of the chatLine. + void setSecondColumn(const qreal &senderWidth, const qreal &contentsWidth, const QPointF &contentsPos, qreal &linePos); + void setGeometryByWidth(const qreal &width, const qreal &contentsWidth, qreal &linePos); - void setSelected(bool selected, ChatLineModel::ColumnType minColumn = ChatLineModel::ContentsColumn); - void setHighlighted(bool highlighted); + void setSelected(bool selected, ChatLineModel::ColumnType minColumn = ChatLineModel::ContentsColumn); + void setHighlighted(bool highlighted); - void clearCache(); + void clearCache(); protected: - virtual bool sceneEvent(QEvent *event); + virtual bool sceneEvent(QEvent *event); - // These need to be relayed to the appropriate ChatItem - virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); - virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); - virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); - virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event); - virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); - virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event); + // These need to be relayed to the appropriate ChatItem + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event); + virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); + virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event); - ChatItem *mouseEventTargetItem(const QPointF &pos); + ChatItem *mouseEventTargetItem(const QPointF &pos); - inline ChatItem *mouseGrabberItem() const { return _mouseGrabberItem; } - void setMouseGrabberItem(ChatItem *item); + inline ChatItem *mouseGrabberItem() const { return _mouseGrabberItem; } + void setMouseGrabberItem(ChatItem *item); private: - int _row; - QAbstractItemModel *_model; - ContentsChatItem _contentsItem; - SenderChatItem _senderItem; - TimestampChatItem _timestampItem; - qreal _width, _height; - - enum { ItemMask = 0x3f, - Selected = 0x40, - Highlighted = 0x80 - }; - // _selection[1..0] ... Min Selected Column (See MessageModel::ColumnType) - // _selection[5..2] ... reserved for new column types - // _selection[6] ...... Selected - // _selection[7] ...... Highlighted - quint8 _selection; // save space, so we put both the col and the flags into one byte - - ChatItem *_mouseGrabberItem; - ChatItem *_hoverItem; + int _row; + QAbstractItemModel *_model; + ContentsChatItem _contentsItem; + SenderChatItem _senderItem; + TimestampChatItem _timestampItem; + qreal _width, _height; + + enum { ItemMask = 0x3f, + Selected = 0x40, + Highlighted = 0x80 }; + // _selection[1..0] ... Min Selected Column (See MessageModel::ColumnType) + // _selection[5..2] ... reserved for new column types + // _selection[6] ...... Selected + // _selection[7] ...... Highlighted + quint8 _selection; // save space, so we put both the col and the flags into one byte + + ChatItem *_mouseGrabberItem; + ChatItem *_hoverItem; }; + #endif diff --git a/src/qtui/chatlinemodel.cpp b/src/qtui/chatlinemodel.cpp index 720f9b42..9b5fb46e 100644 --- a/src/qtui/chatlinemodel.cpp +++ b/src/qtui/chatlinemodel.cpp @@ -23,54 +23,64 @@ #include "qtuistyle.h" ChatLineModel::ChatLineModel(QObject *parent) - : MessageModel(parent) + : MessageModel(parent) { - qRegisterMetaType("ChatLineModel::WrapList"); - qRegisterMetaTypeStreamOperators("ChatLineModel::WrapList"); + qRegisterMetaType("ChatLineModel::WrapList"); + qRegisterMetaTypeStreamOperators("ChatLineModel::WrapList"); - connect(QtUi::style(), SIGNAL(changed()), SLOT(styleChanged())); + connect(QtUi::style(), SIGNAL(changed()), SLOT(styleChanged())); } + // MessageModelItem *ChatLineModel::createMessageModelItem(const Message &msg) { // return new ChatLineModelItem(msg); // } -void ChatLineModel::insertMessages__(int pos, const QList &messages) { - for(int i = 0; i < messages.count(); i++) { - _messageList.insert(pos, ChatLineModelItem(messages[i])); - pos++; - } +void ChatLineModel::insertMessages__(int pos, const QList &messages) +{ + for (int i = 0; i < messages.count(); i++) { + _messageList.insert(pos, ChatLineModelItem(messages[i])); + pos++; + } } -Message ChatLineModel::takeMessageAt(int i) { - Message msg = _messageList[i].message(); - _messageList.removeAt(i); - return msg; + +Message ChatLineModel::takeMessageAt(int i) +{ + Message msg = _messageList[i].message(); + _messageList.removeAt(i); + return msg; } -void ChatLineModel::styleChanged() { - foreach(ChatLineModelItem item, _messageList) { - item.invalidateWrapList(); - } - emit dataChanged(index(0,0), index(rowCount()-1, columnCount()-1)); + +void ChatLineModel::styleChanged() +{ + foreach(ChatLineModelItem item, _messageList) { + item.invalidateWrapList(); + } + emit dataChanged(index(0, 0), index(rowCount()-1, columnCount()-1)); } -QDataStream &operator<<(QDataStream &out, const ChatLineModel::WrapList wplist) { - out << wplist.count(); - ChatLineModel::WrapList::const_iterator it = wplist.begin(); - while(it != wplist.end()) { - out << (*it).start << (*it).width << (*it).trailing; - ++it; - } - return out; + +QDataStream &operator<<(QDataStream &out, const ChatLineModel::WrapList wplist) +{ + out << wplist.count(); + ChatLineModel::WrapList::const_iterator it = wplist.begin(); + while (it != wplist.end()) { + out << (*it).start << (*it).width << (*it).trailing; + ++it; + } + return out; } -QDataStream &operator>>(QDataStream &in, ChatLineModel::WrapList &wplist) { - quint16 cnt; - in >> cnt; - wplist.resize(cnt); - for(quint16 i = 0; i < cnt; i++) { - in >> wplist[i].start >> wplist[i].width >> wplist[i].trailing; - } - return in; + +QDataStream &operator>>(QDataStream &in, ChatLineModel::WrapList &wplist) +{ + quint16 cnt; + in >> cnt; + wplist.resize(cnt); + for (quint16 i = 0; i < cnt; i++) { + in >> wplist[i].start >> wplist[i].width >> wplist[i].trailing; + } + return in; } diff --git a/src/qtui/chatlinemodel.h b/src/qtui/chatlinemodel.h index 407821f8..aecc9bc3 100644 --- a/src/qtui/chatlinemodel.h +++ b/src/qtui/chatlinemodel.h @@ -26,48 +26,49 @@ #include #include "chatlinemodelitem.h" -class ChatLineModel : public MessageModel { - Q_OBJECT +class ChatLineModel : public MessageModel +{ + Q_OBJECT public: - enum ChatLineRole { - WrapListRole = MessageModel::UserRole, - MsgLabelRole, - SelectedBackgroundRole - }; + enum ChatLineRole { + WrapListRole = MessageModel::UserRole, + MsgLabelRole, + SelectedBackgroundRole + }; - ChatLineModel(QObject *parent = 0); + ChatLineModel(QObject *parent = 0); - typedef ChatLineModelItem::Word Word; - typedef ChatLineModelItem::WrapList WrapList; - virtual inline const MessageModelItem *messageItemAt(int i) const { return &_messageList[i]; } + typedef ChatLineModelItem::Word Word; + typedef ChatLineModelItem::WrapList WrapList; + virtual inline const MessageModelItem *messageItemAt(int i) const { return &_messageList[i]; } protected: // virtual MessageModelItem *createMessageModelItem(const Message &); - virtual inline int messageCount() const { return _messageList.count(); } - virtual inline bool messagesIsEmpty() const { return _messageList.isEmpty(); } - virtual inline MessageModelItem *messageItemAt(int i) { return &_messageList[i]; } - virtual inline const MessageModelItem *firstMessageItem() const { return &_messageList.first(); } - virtual inline MessageModelItem *firstMessageItem() { return &_messageList.first(); } - virtual inline const MessageModelItem *lastMessageItem() const { return &_messageList.last(); } - virtual inline MessageModelItem *lastMessageItem() { return &_messageList.last(); } - virtual inline void insertMessage__(int pos, const Message &msg) { _messageList.insert(pos, ChatLineModelItem(msg)); } - virtual void insertMessages__(int pos, const QList &); - virtual inline void removeMessageAt(int i) { _messageList.removeAt(i); } - virtual inline void removeAllMessages() { _messageList.clear(); } - virtual Message takeMessageAt(int i); + virtual inline int messageCount() const { return _messageList.count(); } + virtual inline bool messagesIsEmpty() const { return _messageList.isEmpty(); } + virtual inline MessageModelItem *messageItemAt(int i) { return &_messageList[i]; } + virtual inline const MessageModelItem *firstMessageItem() const { return &_messageList.first(); } + virtual inline MessageModelItem *firstMessageItem() { return &_messageList.first(); } + virtual inline const MessageModelItem *lastMessageItem() const { return &_messageList.last(); } + virtual inline MessageModelItem *lastMessageItem() { return &_messageList.last(); } + virtual inline void insertMessage__(int pos, const Message &msg) { _messageList.insert(pos, ChatLineModelItem(msg)); } + virtual void insertMessages__(int pos, const QList &); + virtual inline void removeMessageAt(int i) { _messageList.removeAt(i); } + virtual inline void removeAllMessages() { _messageList.clear(); } + virtual Message takeMessageAt(int i); protected slots: - virtual void styleChanged(); + virtual void styleChanged(); private: - QList _messageList; + QList _messageList; }; + QDataStream &operator<<(QDataStream &out, const ChatLineModel::WrapList); QDataStream &operator>>(QDataStream &in, ChatLineModel::WrapList &); Q_DECLARE_METATYPE(ChatLineModel::WrapList) #endif - diff --git a/src/qtui/chatlinemodelitem.cpp b/src/qtui/chatlinemodelitem.cpp index 16b57e2e..9936500e 100644 --- a/src/qtui/chatlinemodelitem.cpp +++ b/src/qtui/chatlinemodelitem.cpp @@ -29,15 +29,14 @@ // This Struct is taken from Harfbuzz. We use it only to calc it's size. // we use a shared memory region so we do not have to malloc a buffer area for every line typedef struct { - /*HB_LineBreakType*/ unsigned lineBreakType :2; - /*HB_Bool*/ unsigned whiteSpace :1; /* A unicode whitespace character, except NBSP, ZWNBSP */ - /*HB_Bool*/ unsigned charStop :1; /* Valid cursor position (for left/right arrow) */ - /*HB_Bool*/ unsigned wordBoundary :1; - /*HB_Bool*/ unsigned sentenceBoundary :1; - unsigned unused :2; + /*HB_LineBreakType*/ unsigned lineBreakType : 2; + /*HB_Bool*/ unsigned whiteSpace : 1; /* A unicode whitespace character, except NBSP, ZWNBSP */ + /*HB_Bool*/ unsigned charStop : 1; /* Valid cursor position (for left/right arrow) */ + /*HB_Bool*/ unsigned wordBoundary : 1; + /*HB_Bool*/ unsigned sentenceBoundary : 1; + unsigned unused : 2; } HB_CharAttributes_Dummy; - unsigned char *ChatLineModelItem::TextBoundaryFinderBuffer = (unsigned char *)malloc(512 * sizeof(HB_CharAttributes_Dummy)); int ChatLineModelItem::TextBoundaryFinderBufferSize = 512 * (sizeof(HB_CharAttributes_Dummy) / sizeof(unsigned char)); @@ -45,190 +44,204 @@ int ChatLineModelItem::TextBoundaryFinderBufferSize = 512 * (sizeof(HB_CharAttri // the actual ChatLineModelItem // **************************************** ChatLineModelItem::ChatLineModelItem(const Message &msg) - : MessageModelItem(), + : MessageModelItem(), _styledMsg(msg) { - if(!msg.sender().contains('!')) - _styledMsg.setFlags(msg.flags() |= Message::ServerMsg); + if (!msg.sender().contains('!')) + _styledMsg.setFlags(msg.flags() |= Message::ServerMsg); } -bool ChatLineModelItem::setData(int column, const QVariant &value, int role) { - switch(role) { + +bool ChatLineModelItem::setData(int column, const QVariant &value, int role) +{ + switch (role) { case MessageModel::FlagsRole: - _styledMsg.setFlags((Message::Flags)value.toUInt()); - return true; + _styledMsg.setFlags((Message::Flags)value.toUInt()); + return true; default: - return MessageModelItem::setData(column, value, role); - } + return MessageModelItem::setData(column, value, role); + } } -QVariant ChatLineModelItem::data(int column, int role) const { - if(role == ChatLineModel::MsgLabelRole) - return messageLabel(); - - QVariant variant; - MessageModel::ColumnType col = (MessageModel::ColumnType)column; - switch(col) { - case ChatLineModel::TimestampColumn: - variant = timestampData(role); - break; - case ChatLineModel::SenderColumn: - variant = senderData(role); - break; - case ChatLineModel::ContentsColumn: - variant = contentsData(role); - break; - default: - break; - } - if(!variant.isValid()) - return MessageModelItem::data(column, role); - return variant; -} -QVariant ChatLineModelItem::timestampData(int role) const { - switch(role) { - case ChatLineModel::DisplayRole: - return _styledMsg.decoratedTimestamp(); - case ChatLineModel::EditRole: - return _styledMsg.timestamp(); - case ChatLineModel::BackgroundRole: - return backgroundBrush(UiStyle::Timestamp); - case ChatLineModel::SelectedBackgroundRole: - return backgroundBrush(UiStyle::Timestamp, true); - case ChatLineModel::FormatRole: - return QVariant::fromValue(UiStyle::FormatList() - << qMakePair((quint16)0, (quint32)UiStyle::formatType(_styledMsg.type()) | UiStyle::Timestamp)); - } - return QVariant(); +QVariant ChatLineModelItem::data(int column, int role) const +{ + if (role == ChatLineModel::MsgLabelRole) + return messageLabel(); + + QVariant variant; + MessageModel::ColumnType col = (MessageModel::ColumnType)column; + switch (col) { + case ChatLineModel::TimestampColumn: + variant = timestampData(role); + break; + case ChatLineModel::SenderColumn: + variant = senderData(role); + break; + case ChatLineModel::ContentsColumn: + variant = contentsData(role); + break; + default: + break; + } + if (!variant.isValid()) + return MessageModelItem::data(column, role); + return variant; } -QVariant ChatLineModelItem::senderData(int role) const { - switch(role) { - case ChatLineModel::DisplayRole: - return _styledMsg.decoratedSender(); - case ChatLineModel::EditRole: - return _styledMsg.plainSender(); - case ChatLineModel::BackgroundRole: - return backgroundBrush(UiStyle::Sender); - case ChatLineModel::SelectedBackgroundRole: - return backgroundBrush(UiStyle::Sender, true); - case ChatLineModel::FormatRole: - return QVariant::fromValue(UiStyle::FormatList() - << qMakePair((quint16)0, (quint32)UiStyle::formatType(_styledMsg.type()) | UiStyle::Sender)); - } - return QVariant(); + +QVariant ChatLineModelItem::timestampData(int role) const +{ + switch (role) { + case ChatLineModel::DisplayRole: + return _styledMsg.decoratedTimestamp(); + case ChatLineModel::EditRole: + return _styledMsg.timestamp(); + case ChatLineModel::BackgroundRole: + return backgroundBrush(UiStyle::Timestamp); + case ChatLineModel::SelectedBackgroundRole: + return backgroundBrush(UiStyle::Timestamp, true); + case ChatLineModel::FormatRole: + return QVariant::fromValue(UiStyle::FormatList() + << qMakePair((quint16)0, (quint32) UiStyle::formatType(_styledMsg.type()) | UiStyle::Timestamp)); + } + return QVariant(); } -QVariant ChatLineModelItem::contentsData(int role) const { - switch(role) { - case ChatLineModel::DisplayRole: - case ChatLineModel::EditRole: - return _styledMsg.plainContents(); - case ChatLineModel::BackgroundRole: - return backgroundBrush(UiStyle::Contents); - case ChatLineModel::SelectedBackgroundRole: - return backgroundBrush(UiStyle::Contents, true); - case ChatLineModel::FormatRole: - return QVariant::fromValue(_styledMsg.contentsFormatList()); - case ChatLineModel::WrapListRole: - if(_wrapList.isEmpty()) - computeWrapList(); - return QVariant::fromValue(_wrapList); - } - return QVariant(); + +QVariant ChatLineModelItem::senderData(int role) const +{ + switch (role) { + case ChatLineModel::DisplayRole: + return _styledMsg.decoratedSender(); + case ChatLineModel::EditRole: + return _styledMsg.plainSender(); + case ChatLineModel::BackgroundRole: + return backgroundBrush(UiStyle::Sender); + case ChatLineModel::SelectedBackgroundRole: + return backgroundBrush(UiStyle::Sender, true); + case ChatLineModel::FormatRole: + return QVariant::fromValue(UiStyle::FormatList() + << qMakePair((quint16)0, (quint32) UiStyle::formatType(_styledMsg.type()) | UiStyle::Sender)); + } + return QVariant(); } -quint32 ChatLineModelItem::messageLabel() const { - quint32 label = _styledMsg.senderHash() << 16; - if(_styledMsg.flags() & Message::Self) - label |= UiStyle::OwnMsg; - if(_styledMsg.flags() & Message::Highlight) - label |= UiStyle::Highlight; - return label; + +QVariant ChatLineModelItem::contentsData(int role) const +{ + switch (role) { + case ChatLineModel::DisplayRole: + case ChatLineModel::EditRole: + return _styledMsg.plainContents(); + case ChatLineModel::BackgroundRole: + return backgroundBrush(UiStyle::Contents); + case ChatLineModel::SelectedBackgroundRole: + return backgroundBrush(UiStyle::Contents, true); + case ChatLineModel::FormatRole: + return QVariant::fromValue(_styledMsg.contentsFormatList()); + case ChatLineModel::WrapListRole: + if (_wrapList.isEmpty()) + computeWrapList(); + return QVariant::fromValue(_wrapList); + } + return QVariant(); } -QVariant ChatLineModelItem::backgroundBrush(UiStyle::FormatType subelement, bool selected) const { - QTextCharFormat fmt = QtUi::style()->format(UiStyle::formatType(_styledMsg.type()) | subelement, messageLabel() | (selected ? UiStyle::Selected : 0)); - if(fmt.hasProperty(QTextFormat::BackgroundBrush)) - return QVariant::fromValue(fmt.background()); - return QVariant(); + +quint32 ChatLineModelItem::messageLabel() const +{ + quint32 label = _styledMsg.senderHash() << 16; + if (_styledMsg.flags() & Message::Self) + label |= UiStyle::OwnMsg; + if (_styledMsg.flags() & Message::Highlight) + label |= UiStyle::Highlight; + return label; } -void ChatLineModelItem::computeWrapList() const { - QString text = _styledMsg.plainContents(); - int length = text.length(); - if(!length) - return; - - QList wplist; // use a temp list which we'll later copy into a QVector for efficiency - QTextBoundaryFinder finder(QTextBoundaryFinder::Line, _styledMsg.plainContents().unicode(), length, - TextBoundaryFinderBuffer, TextBoundaryFinderBufferSize); - - int idx; - int oldidx = 0; - ChatLineModel::Word word; - word.start = 0; - qreal wordstartx = 0; - - QTextLayout layout(_styledMsg.plainContents()); - QTextOption option; - option.setWrapMode(QTextOption::NoWrap); - layout.setTextOption(option); - - layout.setAdditionalFormats(QtUi::style()->toTextLayoutList(_styledMsg.contentsFormatList(), length, messageLabel())); - layout.beginLayout(); - QTextLine line = layout.createLine(); - line.setNumColumns(length); - layout.endLayout(); - - while((idx = finder.toNextBoundary()) >= 0 && idx <= length) { - - // QTextBoundaryFinder has inconsistent behavior in Qt version up to and including 4.6.3 (at least). - // It doesn't point to the position we should break, but to the character before that. - // Unfortunately Qt decided to fix this by changing the behavior of QTBF, so now we have to add a version - // check. At the time of this writing, I'm still trying to get this reverted upstream... - // - // cf. https://bugs.webkit.org/show_bug.cgi?id=31076 and Qt commit e6ac173 - static int needWorkaround = -1; - if(needWorkaround < 0) { - needWorkaround = 0; - QStringList versions = QString(qVersion()).split('.'); - if(versions.count() == 3 && versions.at(0).toInt() == 4) { - if(versions.at(1).toInt() <= 6 && versions.at(2).toInt() <= 3) - needWorkaround = 1; - } - } - if(needWorkaround == 1) { - if(idx < length) - idx++; - } - if(idx == oldidx) - continue; +QVariant ChatLineModelItem::backgroundBrush(UiStyle::FormatType subelement, bool selected) const +{ + QTextCharFormat fmt = QtUi::style()->format(UiStyle::formatType(_styledMsg.type()) | subelement, messageLabel() | (selected ? UiStyle::Selected : 0)); + if (fmt.hasProperty(QTextFormat::BackgroundBrush)) + return QVariant::fromValue(fmt.background()); + return QVariant(); +} - word.start = oldidx; - int wordend = idx; - for(; wordend > word.start; wordend--) { - if(!text.at(wordend-1).isSpace()) - break; + +void ChatLineModelItem::computeWrapList() const +{ + QString text = _styledMsg.plainContents(); + int length = text.length(); + if (!length) + return; + + QList wplist; // use a temp list which we'll later copy into a QVector for efficiency + QTextBoundaryFinder finder(QTextBoundaryFinder::Line, _styledMsg.plainContents().unicode(), length, + TextBoundaryFinderBuffer, TextBoundaryFinderBufferSize); + + int idx; + int oldidx = 0; + ChatLineModel::Word word; + word.start = 0; + qreal wordstartx = 0; + + QTextLayout layout(_styledMsg.plainContents()); + QTextOption option; + option.setWrapMode(QTextOption::NoWrap); + layout.setTextOption(option); + + layout.setAdditionalFormats(QtUi::style()->toTextLayoutList(_styledMsg.contentsFormatList(), length, messageLabel())); + layout.beginLayout(); + QTextLine line = layout.createLine(); + line.setNumColumns(length); + layout.endLayout(); + + while ((idx = finder.toNextBoundary()) >= 0 && idx <= length) { + // QTextBoundaryFinder has inconsistent behavior in Qt version up to and including 4.6.3 (at least). + // It doesn't point to the position we should break, but to the character before that. + // Unfortunately Qt decided to fix this by changing the behavior of QTBF, so now we have to add a version + // check. At the time of this writing, I'm still trying to get this reverted upstream... + // + // cf. https://bugs.webkit.org/show_bug.cgi?id=31076 and Qt commit e6ac173 + static int needWorkaround = -1; + if (needWorkaround < 0) { + needWorkaround = 0; + QStringList versions = QString(qVersion()).split('.'); + if (versions.count() == 3 && versions.at(0).toInt() == 4) { + if (versions.at(1).toInt() <= 6 && versions.at(2).toInt() <= 3) + needWorkaround = 1; + } + } + if (needWorkaround == 1) { + if (idx < length) + idx++; + } + + if (idx == oldidx) + continue; + + word.start = oldidx; + int wordend = idx; + for (; wordend > word.start; wordend--) { + if (!text.at(wordend-1).isSpace()) + break; + } + + qreal wordendx = line.cursorToX(wordend); + qreal trailingendx = line.cursorToX(idx); + word.endX = wordendx; + word.width = wordendx - wordstartx; + word.trailing = trailingendx - wordendx; + wordstartx = trailingendx; + wplist.append(word); + + oldidx = idx; } - qreal wordendx = line.cursorToX(wordend); - qreal trailingendx = line.cursorToX(idx); - word.endX = wordendx; - word.width = wordendx - wordstartx; - word.trailing = trailingendx - wordendx; - wordstartx = trailingendx; - wplist.append(word); - - oldidx = idx; - } - - // A QVector needs less space than a QList - _wrapList.resize(wplist.count()); - for(int i = 0; i < wplist.count(); i++) { - _wrapList[i] = wplist.at(i); - } + // A QVector needs less space than a QList + _wrapList.resize(wplist.count()); + for (int i = 0; i < wplist.count(); i++) { + _wrapList[i] = wplist.at(i); + } } - diff --git a/src/qtui/chatlinemodelitem.h b/src/qtui/chatlinemodelitem.h index 8f90d22b..25939b24 100644 --- a/src/qtui/chatlinemodelitem.h +++ b/src/qtui/chatlinemodelitem.h @@ -25,47 +25,49 @@ #include "uistyle.h" -class ChatLineModelItem : public MessageModelItem { +class ChatLineModelItem : public MessageModelItem +{ public: - ChatLineModelItem(const Message &); + ChatLineModelItem(const Message &); - virtual QVariant data(int column, int role) const; - virtual bool setData(int column, const QVariant &value, int role); + virtual QVariant data(int column, int role) const; + virtual bool setData(int column, const QVariant &value, int role); - virtual inline const Message &message() const { return _styledMsg; } - virtual inline const QDateTime ×tamp() const { return _styledMsg.timestamp(); } - virtual inline const MsgId &msgId() const { return _styledMsg.msgId(); } - virtual inline const BufferId &bufferId() const { return _styledMsg.bufferId(); } - virtual inline void setBufferId(BufferId bufferId) { _styledMsg.setBufferId(bufferId); } - virtual inline Message::Type msgType() const { return _styledMsg.type(); } - virtual inline Message::Flags msgFlags() const { return _styledMsg.flags(); } + virtual inline const Message &message() const { return _styledMsg; } + virtual inline const QDateTime ×tamp() const { return _styledMsg.timestamp(); } + virtual inline const MsgId &msgId() const { return _styledMsg.msgId(); } + virtual inline const BufferId &bufferId() const { return _styledMsg.bufferId(); } + virtual inline void setBufferId(BufferId bufferId) { _styledMsg.setBufferId(bufferId); } + virtual inline Message::Type msgType() const { return _styledMsg.type(); } + virtual inline Message::Flags msgFlags() const { return _styledMsg.flags(); } - virtual inline void invalidateWrapList() { _wrapList.clear(); } + virtual inline void invalidateWrapList() { _wrapList.clear(); } - /// Used to store information about words to be used for wrapping - struct Word { - quint16 start; - qreal endX; - qreal width; - qreal trailing; - }; - typedef QVector WrapList; + /// Used to store information about words to be used for wrapping + struct Word { + quint16 start; + qreal endX; + qreal width; + qreal trailing; + }; + typedef QVector WrapList; private: - QVariant timestampData(int role) const; - QVariant senderData(int role) const; - QVariant contentsData(int role) const; + QVariant timestampData(int role) const; + QVariant senderData(int role) const; + QVariant contentsData(int role) const; - QVariant backgroundBrush(UiStyle::FormatType subelement, bool selected = false) const; - quint32 messageLabel() const; + QVariant backgroundBrush(UiStyle::FormatType subelement, bool selected = false) const; + quint32 messageLabel() const; - void computeWrapList() const; + void computeWrapList() const; - mutable WrapList _wrapList; - UiStyle::StyledMessage _styledMsg; + mutable WrapList _wrapList; + UiStyle::StyledMessage _styledMsg; - static unsigned char *TextBoundaryFinderBuffer; - static int TextBoundaryFinderBufferSize; + static unsigned char *TextBoundaryFinderBuffer; + static int TextBoundaryFinderBufferSize; }; + #endif diff --git a/src/qtui/chatmonitorfilter.cpp b/src/qtui/chatmonitorfilter.cpp index b46dd29c..676ea850 100644 --- a/src/qtui/chatmonitorfilter.cpp +++ b/src/qtui/chatmonitorfilter.cpp @@ -27,143 +27,163 @@ #include "clientignorelistmanager.h" ChatMonitorFilter::ChatMonitorFilter(MessageModel *model, QObject *parent) - : MessageFilter(model, parent) + : MessageFilter(model, parent) { - ChatViewSettings viewSettings(idString()); - _showFields = viewSettings.value("ShowFields", AllFields).toInt(); - _showOwnMessages = viewSettings.value("ShowOwnMsgs", true).toBool(); - viewSettings.notify("ShowFields", this, SLOT(showFieldsSettingChanged(const QVariant &))); - viewSettings.notify("ShowOwnMsgs", this, SLOT(showOwnMessagesSettingChanged(const QVariant &))); - - // ChatMonitorSettingsPage - QString showHighlightsSettingsId = "ShowHighlights"; - QString operationModeSettingsId = "OperationMode"; - QString buffersSettingsId = "Buffers"; - - _showHighlights = viewSettings.value(showHighlightsSettingsId, false).toBool(); - _operationMode = viewSettings.value(operationModeSettingsId, 0).toInt(); - // read configured list of buffers to monitor/ignore - foreach(QVariant v, viewSettings.value(buffersSettingsId, QVariant()).toList()) + ChatViewSettings viewSettings(idString()); + _showFields = viewSettings.value("ShowFields", AllFields).toInt(); + _showOwnMessages = viewSettings.value("ShowOwnMsgs", true).toBool(); + viewSettings.notify("ShowFields", this, SLOT(showFieldsSettingChanged(const QVariant &))); + viewSettings.notify("ShowOwnMsgs", this, SLOT(showOwnMessagesSettingChanged(const QVariant &))); + + // ChatMonitorSettingsPage + QString showHighlightsSettingsId = "ShowHighlights"; + QString operationModeSettingsId = "OperationMode"; + QString buffersSettingsId = "Buffers"; + + _showHighlights = viewSettings.value(showHighlightsSettingsId, false).toBool(); + _operationMode = viewSettings.value(operationModeSettingsId, 0).toInt(); + // read configured list of buffers to monitor/ignore + foreach(QVariant v, viewSettings.value(buffersSettingsId, QVariant()).toList()) _bufferIds << v.value(); - viewSettings.notify(showHighlightsSettingsId, this, SLOT(showHighlightsSettingChanged(const QVariant &))); - viewSettings.notify(operationModeSettingsId, this, SLOT(operationModeSettingChanged(const QVariant &))); - viewSettings.notify(buffersSettingsId, this, SLOT(buffersSettingChanged(const QVariant &))); + viewSettings.notify(showHighlightsSettingsId, this, SLOT(showHighlightsSettingChanged(const QVariant &))); + viewSettings.notify(operationModeSettingsId, this, SLOT(operationModeSettingChanged(const QVariant &))); + viewSettings.notify(buffersSettingsId, this, SLOT(buffersSettingChanged(const QVariant &))); } -bool ChatMonitorFilter::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { - Q_UNUSED(sourceParent) - - QModelIndex source_index = sourceModel()->index(sourceRow, 0); - - Message::Flags flags = (Message::Flags)source_index.data(MessageModel::FlagsRole).toInt(); - if(flags & Message::Backlog || (!_showOwnMessages && flags & Message::Self)) - return false; - - Message::Type type = (Message::Type)source_index.data(MessageModel::TypeRole).toInt(); - if(!(type & (Message::Plain | Message::Notice | Message::Action))) - return false; - - BufferId bufferId = source_index.data(MessageModel::BufferIdRole).value(); - - // ChatMonitorSettingsPage - if(_operationMode == ChatViewSettings::OptOut - && !(_showHighlights && flags & Message::Highlight) - && _bufferIds.contains(bufferId)) - return false; - if(_operationMode == ChatViewSettings::OptIn - && !(_showHighlights && flags & Message::Highlight) - && !_bufferIds.contains(bufferId)) - return false; - - // ignorelist handling - // only match if message is not flagged as server msg - if(!(flags & Message::ServerMsg) && Client::ignoreListManager() - && Client::ignoreListManager()->match(source_index.data(MessageModel::MessageRole).value(), Client::networkModel()->networkName(bufferId))) - return false; - return true; + +bool ChatMonitorFilter::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +{ + Q_UNUSED(sourceParent) + + QModelIndex source_index = sourceModel()->index(sourceRow, 0); + + Message::Flags flags = (Message::Flags)source_index.data(MessageModel::FlagsRole).toInt(); + if (flags & Message::Backlog || (!_showOwnMessages && flags & Message::Self)) + return false; + + Message::Type type = (Message::Type)source_index.data(MessageModel::TypeRole).toInt(); + if (!(type & (Message::Plain | Message::Notice | Message::Action))) + return false; + + BufferId bufferId = source_index.data(MessageModel::BufferIdRole).value(); + + // ChatMonitorSettingsPage + if (_operationMode == ChatViewSettings::OptOut + && !(_showHighlights && flags & Message::Highlight) + && _bufferIds.contains(bufferId)) + return false; + if (_operationMode == ChatViewSettings::OptIn + && !(_showHighlights && flags & Message::Highlight) + && !_bufferIds.contains(bufferId)) + return false; + + // ignorelist handling + // only match if message is not flagged as server msg + if (!(flags & Message::ServerMsg) && Client::ignoreListManager() + && Client::ignoreListManager()->match(source_index.data(MessageModel::MessageRole).value(), Client::networkModel()->networkName(bufferId))) + return false; + return true; } + // override this to inject display of network and channel -QVariant ChatMonitorFilter::data(const QModelIndex &index, int role) const { - if(index.column() != ChatLineModel::SenderColumn || role != ChatLineModel::DisplayRole) - return MessageFilter::data(index, role); - - BufferId bufid = data(index, ChatLineModel::BufferIdRole).value(); - if(!bufid.isValid()) { - qDebug() << "ChatMonitorFilter::data(): chatline belongs to an invalid buffer!"; - return QVariant(); - } - - QModelIndex source_index = mapToSource(index); - - QStringList fields; - if(_showFields & NetworkField) { - fields << Client::networkModel()->networkName(bufid); - } - if(_showFields & BufferField) { - fields << Client::networkModel()->bufferName(bufid); - } - - Message::Type messageType = (Message::Type)source_index.data(MessageModel::TypeRole).toInt(); - if(messageType & (Message::Plain | Message::Notice)) { - QString sender = MessageFilter::data(index, ChatLineModel::EditRole).toString(); - fields << sender; - } - return QString("<%1>").arg(fields.join(":")); +QVariant ChatMonitorFilter::data(const QModelIndex &index, int role) const +{ + if (index.column() != ChatLineModel::SenderColumn || role != ChatLineModel::DisplayRole) + return MessageFilter::data(index, role); + + BufferId bufid = data(index, ChatLineModel::BufferIdRole).value(); + if (!bufid.isValid()) { + qDebug() << "ChatMonitorFilter::data(): chatline belongs to an invalid buffer!"; + return QVariant(); + } + + QModelIndex source_index = mapToSource(index); + + QStringList fields; + if (_showFields & NetworkField) { + fields << Client::networkModel()->networkName(bufid); + } + if (_showFields & BufferField) { + fields << Client::networkModel()->bufferName(bufid); + } + + Message::Type messageType = (Message::Type)source_index.data(MessageModel::TypeRole).toInt(); + if (messageType & (Message::Plain | Message::Notice)) { + QString sender = MessageFilter::data(index, ChatLineModel::EditRole).toString(); + fields << sender; + } + return QString("<%1>").arg(fields.join(":")); } -void ChatMonitorFilter::addShowField(int field) { - if(_showFields & field) - return; - ChatViewSettings(idString()).setValue("ShowFields", _showFields | field); +void ChatMonitorFilter::addShowField(int field) +{ + if (_showFields & field) + return; + + ChatViewSettings(idString()).setValue("ShowFields", _showFields | field); } -void ChatMonitorFilter::removeShowField(int field) { - if(!(_showFields & field)) - return; - ChatViewSettings(idString()).setValue("ShowFields", _showFields ^ field); +void ChatMonitorFilter::removeShowField(int field) +{ + if (!(_showFields & field)) + return; + + ChatViewSettings(idString()).setValue("ShowFields", _showFields ^ field); } -void ChatMonitorFilter::setShowOwnMessages(bool show) { - if(_showOwnMessages == show) - return; - ChatViewSettings(idString()).setValue("ShowOwnMsgs", show); +void ChatMonitorFilter::setShowOwnMessages(bool show) +{ + if (_showOwnMessages == show) + return; + + ChatViewSettings(idString()).setValue("ShowOwnMsgs", show); } -void ChatMonitorFilter::showFieldsSettingChanged(const QVariant &newValue) { - int newFields = newValue.toInt(); - if(_showFields == newFields) - return; - _showFields = newFields; +void ChatMonitorFilter::showFieldsSettingChanged(const QVariant &newValue) +{ + int newFields = newValue.toInt(); + if (_showFields == newFields) + return; - int rows = rowCount(); - if(rows == 0) - return; + _showFields = newFields; - emit dataChanged(index(0, ChatLineModel::SenderColumn), index(rows - 1, ChatLineModel::SenderColumn)); + int rows = rowCount(); + if (rows == 0) + return; + + emit dataChanged(index(0, ChatLineModel::SenderColumn), index(rows - 1, ChatLineModel::SenderColumn)); } -void ChatMonitorFilter::showOwnMessagesSettingChanged(const QVariant &newValue) { - _showOwnMessages = newValue.toBool(); + +void ChatMonitorFilter::showOwnMessagesSettingChanged(const QVariant &newValue) +{ + _showOwnMessages = newValue.toBool(); } -void ChatMonitorFilter::showHighlightsSettingChanged(const QVariant &newValue) { - _showHighlights = newValue.toBool(); + +void ChatMonitorFilter::showHighlightsSettingChanged(const QVariant &newValue) +{ + _showHighlights = newValue.toBool(); } -void ChatMonitorFilter::operationModeSettingChanged(const QVariant &newValue) { - _operationMode = newValue.toInt(); + +void ChatMonitorFilter::operationModeSettingChanged(const QVariant &newValue) +{ + _operationMode = newValue.toInt(); } -void ChatMonitorFilter::buffersSettingChanged(const QVariant &newValue) { - _bufferIds.clear(); - foreach (QVariant v, newValue.toList()) { - _bufferIds << v.value(); - } - invalidateFilter(); + +void ChatMonitorFilter::buffersSettingChanged(const QVariant &newValue) +{ + _bufferIds.clear(); + foreach(QVariant v, newValue.toList()) { + _bufferIds << v.value(); + } + invalidateFilter(); } diff --git a/src/qtui/chatmonitorfilter.h b/src/qtui/chatmonitorfilter.h index d7f4c4bd..6b3adcd1 100644 --- a/src/qtui/chatmonitorfilter.h +++ b/src/qtui/chatmonitorfilter.h @@ -25,45 +25,47 @@ #include "messagefilter.h" -class ChatMonitorFilter : public MessageFilter { - Q_OBJECT +class ChatMonitorFilter : public MessageFilter +{ + Q_OBJECT public: - enum SenderFields { - NoField = 0x00, - NetworkField = 0x01, - BufferField = 0x02, - SenderField = 0x04, - AllFields = 0xff - }; + enum SenderFields { + NoField = 0x00, + NetworkField = 0x01, + BufferField = 0x02, + SenderField = 0x04, + AllFields = 0xff + }; - ChatMonitorFilter(MessageModel *model, QObject *parent = 0); + ChatMonitorFilter(MessageModel *model, QObject *parent = 0); - virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; - virtual QString idString() const { return "ChatMonitor"; } - virtual QVariant data(const QModelIndex &index, int role) const; + virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; + virtual QString idString() const { return "ChatMonitor"; } + virtual QVariant data(const QModelIndex &index, int role) const; - int showFields() const { return _showFields; } - bool showOwnMessages() const { return _showOwnMessages; } + int showFields() const { return _showFields; } + bool showOwnMessages() const { return _showOwnMessages; } public slots: - void addShowField(int field); - void removeShowField(int field); - void setShowOwnMessages(bool show); + void addShowField(int field); + void removeShowField(int field); + void setShowOwnMessages(bool show); private slots: - void showFieldsSettingChanged(const QVariant &newValue); - void showOwnMessagesSettingChanged(const QVariant &newValue); - void showHighlightsSettingChanged(const QVariant &newValue); - void operationModeSettingChanged(const QVariant &newValue); - void buffersSettingChanged(const QVariant &newValue); + void showFieldsSettingChanged(const QVariant &newValue); + void showOwnMessagesSettingChanged(const QVariant &newValue); + void showHighlightsSettingChanged(const QVariant &newValue); + void operationModeSettingChanged(const QVariant &newValue); + void buffersSettingChanged(const QVariant &newValue); private: - int _showFields; - bool _showOwnMessages; - QList _bufferIds; - bool _showHighlights; - int _operationMode; + int _showFields; + bool _showOwnMessages; + QList _bufferIds; + bool _showHighlights; + int _operationMode; }; + #endif diff --git a/src/qtui/chatmonitorview.cpp b/src/qtui/chatmonitorview.cpp index 4316486d..5bd1844a 100644 --- a/src/qtui/chatmonitorview.cpp +++ b/src/qtui/chatmonitorview.cpp @@ -39,77 +39,87 @@ #include "clientignorelistmanager.h" ChatMonitorView::ChatMonitorView(ChatMonitorFilter *filter, QWidget *parent) - : ChatView(filter, parent), + : ChatView(filter, parent), _filter(filter) { - scene()->setSenderCutoffMode(ChatScene::CutoffLeft); - connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), this, SLOT(coreConnectionStateChanged(bool))); + scene()->setSenderCutoffMode(ChatScene::CutoffLeft); + connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), this, SLOT(coreConnectionStateChanged(bool))); } -void ChatMonitorView::addActionsToMenu(QMenu *menu, const QPointF &pos) { - ChatView::addActionsToMenu(menu, pos); - menu->addSeparator(); - QAction *showOwnNicksAction = menu->addAction(tr("Show Own Messages"), _filter, SLOT(setShowOwnMessages(bool))); - showOwnNicksAction->setCheckable(true); - showOwnNicksAction->setChecked(_filter->showOwnMessages()); - if(scene()->columnByScenePos(pos) == ChatLineModel::SenderColumn) { +void ChatMonitorView::addActionsToMenu(QMenu *menu, const QPointF &pos) +{ + ChatView::addActionsToMenu(menu, pos); menu->addSeparator(); + QAction *showOwnNicksAction = menu->addAction(tr("Show Own Messages"), _filter, SLOT(setShowOwnMessages(bool))); + showOwnNicksAction->setCheckable(true); + showOwnNicksAction->setChecked(_filter->showOwnMessages()); + + if (scene()->columnByScenePos(pos) == ChatLineModel::SenderColumn) { + menu->addSeparator(); - QAction *showNetworkAction = menu->addAction(tr("Show Network Name"), this, SLOT(showFieldsChanged(bool))); - showNetworkAction->setCheckable(true); - showNetworkAction->setChecked(_filter->showFields() & ChatMonitorFilter::NetworkField); - showNetworkAction->setData(ChatMonitorFilter::NetworkField); + QAction *showNetworkAction = menu->addAction(tr("Show Network Name"), this, SLOT(showFieldsChanged(bool))); + showNetworkAction->setCheckable(true); + showNetworkAction->setChecked(_filter->showFields() & ChatMonitorFilter::NetworkField); + showNetworkAction->setData(ChatMonitorFilter::NetworkField); - QAction *showBufferAction = menu->addAction(tr("Show Buffer Name"), this, SLOT(showFieldsChanged(bool))); - showBufferAction->setCheckable(true); - showBufferAction->setChecked(_filter->showFields() & ChatMonitorFilter::BufferField); - showBufferAction->setData(ChatMonitorFilter::BufferField); - } + QAction *showBufferAction = menu->addAction(tr("Show Buffer Name"), this, SLOT(showFieldsChanged(bool))); + showBufferAction->setCheckable(true); + showBufferAction->setChecked(_filter->showFields() & ChatMonitorFilter::BufferField); + showBufferAction->setData(ChatMonitorFilter::BufferField); + } - menu->addSeparator(); - menu->addAction(SmallIcon("configure"), tr("Configure..."), this, SLOT(showSettingsPage())); + menu->addSeparator(); + menu->addAction(SmallIcon("configure"), tr("Configure..."), this, SLOT(showSettingsPage())); } -void ChatMonitorView::mouseDoubleClickEvent(QMouseEvent *event) { - if(scene()->columnByScenePos(event->pos()) != ChatLineModel::SenderColumn) { - ChatView::mouseDoubleClickEvent(event); - return; - } - ChatItem *chatItem = scene()->chatItemAt(mapToScene(event->pos())); - if(!chatItem) { - event->ignore(); - return; - } +void ChatMonitorView::mouseDoubleClickEvent(QMouseEvent *event) +{ + if (scene()->columnByScenePos(event->pos()) != ChatLineModel::SenderColumn) { + ChatView::mouseDoubleClickEvent(event); + return; + } + + ChatItem *chatItem = scene()->chatItemAt(mapToScene(event->pos())); + if (!chatItem) { + event->ignore(); + return; + } + + event->accept(); + BufferId bufferId = chatItem->data(MessageModel::BufferIdRole).value(); + if (!bufferId.isValid()) + return; + + Client::bufferModel()->switchToBuffer(bufferId); +} - event->accept(); - BufferId bufferId = chatItem->data(MessageModel::BufferIdRole).value(); - if(!bufferId.isValid()) - return; - Client::bufferModel()->switchToBuffer(bufferId); +void ChatMonitorView::showFieldsChanged(bool checked) +{ + QAction *showAction = qobject_cast(sender()); + if (!showAction) + return; + + if (checked) + _filter->addShowField(showAction->data().toInt()); + else + _filter->removeShowField(showAction->data().toInt()); } -void ChatMonitorView::showFieldsChanged(bool checked) { - QAction *showAction = qobject_cast(sender()); - if(!showAction) - return; - if(checked) - _filter->addShowField(showAction->data().toInt()); - else - _filter->removeShowField(showAction->data().toInt()); +void ChatMonitorView::showSettingsPage() +{ + SettingsPageDlg dlg(new ChatMonitorSettingsPage(), this); + dlg.exec(); } -void ChatMonitorView::showSettingsPage() { - SettingsPageDlg dlg(new ChatMonitorSettingsPage(), this); - dlg.exec(); -} // connect only after client is synced to core since ChatMonitorView is created before // the ignoreListManager -void ChatMonitorView::coreConnectionStateChanged(bool connected) { - if(connected) - connect(Client::ignoreListManager(), SIGNAL(ignoreListChanged()), _filter, SLOT(invalidateFilter())); +void ChatMonitorView::coreConnectionStateChanged(bool connected) +{ + if (connected) + connect(Client::ignoreListManager(), SIGNAL(ignoreListChanged()), _filter, SLOT(invalidateFilter())); } diff --git a/src/qtui/chatmonitorview.h b/src/qtui/chatmonitorview.h index 74a90c19..73e5045f 100644 --- a/src/qtui/chatmonitorview.h +++ b/src/qtui/chatmonitorview.h @@ -25,26 +25,28 @@ class ChatMonitorFilter; -class ChatMonitorView : public ChatView { - Q_OBJECT +class ChatMonitorView : public ChatView +{ + Q_OBJECT public: - ChatMonitorView(ChatMonitorFilter *filter, QWidget *parent); + ChatMonitorView(ChatMonitorFilter *filter, QWidget *parent); protected: - virtual void addActionsToMenu(QMenu *menu, const QPointF &pos); - virtual void mouseDoubleClickEvent(QMouseEvent *event); + virtual void addActionsToMenu(QMenu *menu, const QPointF &pos); + virtual void mouseDoubleClickEvent(QMouseEvent *event); private slots: - void showFieldsChanged(bool checked); - void showSettingsPage(); - virtual void coreConnectionStateChanged(bool connected); + void showFieldsChanged(bool checked); + void showSettingsPage(); + virtual void coreConnectionStateChanged(bool connected); protected: - inline ChatMonitorFilter *filter() const { return _filter; } + inline ChatMonitorFilter *filter() const { return _filter; } private: - ChatMonitorFilter *_filter; + ChatMonitorFilter *_filter; }; + #endif //CHATMONITORVIEW_H diff --git a/src/qtui/chatscene.cpp b/src/qtui/chatscene.cpp index 797b0083..42529f33 100644 --- a/src/qtui/chatscene.cpp +++ b/src/qtui/chatscene.cpp @@ -58,7 +58,7 @@ const qreal minContentsWidth = 200; ChatScene::ChatScene(QAbstractItemModel *model, const QString &idString, qreal width, ChatView *parent) - : QGraphicsScene(0, 0, width, 0, (QObject *)parent), + : QGraphicsScene(0, 0, width, 0, (QObject *)parent), _chatView(parent), _idString(idString), _model(model), @@ -78,216 +78,240 @@ ChatScene::ChatScene(QAbstractItemModel *model, const QString &idString, qreal w _clickHandled(true), _leftButtonPressed(false) { - MessageFilter *filter = qobject_cast(model); - if(filter && filter->isSingleBufferFilter()) { - _singleBufferId = filter->singleBufferId(); - } + MessageFilter *filter = qobject_cast(model); + if (filter && filter->isSingleBufferFilter()) { + _singleBufferId = filter->singleBufferId(); + } - addItem(_markerLine); - connect(this, SIGNAL(sceneRectChanged(const QRectF &)), _markerLine, SLOT(sceneRectChanged(const QRectF &))); + addItem(_markerLine); + connect(this, SIGNAL(sceneRectChanged(const QRectF &)), _markerLine, SLOT(sceneRectChanged(const QRectF &))); - ChatViewSettings defaultSettings; - int defaultFirstColHandlePos = defaultSettings.value("FirstColumnHandlePos", 80).toInt(); - int defaultSecondColHandlePos = defaultSettings.value("SecondColumnHandlePos", 200).toInt(); + ChatViewSettings defaultSettings; + int defaultFirstColHandlePos = defaultSettings.value("FirstColumnHandlePos", 80).toInt(); + int defaultSecondColHandlePos = defaultSettings.value("SecondColumnHandlePos", 200).toInt(); - ChatViewSettings viewSettings(this); - _firstColHandlePos = viewSettings.value("FirstColumnHandlePos", defaultFirstColHandlePos).toInt(); - _secondColHandlePos = viewSettings.value("SecondColumnHandlePos", defaultSecondColHandlePos).toInt(); + ChatViewSettings viewSettings(this); + _firstColHandlePos = viewSettings.value("FirstColumnHandlePos", defaultFirstColHandlePos).toInt(); + _secondColHandlePos = viewSettings.value("SecondColumnHandlePos", defaultSecondColHandlePos).toInt(); - _firstColHandle = new ColumnHandleItem(QtUi::style()->firstColumnSeparator()); - addItem(_firstColHandle); - _firstColHandle->setXPos(_firstColHandlePos); - connect(_firstColHandle, SIGNAL(positionChanged(qreal)), this, SLOT(firstHandlePositionChanged(qreal))); - connect(this, SIGNAL(sceneRectChanged(const QRectF &)), _firstColHandle, SLOT(sceneRectChanged(const QRectF &))); + _firstColHandle = new ColumnHandleItem(QtUi::style()->firstColumnSeparator()); + addItem(_firstColHandle); + _firstColHandle->setXPos(_firstColHandlePos); + connect(_firstColHandle, SIGNAL(positionChanged(qreal)), this, SLOT(firstHandlePositionChanged(qreal))); + connect(this, SIGNAL(sceneRectChanged(const QRectF &)), _firstColHandle, SLOT(sceneRectChanged(const QRectF &))); - _secondColHandle = new ColumnHandleItem(QtUi::style()->secondColumnSeparator()); - addItem(_secondColHandle); - _secondColHandle->setXPos(_secondColHandlePos); - connect(_secondColHandle, SIGNAL(positionChanged(qreal)), this, SLOT(secondHandlePositionChanged(qreal))); + _secondColHandle = new ColumnHandleItem(QtUi::style()->secondColumnSeparator()); + addItem(_secondColHandle); + _secondColHandle->setXPos(_secondColHandlePos); + connect(_secondColHandle, SIGNAL(positionChanged(qreal)), this, SLOT(secondHandlePositionChanged(qreal))); - connect(this, SIGNAL(sceneRectChanged(const QRectF &)), _secondColHandle, SLOT(sceneRectChanged(const QRectF &))); + connect(this, SIGNAL(sceneRectChanged(const QRectF &)), _secondColHandle, SLOT(sceneRectChanged(const QRectF &))); - setHandleXLimits(); + setHandleXLimits(); - if(model->rowCount() > 0) - rowsInserted(QModelIndex(), 0, model->rowCount() - 1); + if (model->rowCount() > 0) + rowsInserted(QModelIndex(), 0, model->rowCount() - 1); - connect(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)), - this, SLOT(rowsInserted(const QModelIndex &, int, int))); - connect(model, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)), - this, SLOT(rowsAboutToBeRemoved(const QModelIndex &, int, int))); - connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(rowsRemoved())); - connect(model, SIGNAL(dataChanged(QModelIndex, QModelIndex)), SLOT(dataChanged(QModelIndex, QModelIndex))); + connect(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)), + this, SLOT(rowsInserted(const QModelIndex &, int, int))); + connect(model, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)), + this, SLOT(rowsAboutToBeRemoved(const QModelIndex &, int, int))); + connect(model, SIGNAL(rowsRemoved(QModelIndex, int, int)), + this, SLOT(rowsRemoved())); + connect(model, SIGNAL(dataChanged(QModelIndex, QModelIndex)), SLOT(dataChanged(QModelIndex, QModelIndex))); #ifdef HAVE_WEBKIT - webPreview.timer.setSingleShot(true); - connect(&webPreview.timer, SIGNAL(timeout()), this, SLOT(webPreviewNextStep())); + webPreview.timer.setSingleShot(true); + connect(&webPreview.timer, SIGNAL(timeout()), this, SLOT(webPreviewNextStep())); #endif - _showWebPreview = defaultSettings.showWebPreview(); - defaultSettings.notify("ShowWebPreview", this, SLOT(showWebPreviewChanged())); + _showWebPreview = defaultSettings.showWebPreview(); + defaultSettings.notify("ShowWebPreview", this, SLOT(showWebPreviewChanged())); - _clickTimer.setInterval(QApplication::doubleClickInterval()); - _clickTimer.setSingleShot(true); - connect(&_clickTimer, SIGNAL(timeout()), SLOT(clickTimeout())); + _clickTimer.setInterval(QApplication::doubleClickInterval()); + _clickTimer.setSingleShot(true); + connect(&_clickTimer, SIGNAL(timeout()), SLOT(clickTimeout())); - setItemIndexMethod(QGraphicsScene::NoIndex); + setItemIndexMethod(QGraphicsScene::NoIndex); } -ChatScene::~ChatScene() { + +ChatScene::~ChatScene() +{ } -ChatView *ChatScene::chatView() const { - return _chatView; + +ChatView *ChatScene::chatView() const +{ + return _chatView; } -ColumnHandleItem *ChatScene::firstColumnHandle() const { - return _firstColHandle; + +ColumnHandleItem *ChatScene::firstColumnHandle() const +{ + return _firstColHandle; } -ColumnHandleItem *ChatScene::secondColumnHandle() const { - return _secondColHandle; + +ColumnHandleItem *ChatScene::secondColumnHandle() const +{ + return _secondColHandle; } -ChatLine *ChatScene::chatLine(MsgId msgId, bool matchExact, bool ignoreDayChange) const { - if(!_lines.count()) - return 0; - QList::ConstIterator start = _lines.begin(); - QList::ConstIterator end = _lines.end(); - QList::ConstIterator middle; - - int n = int(end - start); - int half; - - while(n > 0) { - half = n >> 1; - middle = start + half; - if((*middle)->msgId() < msgId) { - start = middle + 1; - n -= half + 1; - } else { - n = half; +ChatLine *ChatScene::chatLine(MsgId msgId, bool matchExact, bool ignoreDayChange) const +{ + if (!_lines.count()) + return 0; + + QList::ConstIterator start = _lines.begin(); + QList::ConstIterator end = _lines.end(); + QList::ConstIterator middle; + + int n = int(end - start); + int half; + + while (n > 0) { + half = n >> 1; + middle = start + half; + if ((*middle)->msgId() < msgId) { + start = middle + 1; + n -= half + 1; + } + else { + n = half; + } } - } - if(start != end && (*start)->msgId() == msgId && (ignoreDayChange? (*start)->msgType() != Message::DayChange : true)) - return *start; + if (start != end && (*start)->msgId() == msgId && (ignoreDayChange ? (*start)->msgType() != Message::DayChange : true)) + return *start; - if(matchExact) - return 0; + if (matchExact) + return 0; - if(start == _lines.begin()) // not (yet?) in our scene - return 0; + if (start == _lines.begin()) // not (yet?) in our scene + return 0; + + // if we didn't find the exact msgId, take the next-lower one (this makes sense for lastSeen) - // if we didn't find the exact msgId, take the next-lower one (this makes sense for lastSeen) + if (start == end) { // higher than last element + if (!ignoreDayChange) + return _lines.last(); - if(start == end) { // higher than last element - if(!ignoreDayChange) - return _lines.last(); + for (int i = _lines.count() -1; i >= 0; i--) { + if (_lines.at(i)->msgType() != Message::DayChange) + return _lines.at(i); + } + return 0; + } - for(int i = _lines.count() -1; i >= 0; i--) { - if(_lines.at(i)->msgType() != Message::DayChange) - return _lines.at(i); + // return the next-lower line + if (!ignoreDayChange) + return *(--start); + + do { + if ((*(--start))->msgType() != Message::DayChange) + return *start; } + while (start != _lines.begin()); return 0; - } +} - // return the next-lower line - if(!ignoreDayChange) - return *(--start); - do { - if((*(--start))->msgType() != Message::DayChange) - return *start; - } while(start != _lines.begin()); - return 0; +ChatItem *ChatScene::chatItemAt(const QPointF &scenePos) const +{ + foreach(QGraphicsItem *item, items(scenePos, Qt::IntersectsItemBoundingRect, Qt::AscendingOrder)) { + ChatLine *line = qgraphicsitem_cast(item); + if (line) + return line->itemAt(line->mapFromScene(scenePos)); + } + return 0; } -ChatItem *ChatScene::chatItemAt(const QPointF &scenePos) const { - foreach(QGraphicsItem *item, items(scenePos, Qt::IntersectsItemBoundingRect, Qt::AscendingOrder)) { - ChatLine *line = qgraphicsitem_cast(item); - if(line) - return line->itemAt(line->mapFromScene(scenePos)); - } - return 0; -} -bool ChatScene::containsBuffer(const BufferId &id) const { - MessageFilter *filter = qobject_cast(model()); - if(filter) - return filter->containsBuffer(id); - else - return false; +bool ChatScene::containsBuffer(const BufferId &id) const +{ + MessageFilter *filter = qobject_cast(model()); + if (filter) + return filter->containsBuffer(id); + else + return false; } -void ChatScene::setMarkerLineVisible(bool visible) { - _markerLineVisible = visible; - if(visible && _markerLineValid) - markerLine()->setVisible(true); - else - markerLine()->setVisible(false); + +void ChatScene::setMarkerLineVisible(bool visible) +{ + _markerLineVisible = visible; + if (visible && _markerLineValid) + markerLine()->setVisible(true); + else + markerLine()->setVisible(false); } -void ChatScene::setMarkerLine(MsgId msgId) { - if(!isSingleBufferScene()) - return; - if(!msgId.isValid()) - msgId = Client::markerLine(singleBufferId()); - - if(msgId.isValid()) { - ChatLine *line = chatLine(msgId, false, true); - if(line) { - markerLine()->setChatLine(line); - // if this was the last line, we won't see it because it's outside the sceneRect - // .. which is exactly what we want :) - markerLine()->setPos(line->pos() + QPointF(0, line->height())); - - // DayChange messages might have been hidden outside the scene rect, don't make the markerline visible then! - if(markerLine()->pos().y() >= sceneRect().y()) { - _markerLineValid = true; - if(_markerLineVisible) - markerLine()->setVisible(true); - if(_markerLineJumpPending) { - _markerLineJumpPending = false; - if(markerLine()->isVisible()) { - markerLine()->ensureVisible(QRectF(), 50, 50); - } - } +void ChatScene::setMarkerLine(MsgId msgId) +{ + if (!isSingleBufferScene()) return; - } + + if (!msgId.isValid()) + msgId = Client::markerLine(singleBufferId()); + + if (msgId.isValid()) { + ChatLine *line = chatLine(msgId, false, true); + if (line) { + markerLine()->setChatLine(line); + // if this was the last line, we won't see it because it's outside the sceneRect + // .. which is exactly what we want :) + markerLine()->setPos(line->pos() + QPointF(0, line->height())); + + // DayChange messages might have been hidden outside the scene rect, don't make the markerline visible then! + if (markerLine()->pos().y() >= sceneRect().y()) { + _markerLineValid = true; + if (_markerLineVisible) + markerLine()->setVisible(true); + if (_markerLineJumpPending) { + _markerLineJumpPending = false; + if (markerLine()->isVisible()) { + markerLine()->ensureVisible(QRectF(), 50, 50); + } + } + return; + } + } } - } - _markerLineValid = false; - markerLine()->setVisible(false); + _markerLineValid = false; + markerLine()->setVisible(false); } -void ChatScene::jumpToMarkerLine(bool requestBacklog) { - if(!isSingleBufferScene()) - return; - if(markerLine()->isVisible()) { - markerLine()->ensureVisible(QRectF(), 50, 50); - return; - } - if(!_markerLineValid && requestBacklog) { - MsgId msgId = Client::markerLine(singleBufferId()); - if(msgId.isValid()) { - _markerLineJumpPending = true; - Client::backlogManager()->requestBacklog(singleBufferId(), msgId, -1, -1, 0); - - // If we filtered out the lastSeenMsg (by changing filters after setting it), we'd never jump because the above request - // won't fetch any prior lines. Thus, trigger a dynamic backlog request just in case, so repeated - // jump tries will eventually cause enough backlog to be fetched. - // This is a bit hackish, but not wasteful, as jumping to the top of the ChatView would trigger a dynamic fetch anyway. - this->requestBacklog(); +void ChatScene::jumpToMarkerLine(bool requestBacklog) +{ + if (!isSingleBufferScene()) + return; + + if (markerLine()->isVisible()) { + markerLine()->ensureVisible(QRectF(), 50, 50); + return; + } + if (!_markerLineValid && requestBacklog) { + MsgId msgId = Client::markerLine(singleBufferId()); + if (msgId.isValid()) { + _markerLineJumpPending = true; + Client::backlogManager()->requestBacklog(singleBufferId(), msgId, -1, -1, 0); + + // If we filtered out the lastSeenMsg (by changing filters after setting it), we'd never jump because the above request + // won't fetch any prior lines. Thus, trigger a dynamic backlog request just in case, so repeated + // jump tries will eventually cause enough backlog to be fetched. + // This is a bit hackish, but not wasteful, as jumping to the top of the ChatView would trigger a dynamic fetch anyway. + this->requestBacklog(); + } } - } } -void ChatScene::rowsInserted(const QModelIndex &index, int start, int end) { - Q_UNUSED(index); + +void ChatScene::rowsInserted(const QModelIndex &index, int start, int end) +{ + Q_UNUSED(index); // QModelIndex sidx = model()->index(start, 2); // QModelIndex eidx = model()->index(end, 2); @@ -295,94 +319,96 @@ void ChatScene::rowsInserted(const QModelIndex &index, int start, int end) { // if(start > 0) { // QModelIndex ssidx = model()->index(start - 1, 2); // qDebug() << "Start--:" << start - 1 << ssidx.data(MessageModel::MsgIdRole).value() -// << ssidx.data(Qt::DisplayRole).toString(); +// << ssidx.data(Qt::DisplayRole).toString(); // } // qDebug() << "Start:" << start << sidx.data(MessageModel::MsgIdRole).value() -// << sidx.data(Qt::DisplayRole).toString(); +// << sidx.data(Qt::DisplayRole).toString(); // qDebug() << "End:" << end << eidx.data(MessageModel::MsgIdRole).value() -// << eidx.data(Qt::DisplayRole).toString(); +// << eidx.data(Qt::DisplayRole).toString(); // if(end + 1 < model()->rowCount()) { // QModelIndex eeidx = model()->index(end + 1, 2); // qDebug() << "End++:" << end + 1 << eeidx.data(MessageModel::MsgIdRole).value() -// << eeidx.data(Qt::DisplayRole).toString(); +// << eeidx.data(Qt::DisplayRole).toString(); // } - qreal h = 0; - qreal y = 0; - qreal width = _sceneRect.width(); - bool atBottom = (start == _lines.count()); - bool atTop = !atBottom && (start == 0); - - if(start < _lines.count()) { - y = _lines.value(start)->y(); - } else if(atBottom && !_lines.isEmpty()) { - y = _lines.last()->y() + _lines.last()->height(); - } - - qreal contentsWidth = width - secondColumnHandle()->sceneRight(); - qreal senderWidth = secondColumnHandle()->sceneLeft() - firstColumnHandle()->sceneRight(); - qreal timestampWidth = firstColumnHandle()->sceneLeft(); - QPointF contentsPos(secondColumnHandle()->sceneRight(), 0); - QPointF senderPos(firstColumnHandle()->sceneRight(), 0); - - if(atTop) { - for(int i = end; i >= start; i--) { - ChatLine *line = new ChatLine(i, model(), - width, - timestampWidth, senderWidth, contentsWidth, - senderPos, contentsPos); - h += line->height(); - line->setPos(0, y-h); - _lines.insert(start, line); - addItem(line); + qreal h = 0; + qreal y = 0; + qreal width = _sceneRect.width(); + bool atBottom = (start == _lines.count()); + bool atTop = !atBottom && (start == 0); + + if (start < _lines.count()) { + y = _lines.value(start)->y(); } - } else { - for(int i = start; i <= end; i++) { - ChatLine *line = new ChatLine(i, model(), - width, - timestampWidth, senderWidth, contentsWidth, - senderPos, contentsPos); - line->setPos(0, y+h); - h += line->height(); - _lines.insert(i, line); - addItem(line); + else if (atBottom && !_lines.isEmpty()) { + y = _lines.last()->y() + _lines.last()->height(); } - } - - // update existing items - for(int i = end+1; i < _lines.count(); i++) { - _lines[i]->setRow(i); - } - - // update selection - if(_selectionStart >= 0) { - int offset = end - start + 1; - int oldStart = _selectionStart; - if(_selectionStart >= start) - _selectionStart += offset; - if(_selectionEnd >= start) { - _selectionEnd += offset; - if(_selectionStart == oldStart) - for(int i = start; i < start + offset; i++) - _lines[i]->setSelected(true); + + qreal contentsWidth = width - secondColumnHandle()->sceneRight(); + qreal senderWidth = secondColumnHandle()->sceneLeft() - firstColumnHandle()->sceneRight(); + qreal timestampWidth = firstColumnHandle()->sceneLeft(); + QPointF contentsPos(secondColumnHandle()->sceneRight(), 0); + QPointF senderPos(firstColumnHandle()->sceneRight(), 0); + + if (atTop) { + for (int i = end; i >= start; i--) { + ChatLine *line = new ChatLine(i, model(), + width, + timestampWidth, senderWidth, contentsWidth, + senderPos, contentsPos); + h += line->height(); + line->setPos(0, y-h); + _lines.insert(start, line); + addItem(line); + } + } + else { + for (int i = start; i <= end; i++) { + ChatLine *line = new ChatLine(i, model(), + width, + timestampWidth, senderWidth, contentsWidth, + senderPos, contentsPos); + line->setPos(0, y+h); + h += line->height(); + _lines.insert(i, line); + addItem(line); + } + } + + // update existing items + for (int i = end+1; i < _lines.count(); i++) { + _lines[i]->setRow(i); } - if(_firstSelectionRow >= start) - _firstSelectionRow += offset; - } - - // neither pre- or append means we have to do dirty work: move items... - if(!(atTop || atBottom)) { - ChatLine *line = 0; - for(int i = 0; i <= end; i++) { - line = _lines.at(i); - line->setPos(0, line->pos().y() - h); - if(line == markerLine()->chatLine()) - markerLine()->setPos(line->pos() + QPointF(0, line->height())); + + // update selection + if (_selectionStart >= 0) { + int offset = end - start + 1; + int oldStart = _selectionStart; + if (_selectionStart >= start) + _selectionStart += offset; + if (_selectionEnd >= start) { + _selectionEnd += offset; + if (_selectionStart == oldStart) + for (int i = start; i < start + offset; i++) + _lines[i]->setSelected(true); + } + if (_firstSelectionRow >= start) + _firstSelectionRow += offset; } - } - // check if all went right - Q_ASSERT(start == 0 || _lines.at(start - 1)->pos().y() + _lines.at(start - 1)->height() == _lines.at(start)->pos().y()); + // neither pre- or append means we have to do dirty work: move items... + if (!(atTop || atBottom)) { + ChatLine *line = 0; + for (int i = 0; i <= end; i++) { + line = _lines.at(i); + line->setPos(0, line->pos().y() - h); + if (line == markerLine()->chatLine()) + markerLine()->setPos(line->pos() + QPointF(0, line->height())); + } + } + + // check if all went right + Q_ASSERT(start == 0 || _lines.at(start - 1)->pos().y() + _lines.at(start - 1)->height() == _lines.at(start)->pos().y()); // if(start != 0) { // if(_lines.at(start - 1)->pos().y() + _lines.at(start - 1)->height() != _lines.at(start)->pos().y()) { // qDebug() << "lines:" << _lines.count() << "start:" << start << "end:" << end; @@ -392,7 +418,7 @@ void ChatScene::rowsInserted(const QModelIndex &index, int start, int end) { // Q_ASSERT(false) // } // } - Q_ASSERT(end + 1 == _lines.count() || _lines.at(end)->pos().y() + _lines.at(end)->height() == _lines.at(end + 1)->pos().y()); + Q_ASSERT(end + 1 == _lines.count() || _lines.at(end)->pos().y() + _lines.at(end)->height() == _lines.at(end + 1)->pos().y()); // if(end + 1 < _lines.count()) { // if(_lines.at(end)->pos().y() + _lines.at(end)->height() != _lines.at(end + 1)->pos().y()) { // qDebug() << "lines:" << _lines.count() << "start:" << start << "end:" << end; @@ -403,745 +429,837 @@ void ChatScene::rowsInserted(const QModelIndex &index, int start, int end) { // } // } - if(!atBottom) { - if(start < _firstLineRow) { - int prevFirstLineRow = _firstLineRow + (end - start + 1); - for(int i = end + 1; i < prevFirstLineRow; i++) { - _lines.at(i)->show(); - } + if (!atBottom) { + if (start < _firstLineRow) { + int prevFirstLineRow = _firstLineRow + (end - start + 1); + for (int i = end + 1; i < prevFirstLineRow; i++) { + _lines.at(i)->show(); + } + } + // force new search for first proper line + _firstLineRow = -1; } - // force new search for first proper line - _firstLineRow = -1; - } - updateSceneRect(); - if(atBottom) { - emit lastLineChanged(_lines.last(), h); - } - - // now move the marker line if necessary. we don't need to do anything if we appended lines though... - if(!_markerLineValid) - setMarkerLine(); + updateSceneRect(); + if (atBottom) { + emit lastLineChanged(_lines.last(), h); + } + + // now move the marker line if necessary. we don't need to do anything if we appended lines though... + if (!_markerLineValid) + setMarkerLine(); } -void ChatScene::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { - Q_UNUSED(parent); - - qreal h = 0; // total height of removed items; - - bool atTop = (start == 0); - bool atBottom = (end == _lines.count() - 1); - - // clear selection - if(_selectingItem) { - int row = _selectingItem->row(); - if(row >= start && row <= end) - setSelectingItem(0); - } - - // remove items from scene - QList::iterator lineIter = _lines.begin() + start; - int lineCount = start; - while(lineIter != _lines.end() && lineCount <= end) { - if((*lineIter) == markerLine()->chatLine()) - markerLine()->setChatLine(0); - h += (*lineIter)->height(); - delete *lineIter; - lineIter = _lines.erase(lineIter); - lineCount++; - } - - // update rows of remaining chatlines - for(int i = start; i < _lines.count(); i++) { - _lines.at(i)->setRow(i); - } - - // update selection - if(_selectionStart >= 0) { - int offset = end - start + 1; - if(_selectionStart >= start) - _selectionStart = qMax(_selectionStart - offset, start); - if(_selectionEnd >= start) - _selectionEnd -= offset; - if(_firstSelectionRow >= start) - _firstSelectionRow -= offset; - - if(_selectionEnd < _selectionStart) { - _isSelecting = false; - _selectionStart = -1; + +void ChatScene::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent); + + qreal h = 0; // total height of removed items; + + bool atTop = (start == 0); + bool atBottom = (end == _lines.count() - 1); + + // clear selection + if (_selectingItem) { + int row = _selectingItem->row(); + if (row >= start && row <= end) + setSelectingItem(0); + } + + // remove items from scene + QList::iterator lineIter = _lines.begin() + start; + int lineCount = start; + while (lineIter != _lines.end() && lineCount <= end) { + if ((*lineIter) == markerLine()->chatLine()) + markerLine()->setChatLine(0); + h += (*lineIter)->height(); + delete *lineIter; + lineIter = _lines.erase(lineIter); + lineCount++; } - } - - // neither removing at bottom or top means we have to move items... - if(!(atTop || atBottom)) { - qreal offset = h; - int moveStart = 0; - int moveEnd = _lines.count() - 1; - if(start < _lines.count() - start) { - // move top part - moveEnd = start - 1; - } else { - // move bottom part - moveStart = start; - offset = -offset; + + // update rows of remaining chatlines + for (int i = start; i < _lines.count(); i++) { + _lines.at(i)->setRow(i); } - ChatLine *line = 0; - for(int i = moveStart; i <= moveEnd; i++) { - line = _lines.at(i); - line->setPos(0, line->pos().y() + offset); + + // update selection + if (_selectionStart >= 0) { + int offset = end - start + 1; + if (_selectionStart >= start) + _selectionStart = qMax(_selectionStart - offset, start); + if (_selectionEnd >= start) + _selectionEnd -= offset; + if (_firstSelectionRow >= start) + _firstSelectionRow -= offset; + + if (_selectionEnd < _selectionStart) { + _isSelecting = false; + _selectionStart = -1; + } } - } - - Q_ASSERT(start == 0 || start >= _lines.count() || _lines.at(start - 1)->pos().y() + _lines.at(start - 1)->height() == _lines.at(start)->pos().y()); - - // update sceneRect - // when searching for the first non-date-line we have to take into account that our - // model still contains the just removed lines so we cannot simply call updateSceneRect() - int numRows = model()->rowCount(); - QModelIndex firstLineIdx; - _firstLineRow = -1; - bool needOffset = false; - do { - _firstLineRow++; - if(_firstLineRow >= start && _firstLineRow <= end) { - _firstLineRow = end + 1; - needOffset = true; + + // neither removing at bottom or top means we have to move items... + if (!(atTop || atBottom)) { + qreal offset = h; + int moveStart = 0; + int moveEnd = _lines.count() - 1; + if (start < _lines.count() - start) { + // move top part + moveEnd = start - 1; + } + else { + // move bottom part + moveStart = start; + offset = -offset; + } + ChatLine *line = 0; + for (int i = moveStart; i <= moveEnd; i++) { + line = _lines.at(i); + line->setPos(0, line->pos().y() + offset); + } } - firstLineIdx = model()->index(_firstLineRow, 0); - } while((Message::Type)(model()->data(firstLineIdx, MessageModel::TypeRole).toInt()) == Message::DayChange && _firstLineRow < numRows); - if(needOffset) - _firstLineRow -= end - start + 1; - updateSceneRect(); -} + Q_ASSERT(start == 0 || start >= _lines.count() || _lines.at(start - 1)->pos().y() + _lines.at(start - 1)->height() == _lines.at(start)->pos().y()); -void ChatScene::rowsRemoved() { - // move the marker line if necessary - setMarkerLine(); + // update sceneRect + // when searching for the first non-date-line we have to take into account that our + // model still contains the just removed lines so we cannot simply call updateSceneRect() + int numRows = model()->rowCount(); + QModelIndex firstLineIdx; + _firstLineRow = -1; + bool needOffset = false; + do { + _firstLineRow++; + if (_firstLineRow >= start && _firstLineRow <= end) { + _firstLineRow = end + 1; + needOffset = true; + } + firstLineIdx = model()->index(_firstLineRow, 0); + } + while ((Message::Type)(model()->data(firstLineIdx, MessageModel::TypeRole).toInt()) == Message::DayChange && _firstLineRow < numRows); + + if (needOffset) + _firstLineRow -= end - start + 1; + updateSceneRect(); } -void ChatScene::dataChanged(const QModelIndex &tl, const QModelIndex &br) { - layout(tl.row(), br.row(), _sceneRect.width()); + +void ChatScene::rowsRemoved() +{ + // move the marker line if necessary + setMarkerLine(); } -void ChatScene::updateForViewport(qreal width, qreal height) { - _viewportHeight = height; - setWidth(width); + +void ChatScene::dataChanged(const QModelIndex &tl, const QModelIndex &br) +{ + layout(tl.row(), br.row(), _sceneRect.width()); } -void ChatScene::setWidth(qreal width) { - if(width == _sceneRect.width()) - return; - layout(0, _lines.count()-1, width); + +void ChatScene::updateForViewport(qreal width, qreal height) +{ + _viewportHeight = height; + setWidth(width); } -void ChatScene::layout(int start, int end, qreal width) { - // clock_t startT = clock(); - // disabling the index while doing this complex updates is about - // 2 to 10 times faster! - //setItemIndexMethod(QGraphicsScene::NoIndex); +void ChatScene::setWidth(qreal width) +{ + if (width == _sceneRect.width()) + return; + layout(0, _lines.count()-1, width); +} + - if(end >= 0) { - int row = end; - qreal linePos = _lines.at(row)->scenePos().y() + _lines.at(row)->height(); - qreal contentsWidth = width - secondColumnHandle()->sceneRight(); - while(row >= start) { - _lines.at(row--)->setGeometryByWidth(width, contentsWidth, linePos); - } +void ChatScene::layout(int start, int end, qreal width) +{ + // clock_t startT = clock(); + + // disabling the index while doing this complex updates is about + // 2 to 10 times faster! + //setItemIndexMethod(QGraphicsScene::NoIndex); + + if (end >= 0) { + int row = end; + qreal linePos = _lines.at(row)->scenePos().y() + _lines.at(row)->height(); + qreal contentsWidth = width - secondColumnHandle()->sceneRight(); + while (row >= start) { + _lines.at(row--)->setGeometryByWidth(width, contentsWidth, linePos); + } - if(row >= 0) { - // remaining items don't need geometry changes, but maybe repositioning? - ChatLine *line = _lines.at(row); - qreal offset = linePos - (line->scenePos().y() + line->height()); - if(offset != 0) { - while(row >= 0) { - line = _lines.at(row--); - line->setPos(0, line->scenePos().y() + offset); + if (row >= 0) { + // remaining items don't need geometry changes, but maybe repositioning? + ChatLine *line = _lines.at(row); + qreal offset = linePos - (line->scenePos().y() + line->height()); + if (offset != 0) { + while (row >= 0) { + line = _lines.at(row--); + line->setPos(0, line->scenePos().y() + offset); + } + } } - } } - } - //setItemIndexMethod(QGraphicsScene::BspTreeIndex); + //setItemIndexMethod(QGraphicsScene::BspTreeIndex); - updateSceneRect(width); - setHandleXLimits(); - setMarkerLine(); - emit layoutChanged(); + updateSceneRect(width); + setHandleXLimits(); + setMarkerLine(); + emit layoutChanged(); // clock_t endT = clock(); // qDebug() << "resized" << _lines.count() << "in" << (float)(endT - startT) / CLOCKS_PER_SEC << "sec"; } -void ChatScene::firstHandlePositionChanged(qreal xpos) { - if(_firstColHandlePos == xpos) - return; - _firstColHandlePos = xpos >= 0 ? xpos : 0; - ChatViewSettings viewSettings(this); - viewSettings.setValue("FirstColumnHandlePos", _firstColHandlePos); - ChatViewSettings defaultSettings; - defaultSettings.setValue("FirstColumnHandlePos", _firstColHandlePos); +void ChatScene::firstHandlePositionChanged(qreal xpos) +{ + if (_firstColHandlePos == xpos) + return; - // clock_t startT = clock(); + _firstColHandlePos = xpos >= 0 ? xpos : 0; + ChatViewSettings viewSettings(this); + viewSettings.setValue("FirstColumnHandlePos", _firstColHandlePos); + ChatViewSettings defaultSettings; + defaultSettings.setValue("FirstColumnHandlePos", _firstColHandlePos); - // disabling the index while doing this complex updates is about - // 2 to 10 times faster! - //setItemIndexMethod(QGraphicsScene::NoIndex); + // clock_t startT = clock(); - QList::iterator lineIter = _lines.end(); - QList::iterator lineIterBegin = _lines.begin(); - qreal timestampWidth = firstColumnHandle()->sceneLeft(); - qreal senderWidth = secondColumnHandle()->sceneLeft() - firstColumnHandle()->sceneRight(); - QPointF senderPos(firstColumnHandle()->sceneRight(), 0); + // disabling the index while doing this complex updates is about + // 2 to 10 times faster! + //setItemIndexMethod(QGraphicsScene::NoIndex); - while(lineIter != lineIterBegin) { - lineIter--; - (*lineIter)->setFirstColumn(timestampWidth, senderWidth, senderPos); - } - //setItemIndexMethod(QGraphicsScene::BspTreeIndex); + QList::iterator lineIter = _lines.end(); + QList::iterator lineIterBegin = _lines.begin(); + qreal timestampWidth = firstColumnHandle()->sceneLeft(); + qreal senderWidth = secondColumnHandle()->sceneLeft() - firstColumnHandle()->sceneRight(); + QPointF senderPos(firstColumnHandle()->sceneRight(), 0); + + while (lineIter != lineIterBegin) { + lineIter--; + (*lineIter)->setFirstColumn(timestampWidth, senderWidth, senderPos); + } + //setItemIndexMethod(QGraphicsScene::BspTreeIndex); - setHandleXLimits(); + setHandleXLimits(); // clock_t endT = clock(); // qDebug() << "resized" << _lines.count() << "in" << (float)(endT - startT) / CLOCKS_PER_SEC << "sec"; } -void ChatScene::secondHandlePositionChanged(qreal xpos) { - if(_secondColHandlePos == xpos) - return; - _secondColHandlePos = xpos; - ChatViewSettings viewSettings(this); - viewSettings.setValue("SecondColumnHandlePos", _secondColHandlePos); - ChatViewSettings defaultSettings; - defaultSettings.setValue("SecondColumnHandlePos", _secondColHandlePos); - - // clock_t startT = clock(); - - // disabling the index while doing this complex updates is about - // 2 to 10 times faster! - //setItemIndexMethod(QGraphicsScene::NoIndex); - - QList::iterator lineIter = _lines.end(); - QList::iterator lineIterBegin = _lines.begin(); - qreal linePos = _sceneRect.y() + _sceneRect.height(); - qreal senderWidth = secondColumnHandle()->sceneLeft() - firstColumnHandle()->sceneRight(); - qreal contentsWidth = _sceneRect.width() - secondColumnHandle()->sceneRight(); - QPointF contentsPos(secondColumnHandle()->sceneRight(), 0); - while(lineIter != lineIterBegin) { - lineIter--; - (*lineIter)->setSecondColumn(senderWidth, contentsWidth, contentsPos, linePos); - } - //setItemIndexMethod(QGraphicsScene::BspTreeIndex); - - updateSceneRect(); - setHandleXLimits(); - emit layoutChanged(); +void ChatScene::secondHandlePositionChanged(qreal xpos) +{ + if (_secondColHandlePos == xpos) + return; + + _secondColHandlePos = xpos; + ChatViewSettings viewSettings(this); + viewSettings.setValue("SecondColumnHandlePos", _secondColHandlePos); + ChatViewSettings defaultSettings; + defaultSettings.setValue("SecondColumnHandlePos", _secondColHandlePos); + + // clock_t startT = clock(); + + // disabling the index while doing this complex updates is about + // 2 to 10 times faster! + //setItemIndexMethod(QGraphicsScene::NoIndex); + + QList::iterator lineIter = _lines.end(); + QList::iterator lineIterBegin = _lines.begin(); + qreal linePos = _sceneRect.y() + _sceneRect.height(); + qreal senderWidth = secondColumnHandle()->sceneLeft() - firstColumnHandle()->sceneRight(); + qreal contentsWidth = _sceneRect.width() - secondColumnHandle()->sceneRight(); + QPointF contentsPos(secondColumnHandle()->sceneRight(), 0); + while (lineIter != lineIterBegin) { + lineIter--; + (*lineIter)->setSecondColumn(senderWidth, contentsWidth, contentsPos, linePos); + } + //setItemIndexMethod(QGraphicsScene::BspTreeIndex); + + updateSceneRect(); + setHandleXLimits(); + emit layoutChanged(); // clock_t endT = clock(); // qDebug() << "resized" << _lines.count() << "in" << (float)(endT - startT) / CLOCKS_PER_SEC << "sec"; } -void ChatScene::setHandleXLimits() { - _firstColHandle->setXLimits(0, _secondColHandle->sceneLeft()); - _secondColHandle->setXLimits(_firstColHandle->sceneRight(), width() - minContentsWidth); - update(); + +void ChatScene::setHandleXLimits() +{ + _firstColHandle->setXLimits(0, _secondColHandle->sceneLeft()); + _secondColHandle->setXLimits(_firstColHandle->sceneRight(), width() - minContentsWidth); + update(); } -void ChatScene::setSelectingItem(ChatItem *item) { - if(_selectingItem) _selectingItem->clearSelection(); - _selectingItem = item; + +void ChatScene::setSelectingItem(ChatItem *item) +{ + if (_selectingItem) _selectingItem->clearSelection(); + _selectingItem = item; } -void ChatScene::startGlobalSelection(ChatItem *item, const QPointF &itemPos) { - _selectionStart = _selectionEnd = _firstSelectionRow = item->row(); - _selectionStartCol = _selectionMinCol = item->column(); - _isSelecting = true; - _lines[_selectionStart]->setSelected(true, (ChatLineModel::ColumnType)_selectionMinCol); - updateSelection(item->mapToScene(itemPos)); + +void ChatScene::startGlobalSelection(ChatItem *item, const QPointF &itemPos) +{ + _selectionStart = _selectionEnd = _firstSelectionRow = item->row(); + _selectionStartCol = _selectionMinCol = item->column(); + _isSelecting = true; + _lines[_selectionStart]->setSelected(true, (ChatLineModel::ColumnType)_selectionMinCol); + updateSelection(item->mapToScene(itemPos)); } -void ChatScene::updateSelection(const QPointF &pos) { - int curRow = rowByScenePos(pos); - if(curRow < 0) return; - int curColumn = (int)columnByScenePos(pos); - ChatLineModel::ColumnType minColumn = (ChatLineModel::ColumnType)qMin(curColumn, _selectionStartCol); - if(minColumn != _selectionMinCol) { - _selectionMinCol = minColumn; - for(int l = qMin(_selectionStart, _selectionEnd); l <= qMax(_selectionStart, _selectionEnd); l++) { - _lines[l]->setSelected(true, minColumn); + +void ChatScene::updateSelection(const QPointF &pos) +{ + int curRow = rowByScenePos(pos); + if (curRow < 0) return; + int curColumn = (int)columnByScenePos(pos); + ChatLineModel::ColumnType minColumn = (ChatLineModel::ColumnType)qMin(curColumn, _selectionStartCol); + if (minColumn != _selectionMinCol) { + _selectionMinCol = minColumn; + for (int l = qMin(_selectionStart, _selectionEnd); l <= qMax(_selectionStart, _selectionEnd); l++) { + _lines[l]->setSelected(true, minColumn); + } + } + int newstart = qMin(curRow, _firstSelectionRow); + int newend = qMax(curRow, _firstSelectionRow); + if (newstart < _selectionStart) { + for (int l = newstart; l < _selectionStart; l++) + _lines[l]->setSelected(true, minColumn); } - } - int newstart = qMin(curRow, _firstSelectionRow); - int newend = qMax(curRow, _firstSelectionRow); - if(newstart < _selectionStart) { - for(int l = newstart; l < _selectionStart; l++) - _lines[l]->setSelected(true, minColumn); - } - if(newstart > _selectionStart) { - for(int l = _selectionStart; l < newstart; l++) - _lines[l]->setSelected(false); - } - if(newend > _selectionEnd) { - for(int l = _selectionEnd+1; l <= newend; l++) - _lines[l]->setSelected(true, minColumn); - } - if(newend < _selectionEnd) { - for(int l = newend+1; l <= _selectionEnd; l++) - _lines[l]->setSelected(false); - } - - _selectionStart = newstart; - _selectionEnd = newend; - - if(newstart == newend && minColumn == ChatLineModel::ContentsColumn) { - if(!_selectingItem) { - // _selectingItem has been removed already - return; + if (newstart > _selectionStart) { + for (int l = _selectionStart; l < newstart; l++) + _lines[l]->setSelected(false); + } + if (newend > _selectionEnd) { + for (int l = _selectionEnd+1; l <= newend; l++) + _lines[l]->setSelected(true, minColumn); + } + if (newend < _selectionEnd) { + for (int l = newend+1; l <= _selectionEnd; l++) + _lines[l]->setSelected(false); + } + + _selectionStart = newstart; + _selectionEnd = newend; + + if (newstart == newend && minColumn == ChatLineModel::ContentsColumn) { + if (!_selectingItem) { + // _selectingItem has been removed already + return; + } + _lines[curRow]->setSelected(false); + _isSelecting = false; + _selectionStart = -1; + _selectingItem->continueSelecting(_selectingItem->mapFromScene(pos)); } - _lines[curRow]->setSelected(false); - _isSelecting = false; - _selectionStart = -1; - _selectingItem->continueSelecting(_selectingItem->mapFromScene(pos)); - } } -bool ChatScene::isPosOverSelection(const QPointF &pos) const { - ChatItem *chatItem = chatItemAt(pos); - if(!chatItem) + +bool ChatScene::isPosOverSelection(const QPointF &pos) const +{ + ChatItem *chatItem = chatItemAt(pos); + if (!chatItem) + return false; + if (hasGlobalSelection()) { + int row = chatItem->row(); + if (row >= qMin(_selectionStart, _selectionEnd) && row <= qMax(_selectionStart, _selectionEnd)) + return columnByScenePos(pos) >= _selectionMinCol; + } + else { + return chatItem->isPosOverSelection(chatItem->mapFromScene(pos)); + } return false; - if(hasGlobalSelection()) { - int row = chatItem->row(); - if(row >= qMin(_selectionStart, _selectionEnd) && row <= qMax(_selectionStart, _selectionEnd)) - return columnByScenePos(pos) >= _selectionMinCol; - } else { - return chatItem->isPosOverSelection(chatItem->mapFromScene(pos)); - } - return false; } -bool ChatScene::isScrollingAllowed() const { - if(_isSelecting) - return false; - // TODO: Handle clicks and single-item selections too +bool ChatScene::isScrollingAllowed() const +{ + if (_isSelecting) + return false; + + // TODO: Handle clicks and single-item selections too - return true; + return true; } + /******** MOUSE HANDLING **************************************************************************/ -void ChatScene::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { - QPointF pos = event->scenePos(); - QMenu menu; +void ChatScene::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) +{ + QPointF pos = event->scenePos(); + QMenu menu; + + // zoom actions and similar + chatView()->addActionsToMenu(&menu, pos); + menu.addSeparator(); + + if (isPosOverSelection(pos)) + menu.addAction(SmallIcon("edit-copy"), tr("Copy Selection"), + this, SLOT(selectionToClipboard()), + QKeySequence::Copy); + + // item-specific options (select link etc) + ChatItem *item = chatItemAt(pos); + if (item) + item->addActionsToMenu(&menu, item->mapFromScene(pos)); + else + // no item -> default scene actions + GraphicalUi::contextMenuActionProvider()->addActions(&menu, filter(), BufferId()); + + if (QtUi::mainWindow()->menuBar()->isHidden()) + menu.addAction(QtUi::actionCollection("General")->action("ToggleMenuBar")); + + menu.exec(event->screenPos()); +} - // zoom actions and similar - chatView()->addActionsToMenu(&menu, pos); - menu.addSeparator(); - if(isPosOverSelection(pos)) - menu.addAction(SmallIcon("edit-copy"), tr("Copy Selection"), - this, SLOT(selectionToClipboard()), - QKeySequence::Copy); +void ChatScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + if (event->buttons() == Qt::LeftButton) { + if (!_clickHandled && (event->scenePos() - _clickPos).toPoint().manhattanLength() >= QApplication::startDragDistance()) { + if (_clickTimer.isActive()) + _clickTimer.stop(); + if (_clickMode == SingleClick && isPosOverSelection(_clickPos)) + initiateDrag(event->widget()); + else { + _clickMode = DragStartClick; + handleClick(Qt::LeftButton, _clickPos); + } + _clickMode = NoClick; + } + if (_isSelecting) { + updateSelection(event->scenePos()); + emit mouseMoveWhileSelecting(event->scenePos()); + event->accept(); + } + else if (_clickHandled && _clickMode < DoubleClick) + QGraphicsScene::mouseMoveEvent(event); + } + else + QGraphicsScene::mouseMoveEvent(event); +} - // item-specific options (select link etc) - ChatItem *item = chatItemAt(pos); - if(item) - item->addActionsToMenu(&menu, item->mapFromScene(pos)); - else - // no item -> default scene actions - GraphicalUi::contextMenuActionProvider()->addActions(&menu, filter(), BufferId()); - if (QtUi::mainWindow()->menuBar()->isHidden()) - menu.addAction(QtUi::actionCollection("General")->action("ToggleMenuBar")); +void ChatScene::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + if (event->buttons() == Qt::LeftButton) { + _leftButtonPressed = true; + _clickHandled = false; + if (!isPosOverSelection(event->scenePos())) { + // immediately clear selection if clicked outside; otherwise, wait for potential drag + clearSelection(); + } + if (_clickMode != NoClick && _clickTimer.isActive()) { + switch (_clickMode) { + case NoClick: + _clickMode = SingleClick; break; + case SingleClick: + _clickMode = DoubleClick; break; + case DoubleClick: + _clickMode = TripleClick; break; + case TripleClick: + _clickMode = DoubleClick; break; + case DragStartClick: + break; + } + handleClick(Qt::LeftButton, _clickPos); + } + else { + _clickMode = SingleClick; + _clickPos = event->scenePos(); + } + _clickTimer.start(); + } + if (event->type() == QEvent::GraphicsSceneMouseDoubleClick) + QGraphicsScene::mouseDoubleClickEvent(event); + else + QGraphicsScene::mousePressEvent(event); +} - menu.exec(event->screenPos()); +void ChatScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) +{ + // we check for doubleclick ourselves, so just call press handler + mousePressEvent(event); } -void ChatScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { - if(event->buttons() == Qt::LeftButton) { - if(!_clickHandled && (event->scenePos() - _clickPos).toPoint().manhattanLength() >= QApplication::startDragDistance()) { - if(_clickTimer.isActive()) - _clickTimer.stop(); - if(_clickMode == SingleClick && isPosOverSelection(_clickPos)) - initiateDrag(event->widget()); - else { - _clickMode = DragStartClick; - handleClick(Qt::LeftButton, _clickPos); - } - _clickMode = NoClick; - } - if(_isSelecting) { - updateSelection(event->scenePos()); - emit mouseMoveWhileSelecting(event->scenePos()); - event->accept(); - } else if(_clickHandled && _clickMode < DoubleClick) - QGraphicsScene::mouseMoveEvent(event); - } else - QGraphicsScene::mouseMoveEvent(event); -} -void ChatScene::mousePressEvent(QGraphicsSceneMouseEvent *event) { - if(event->buttons() == Qt::LeftButton) { - _leftButtonPressed = true; - _clickHandled = false; - if(!isPosOverSelection(event->scenePos())) { - // immediately clear selection if clicked outside; otherwise, wait for potential drag - clearSelection(); - } - if(_clickMode != NoClick && _clickTimer.isActive()) { - switch(_clickMode) { - case NoClick: _clickMode = SingleClick; break; - case SingleClick: _clickMode = DoubleClick; break; - case DoubleClick: _clickMode = TripleClick; break; - case TripleClick: _clickMode = DoubleClick; break; - case DragStartClick: break; - } - handleClick(Qt::LeftButton, _clickPos); - } else { - _clickMode = SingleClick; - _clickPos = event->scenePos(); +void ChatScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + if (event->button() == Qt::LeftButton && _leftButtonPressed) { + _leftButtonPressed = false; + if (_clickMode != NoClick) { + if (_clickMode == SingleClick) + clearSelection(); + event->accept(); + if (!_clickTimer.isActive()) + handleClick(Qt::LeftButton, _clickPos); + } + else { + // no click -> drag or selection move + if (isGloballySelecting()) { + selectionToClipboard(QClipboard::Selection); + _isSelecting = false; + event->accept(); + return; + } + } } - _clickTimer.start(); - } - if(event->type() == QEvent::GraphicsSceneMouseDoubleClick) - QGraphicsScene::mouseDoubleClickEvent(event); - else - QGraphicsScene::mousePressEvent(event); + QGraphicsScene::mouseReleaseEvent(event); } -void ChatScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { - // we check for doubleclick ourselves, so just call press handler - mousePressEvent(event); -} -void ChatScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { - if(event->button() == Qt::LeftButton && _leftButtonPressed) { - _leftButtonPressed = false; - if(_clickMode != NoClick) { - if(_clickMode == SingleClick) - clearSelection(); - event->accept(); - if(!_clickTimer.isActive()) +void ChatScene::clickTimeout() +{ + if (!_leftButtonPressed && _clickMode == SingleClick) handleClick(Qt::LeftButton, _clickPos); - } else { - // no click -> drag or selection move - if(isGloballySelecting()) { - selectionToClipboard(QClipboard::Selection); - _isSelecting = false; - event->accept(); - return; - } - } - } - QGraphicsScene::mouseReleaseEvent(event); } -void ChatScene::clickTimeout() { - if(!_leftButtonPressed && _clickMode == SingleClick) - handleClick(Qt::LeftButton, _clickPos); -} -void ChatScene::handleClick(Qt::MouseButton button, const QPointF &scenePos) { - if(button == Qt::LeftButton) { - clearSelection(); +void ChatScene::handleClick(Qt::MouseButton button, const QPointF &scenePos) +{ + if (button == Qt::LeftButton) { + clearSelection(); - // Now send click down to items - ChatItem *chatItem = chatItemAt(scenePos); - if(chatItem) { - chatItem->handleClick(chatItem->mapFromScene(scenePos), _clickMode); + // Now send click down to items + ChatItem *chatItem = chatItemAt(scenePos); + if (chatItem) { + chatItem->handleClick(chatItem->mapFromScene(scenePos), _clickMode); + } + _clickHandled = true; } - _clickHandled = true; - } } -void ChatScene::initiateDrag(QWidget *source) { - QDrag *drag = new QDrag(source); - QMimeData *mimeData = new QMimeData; - mimeData->setText(selection()); - drag->setMimeData(mimeData); - drag->exec(Qt::CopyAction); +void ChatScene::initiateDrag(QWidget *source) +{ + QDrag *drag = new QDrag(source); + QMimeData *mimeData = new QMimeData; + mimeData->setText(selection()); + drag->setMimeData(mimeData); + + drag->exec(Qt::CopyAction); } + /******** SELECTIONS ******************************************************************************/ -void ChatScene::selectionToClipboard(QClipboard::Mode mode) { - if(!hasSelection()) - return; +void ChatScene::selectionToClipboard(QClipboard::Mode mode) +{ + if (!hasSelection()) + return; - stringToClipboard(selection(), mode); + stringToClipboard(selection(), mode); } -void ChatScene::stringToClipboard(const QString &str_, QClipboard::Mode mode) { - QString str = str_; - // remove trailing linefeeds - if(str.endsWith('\n')) - str.chop(1); - switch(mode) { +void ChatScene::stringToClipboard(const QString &str_, QClipboard::Mode mode) +{ + QString str = str_; + // remove trailing linefeeds + if (str.endsWith('\n')) + str.chop(1); + + switch (mode) { case QClipboard::Clipboard: - QApplication::clipboard()->setText(str); - break; + QApplication::clipboard()->setText(str); + break; case QClipboard::Selection: - if(QApplication::clipboard()->supportsSelection()) - QApplication::clipboard()->setText(str, QClipboard::Selection); - break; + if (QApplication::clipboard()->supportsSelection()) + QApplication::clipboard()->setText(str, QClipboard::Selection); + break; default: - break; - }; + break; + }; } + //!\brief Convert current selection to human-readable string. -QString ChatScene::selection() const { - //TODO Make selection format configurable! - if(hasGlobalSelection()) { - int start = qMin(_selectionStart, _selectionEnd); - int end = qMax(_selectionStart, _selectionEnd); - if(start < 0 || end >= _lines.count()) { - qDebug() << "Invalid selection range:" << start << end; - return QString(); - } - QString result; - for(int l = start; l <= end; l++) { - if(_selectionMinCol == ChatLineModel::TimestampColumn) - result += _lines[l]->item(ChatLineModel::TimestampColumn)->data(MessageModel::DisplayRole).toString() + " "; - if(_selectionMinCol <= ChatLineModel::SenderColumn) - result += _lines[l]->item(ChatLineModel::SenderColumn)->data(MessageModel::DisplayRole).toString() + " "; - result += _lines[l]->item(ChatLineModel::ContentsColumn)->data(MessageModel::DisplayRole).toString() + "\n"; +QString ChatScene::selection() const +{ + //TODO Make selection format configurable! + if (hasGlobalSelection()) { + int start = qMin(_selectionStart, _selectionEnd); + int end = qMax(_selectionStart, _selectionEnd); + if (start < 0 || end >= _lines.count()) { + qDebug() << "Invalid selection range:" << start << end; + return QString(); + } + QString result; + for (int l = start; l <= end; l++) { + if (_selectionMinCol == ChatLineModel::TimestampColumn) + result += _lines[l]->item(ChatLineModel::TimestampColumn)->data(MessageModel::DisplayRole).toString() + " "; + if (_selectionMinCol <= ChatLineModel::SenderColumn) + result += _lines[l]->item(ChatLineModel::SenderColumn)->data(MessageModel::DisplayRole).toString() + " "; + result += _lines[l]->item(ChatLineModel::ContentsColumn)->data(MessageModel::DisplayRole).toString() + "\n"; + } + return result; } - return result; - } else if(selectingItem()) - return selectingItem()->selection(); - return QString(); + else if (selectingItem()) + return selectingItem()->selection(); + return QString(); } -bool ChatScene::hasSelection() const { - return hasGlobalSelection() || (selectingItem() && selectingItem()->hasSelection()); + +bool ChatScene::hasSelection() const +{ + return hasGlobalSelection() || (selectingItem() && selectingItem()->hasSelection()); } -bool ChatScene::hasGlobalSelection() const { - return _selectionStart >= 0; + +bool ChatScene::hasGlobalSelection() const +{ + return _selectionStart >= 0; } -bool ChatScene::isGloballySelecting() const { - return _isSelecting; + +bool ChatScene::isGloballySelecting() const +{ + return _isSelecting; } -void ChatScene::clearGlobalSelection() { - if(hasGlobalSelection()) { - for(int l = qMin(_selectionStart, _selectionEnd); l <= qMax(_selectionStart, _selectionEnd); l++) - _lines[l]->setSelected(false); - _isSelecting = false; - _selectionStart = -1; - } + +void ChatScene::clearGlobalSelection() +{ + if (hasGlobalSelection()) { + for (int l = qMin(_selectionStart, _selectionEnd); l <= qMax(_selectionStart, _selectionEnd); l++) + _lines[l]->setSelected(false); + _isSelecting = false; + _selectionStart = -1; + } } -void ChatScene::clearSelection() { - clearGlobalSelection(); - if(selectingItem()) - selectingItem()->clearSelection(); + +void ChatScene::clearSelection() +{ + clearGlobalSelection(); + if (selectingItem()) + selectingItem()->clearSelection(); } + /******** *************************************************************************************/ -void ChatScene::requestBacklog() { - MessageFilter *filter = qobject_cast(model()); - if(filter) - return filter->requestBacklog(); - return; +void ChatScene::requestBacklog() +{ + MessageFilter *filter = qobject_cast(model()); + if (filter) + return filter->requestBacklog(); + return; } -ChatLineModel::ColumnType ChatScene::columnByScenePos(qreal x) const { - if(x < _firstColHandle->x()) - return ChatLineModel::TimestampColumn; - if(x < _secondColHandle->x()) - return ChatLineModel::SenderColumn; - return ChatLineModel::ContentsColumn; +ChatLineModel::ColumnType ChatScene::columnByScenePos(qreal x) const +{ + if (x < _firstColHandle->x()) + return ChatLineModel::TimestampColumn; + if (x < _secondColHandle->x()) + return ChatLineModel::SenderColumn; + + return ChatLineModel::ContentsColumn; } -int ChatScene::rowByScenePos(qreal y) const { - QList itemList = items(QPointF(0, y)); - // ChatLine should be at the bottom of the list - for(int i = itemList.count()-1; i >= 0; i--) { - ChatLine *line = qgraphicsitem_cast(itemList.at(i)); - if(line) - return line->row(); - } - return -1; +int ChatScene::rowByScenePos(qreal y) const +{ + QList itemList = items(QPointF(0, y)); + + // ChatLine should be at the bottom of the list + for (int i = itemList.count()-1; i >= 0; i--) { + ChatLine *line = qgraphicsitem_cast(itemList.at(i)); + if (line) + return line->row(); + } + return -1; } -void ChatScene::updateSceneRect(qreal width) { - if(_lines.isEmpty()) { - updateSceneRect(QRectF(0, 0, width, 0)); - return; - } - - // we hide day change messages at the top by making the scene rect smaller - // and by calling QGraphicsItem::hide() on all leading day change messages - // the first one is needed to ensure proper scrollbar ranges - // the second for cases where the viewport is larger then the set scenerect - // (in this case the items are shown anyways) - if(_firstLineRow == -1) { - int numRows = model()->rowCount(); - _firstLineRow = 0; - QModelIndex firstLineIdx; - while(_firstLineRow < numRows) { - firstLineIdx = model()->index(_firstLineRow, 0); - if((Message::Type)(model()->data(firstLineIdx, MessageModel::TypeRole).toInt()) != Message::DayChange) - break; - _lines.at(_firstLineRow)->hide(); - _firstLineRow++; + +void ChatScene::updateSceneRect(qreal width) +{ + if (_lines.isEmpty()) { + updateSceneRect(QRectF(0, 0, width, 0)); + return; + } + + // we hide day change messages at the top by making the scene rect smaller + // and by calling QGraphicsItem::hide() on all leading day change messages + // the first one is needed to ensure proper scrollbar ranges + // the second for cases where the viewport is larger then the set scenerect + // (in this case the items are shown anyways) + if (_firstLineRow == -1) { + int numRows = model()->rowCount(); + _firstLineRow = 0; + QModelIndex firstLineIdx; + while (_firstLineRow < numRows) { + firstLineIdx = model()->index(_firstLineRow, 0); + if ((Message::Type)(model()->data(firstLineIdx, MessageModel::TypeRole).toInt()) != Message::DayChange) + break; + _lines.at(_firstLineRow)->hide(); + _firstLineRow++; + } + } + + // the following call should be safe. If it crashes something went wrong during insert/remove + if (_firstLineRow < _lines.count()) { + ChatLine *firstLine = _lines.at(_firstLineRow); + ChatLine *lastLine = _lines.last(); + updateSceneRect(QRectF(0, firstLine->pos().y(), width, lastLine->pos().y() + lastLine->height() - firstLine->pos().y())); + } + else { + // empty scene rect + updateSceneRect(QRectF(0, 0, width, 0)); } - } - - // the following call should be safe. If it crashes something went wrong during insert/remove - if(_firstLineRow < _lines.count()) { - ChatLine *firstLine = _lines.at(_firstLineRow); - ChatLine *lastLine = _lines.last(); - updateSceneRect(QRectF(0, firstLine->pos().y(), width, lastLine->pos().y() + lastLine->height() - firstLine->pos().y())); - } else { - // empty scene rect - updateSceneRect(QRectF(0, 0, width, 0)); - } } -void ChatScene::updateSceneRect(const QRectF &rect) { - _sceneRect = rect; - setSceneRect(rect); - update(); + +void ChatScene::updateSceneRect(const QRectF &rect) +{ + _sceneRect = rect; + setSceneRect(rect); + update(); } + // ======================================== // Webkit Only stuff // ======================================== #ifdef HAVE_WEBKIT -void ChatScene::loadWebPreview(ChatItem *parentItem, const QUrl &url, const QRectF &urlRect) { - if(!_showWebPreview) - return; +void ChatScene::loadWebPreview(ChatItem *parentItem, const QUrl &url, const QRectF &urlRect) +{ + if (!_showWebPreview) + return; - if(webPreview.urlRect != urlRect) - webPreview.urlRect = urlRect; + if (webPreview.urlRect != urlRect) + webPreview.urlRect = urlRect; - if(webPreview.parentItem != parentItem) - webPreview.parentItem = parentItem; + if (webPreview.parentItem != parentItem) + webPreview.parentItem = parentItem; - if(webPreview.url != url) { - webPreview.url = url; - // prepare to load a different URL - if(webPreview.previewItem) { - if(webPreview.previewItem->scene()) - removeItem(webPreview.previewItem); - delete webPreview.previewItem; - webPreview.previewItem = 0; + if (webPreview.url != url) { + webPreview.url = url; + // prepare to load a different URL + if (webPreview.previewItem) { + if (webPreview.previewItem->scene()) + removeItem(webPreview.previewItem); + delete webPreview.previewItem; + webPreview.previewItem = 0; + } + webPreview.previewState = WebPreview::NoPreview; } - webPreview.previewState = WebPreview::NoPreview; - } - if(webPreview.url.isEmpty()) - return; + if (webPreview.url.isEmpty()) + return; - // qDebug() << Q_FUNC_INFO << webPreview.previewState; - switch(webPreview.previewState) { - case WebPreview::NoPreview: - webPreview.previewState = WebPreview::NewPreview; - webPreview.timer.start(500); - break; - case WebPreview::NewPreview: - case WebPreview::DelayPreview: - case WebPreview::ShowPreview: - // we're already waiting for the next step or showing the preview - break; - case WebPreview::HidePreview: - // we still have a valid preview - webPreview.previewState = WebPreview::DelayPreview; - webPreview.timer.start(1000); - break; - } - // qDebug() << " new State:" << webPreview.previewState << webPreview.timer.isActive(); + // qDebug() << Q_FUNC_INFO << webPreview.previewState; + switch (webPreview.previewState) { + case WebPreview::NoPreview: + webPreview.previewState = WebPreview::NewPreview; + webPreview.timer.start(500); + break; + case WebPreview::NewPreview: + case WebPreview::DelayPreview: + case WebPreview::ShowPreview: + // we're already waiting for the next step or showing the preview + break; + case WebPreview::HidePreview: + // we still have a valid preview + webPreview.previewState = WebPreview::DelayPreview; + webPreview.timer.start(1000); + break; + } + // qDebug() << " new State:" << webPreview.previewState << webPreview.timer.isActive(); } -void ChatScene::webPreviewNextStep() { - // qDebug() << Q_FUNC_INFO << webPreview.previewState; - switch(webPreview.previewState) { - case WebPreview::NoPreview: - break; - case WebPreview::NewPreview: - Q_ASSERT(!webPreview.previewItem); - webPreview.previewItem = new WebPreviewItem(webPreview.url); - webPreview.previewState = WebPreview::DelayPreview; - webPreview.timer.start(1000); - break; - case WebPreview::DelayPreview: - Q_ASSERT(webPreview.previewItem); - // calc position and show - { - qreal previewY = webPreview.urlRect.bottom(); - qreal previewX = webPreview.urlRect.x(); - if(previewY + webPreview.previewItem->boundingRect().height() > sceneRect().bottom()) - previewY = webPreview.urlRect.y() - webPreview.previewItem->boundingRect().height(); - - if(previewX + webPreview.previewItem->boundingRect().width() > sceneRect().width()) - previewX = sceneRect().right() - webPreview.previewItem->boundingRect().width(); - - webPreview.previewItem->setPos(previewX, previewY); - } - addItem(webPreview.previewItem); - webPreview.previewState = WebPreview::ShowPreview; - break; - case WebPreview::ShowPreview: - qWarning() << "ChatScene::webPreviewNextStep() called while in ShowPreview Step!"; - qWarning() << "removing preview"; - if(webPreview.previewItem && webPreview.previewItem->scene()) - removeItem(webPreview.previewItem); + +void ChatScene::webPreviewNextStep() +{ + // qDebug() << Q_FUNC_INFO << webPreview.previewState; + switch (webPreview.previewState) { + case WebPreview::NoPreview: + break; + case WebPreview::NewPreview: + Q_ASSERT(!webPreview.previewItem); + webPreview.previewItem = new WebPreviewItem(webPreview.url); + webPreview.previewState = WebPreview::DelayPreview; + webPreview.timer.start(1000); + break; + case WebPreview::DelayPreview: + Q_ASSERT(webPreview.previewItem); + // calc position and show + { + qreal previewY = webPreview.urlRect.bottom(); + qreal previewX = webPreview.urlRect.x(); + if (previewY + webPreview.previewItem->boundingRect().height() > sceneRect().bottom()) + previewY = webPreview.urlRect.y() - webPreview.previewItem->boundingRect().height(); + + if (previewX + webPreview.previewItem->boundingRect().width() > sceneRect().width()) + previewX = sceneRect().right() - webPreview.previewItem->boundingRect().width(); + + webPreview.previewItem->setPos(previewX, previewY); + } + addItem(webPreview.previewItem); + webPreview.previewState = WebPreview::ShowPreview; + break; + case WebPreview::ShowPreview: + qWarning() << "ChatScene::webPreviewNextStep() called while in ShowPreview Step!"; + qWarning() << "removing preview"; + if (webPreview.previewItem && webPreview.previewItem->scene()) + removeItem(webPreview.previewItem); // Fall through to deletion! - case WebPreview::HidePreview: - if(webPreview.previewItem) { - delete webPreview.previewItem; - webPreview.previewItem = 0; + case WebPreview::HidePreview: + if (webPreview.previewItem) { + delete webPreview.previewItem; + webPreview.previewItem = 0; + } + webPreview.parentItem = 0; + webPreview.url = QUrl(); + webPreview.urlRect = QRectF(); + webPreview.previewState = WebPreview::NoPreview; } - webPreview.parentItem = 0; - webPreview.url = QUrl(); - webPreview.urlRect = QRectF(); - webPreview.previewState = WebPreview::NoPreview; - } - // qDebug() << " new State:" << webPreview.previewState << webPreview.timer.isActive(); + // qDebug() << " new State:" << webPreview.previewState << webPreview.timer.isActive(); } -void ChatScene::clearWebPreview(ChatItem *parentItem) { - // qDebug() << Q_FUNC_INFO << webPreview.previewState; - switch(webPreview.previewState) { - case WebPreview::NewPreview: - webPreview.previewState = WebPreview::NoPreview; // we haven't loaded anything yet - break; - case WebPreview::ShowPreview: - if(parentItem == 0 || webPreview.parentItem == parentItem) { - if(webPreview.previewItem && webPreview.previewItem->scene()) - removeItem(webPreview.previewItem); - } + +void ChatScene::clearWebPreview(ChatItem *parentItem) +{ + // qDebug() << Q_FUNC_INFO << webPreview.previewState; + switch (webPreview.previewState) { + case WebPreview::NewPreview: + webPreview.previewState = WebPreview::NoPreview; // we haven't loaded anything yet + break; + case WebPreview::ShowPreview: + if (parentItem == 0 || webPreview.parentItem == parentItem) { + if (webPreview.previewItem && webPreview.previewItem->scene()) + removeItem(webPreview.previewItem); + } // fall through into to set hidden state - case WebPreview::DelayPreview: - // we're just loading, so haven't shown the preview yet. - webPreview.previewState = WebPreview::HidePreview; - webPreview.timer.start(5000); - break; - case WebPreview::NoPreview: - case WebPreview::HidePreview: - break; - } - // qDebug() << " new State:" << webPreview.previewState << webPreview.timer.isActive(); + case WebPreview::DelayPreview: + // we're just loading, so haven't shown the preview yet. + webPreview.previewState = WebPreview::HidePreview; + webPreview.timer.start(5000); + break; + case WebPreview::NoPreview: + case WebPreview::HidePreview: + break; + } + // qDebug() << " new State:" << webPreview.previewState << webPreview.timer.isActive(); } + + #endif // ======================================== // end of webkit only // ======================================== -void ChatScene::showWebPreviewChanged() { - ChatViewSettings settings; - _showWebPreview = settings.showWebPreview(); +void ChatScene::showWebPreviewChanged() +{ + ChatViewSettings settings; + _showWebPreview = settings.showWebPreview(); } diff --git a/src/qtui/chatscene.h b/src/qtui/chatscene.h index ea9df69b..2622a0ef 100644 --- a/src/qtui/chatscene.h +++ b/src/qtui/chatscene.h @@ -42,203 +42,205 @@ class WebPreviewItem; class QGraphicsSceneMouseEvent; -class ChatScene : public QGraphicsScene { - Q_OBJECT +class ChatScene : public QGraphicsScene +{ + Q_OBJECT public: - enum CutoffMode { - CutoffLeft, - CutoffRight - }; - - enum ItemType { - ChatLineType = QGraphicsItem::UserType + 1, - ChatItemType, - TimestampChatItemType, - SenderChatItemType, - ContentsChatItemType, - SearchHighlightType, - WebPreviewType, - ColumnHandleType, - MarkerLineType - }; - - enum ClickMode { - NoClick, - DragStartClick, - SingleClick, - DoubleClick, - TripleClick - }; - - ChatScene(QAbstractItemModel *model, const QString &idString, qreal width, ChatView *parent); - virtual ~ChatScene(); - - inline QAbstractItemModel *model() const { return _model; } - inline MessageFilter *filter() const { return qobject_cast(_model); } - inline QString idString() const { return _idString; } - - int rowByScenePos(qreal y) const; - inline int rowByScenePos(const QPointF &pos) const { return rowByScenePos(pos.y()); } - ChatLineModel::ColumnType columnByScenePos(qreal x) const ; - inline ChatLineModel::ColumnType columnByScenePos(const QPointF &pos) const { return columnByScenePos(pos.x()); } - - ChatView *chatView() const; - ChatItem *chatItemAt(const QPointF &pos) const; - inline ChatLine *chatLine(int row) const { return (row < _lines.count()) ? _lines.value(row) : 0; } - inline ChatLine *chatLine(const QModelIndex &index) const { return _lines.value(index.row()); } - - //! Find the ChatLine belonging to a MsgId - /** Searches for the ChatLine belonging to a MsgId. If there are more than one ChatLine with the same msgId, - * the first one is returned. - * Note that this method performs a binary search, hence it has as complexity of O(log n). - * If matchExact is false, and we don't have an exact match for the given msgId, we return the visible line right - * above the requested one. - * \param msgId The message ID to look for - * \param matchExact Whether we find only exact matches - * \param ignoreDayChange Whether we ignore day change messages - * \return The ChatLine corresponding to the given MsgId - */ - ChatLine *chatLine(MsgId msgId, bool matchExact = true, bool ignoreDayChange = true) const; - - inline ChatLine *lastLine() const { return _lines.count() ? _lines.last() : 0; } - - inline MarkerLineItem *markerLine() const { return _markerLine; } - - inline bool isSingleBufferScene() const { return _singleBufferId.isValid(); } - inline BufferId singleBufferId() const { return _singleBufferId; } - bool containsBuffer(const BufferId &id) const; - - ColumnHandleItem *firstColumnHandle() const; - ColumnHandleItem *secondColumnHandle() const; - - inline CutoffMode senderCutoffMode() const { return _cutoffMode; } - inline void setSenderCutoffMode(CutoffMode mode) { _cutoffMode = mode; } - - QString selection() const; - bool hasSelection() const; - bool hasGlobalSelection() const; - bool isPosOverSelection(const QPointF &) const; - bool isGloballySelecting() const; - void initiateDrag(QWidget *source); - - bool isScrollingAllowed() const; - - public slots: - void updateForViewport(qreal width, qreal height); - void setWidth(qreal width); - void layout(int start, int end, qreal width); - - void setMarkerLineVisible(bool visible = true); - void setMarkerLine(MsgId msgId = MsgId()); - void jumpToMarkerLine(bool requestBacklog); - - // these are used by the chatitems to notify the scene and manage selections - void setSelectingItem(ChatItem *item); - ChatItem *selectingItem() const { return _selectingItem; } - void startGlobalSelection(ChatItem *item, const QPointF &itemPos); - void clearGlobalSelection(); - void clearSelection(); - void selectionToClipboard(QClipboard::Mode = QClipboard::Clipboard); - void stringToClipboard(const QString &str, QClipboard::Mode = QClipboard::Clipboard); - - void requestBacklog(); + enum CutoffMode { + CutoffLeft, + CutoffRight + }; + + enum ItemType { + ChatLineType = QGraphicsItem::UserType + 1, + ChatItemType, + TimestampChatItemType, + SenderChatItemType, + ContentsChatItemType, + SearchHighlightType, + WebPreviewType, + ColumnHandleType, + MarkerLineType + }; + + enum ClickMode { + NoClick, + DragStartClick, + SingleClick, + DoubleClick, + TripleClick + }; + + ChatScene(QAbstractItemModel *model, const QString &idString, qreal width, ChatView *parent); + virtual ~ChatScene(); + + inline QAbstractItemModel *model() const { return _model; } + inline MessageFilter *filter() const { return qobject_cast(_model); } + inline QString idString() const { return _idString; } + + int rowByScenePos(qreal y) const; + inline int rowByScenePos(const QPointF &pos) const { return rowByScenePos(pos.y()); } + ChatLineModel::ColumnType columnByScenePos(qreal x) const; + inline ChatLineModel::ColumnType columnByScenePos(const QPointF &pos) const { return columnByScenePos(pos.x()); } + + ChatView *chatView() const; + ChatItem *chatItemAt(const QPointF &pos) const; + inline ChatLine *chatLine(int row) const { return (row < _lines.count()) ? _lines.value(row) : 0; } + inline ChatLine *chatLine(const QModelIndex &index) const { return _lines.value(index.row()); } + + //! Find the ChatLine belonging to a MsgId + /** Searches for the ChatLine belonging to a MsgId. If there are more than one ChatLine with the same msgId, + * the first one is returned. + * Note that this method performs a binary search, hence it has as complexity of O(log n). + * If matchExact is false, and we don't have an exact match for the given msgId, we return the visible line right + * above the requested one. + * \param msgId The message ID to look for + * \param matchExact Whether we find only exact matches + * \param ignoreDayChange Whether we ignore day change messages + * \return The ChatLine corresponding to the given MsgId + */ + ChatLine *chatLine(MsgId msgId, bool matchExact = true, bool ignoreDayChange = true) const; + + inline ChatLine *lastLine() const { return _lines.count() ? _lines.last() : 0; } + + inline MarkerLineItem *markerLine() const { return _markerLine; } + + inline bool isSingleBufferScene() const { return _singleBufferId.isValid(); } + inline BufferId singleBufferId() const { return _singleBufferId; } + bool containsBuffer(const BufferId &id) const; + + ColumnHandleItem *firstColumnHandle() const; + ColumnHandleItem *secondColumnHandle() const; + + inline CutoffMode senderCutoffMode() const { return _cutoffMode; } + inline void setSenderCutoffMode(CutoffMode mode) { _cutoffMode = mode; } + + QString selection() const; + bool hasSelection() const; + bool hasGlobalSelection() const; + bool isPosOverSelection(const QPointF &) const; + bool isGloballySelecting() const; + void initiateDrag(QWidget *source); + + bool isScrollingAllowed() const; + +public slots: + void updateForViewport(qreal width, qreal height); + void setWidth(qreal width); + void layout(int start, int end, qreal width); + + void setMarkerLineVisible(bool visible = true); + void setMarkerLine(MsgId msgId = MsgId()); + void jumpToMarkerLine(bool requestBacklog); + + // these are used by the chatitems to notify the scene and manage selections + void setSelectingItem(ChatItem *item); + ChatItem *selectingItem() const { return _selectingItem; } + void startGlobalSelection(ChatItem *item, const QPointF &itemPos); + void clearGlobalSelection(); + void clearSelection(); + void selectionToClipboard(QClipboard::Mode = QClipboard::Clipboard); + void stringToClipboard(const QString &str, QClipboard::Mode = QClipboard::Clipboard); + + void requestBacklog(); #ifdef HAVE_WEBKIT - void loadWebPreview(ChatItem *parentItem, const QUrl &url, const QRectF &urlRect); - void clearWebPreview(ChatItem *parentItem = 0); + void loadWebPreview(ChatItem *parentItem, const QUrl &url, const QRectF &urlRect); + void clearWebPreview(ChatItem *parentItem = 0); #endif signals: - void lastLineChanged(QGraphicsItem *item, qreal offset); - void layoutChanged(); // indicates changes to the scenerect due to resizing of the contentsitems - void mouseMoveWhileSelecting(const QPointF &scenePos); + void lastLineChanged(QGraphicsItem *item, qreal offset); + void layoutChanged(); // indicates changes to the scenerect due to resizing of the contentsitems + void mouseMoveWhileSelecting(const QPointF &scenePos); protected: - virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *contextMenuEvent); - virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent); - virtual void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent); - virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent); - virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *mouseEvent); - virtual void handleClick(Qt::MouseButton button, const QPointF &scenePos); + virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *contextMenuEvent); + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent); + virtual void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent); + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent); + virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *mouseEvent); + virtual void handleClick(Qt::MouseButton button, const QPointF &scenePos); protected slots: - void rowsInserted(const QModelIndex &, int, int); - void rowsAboutToBeRemoved(const QModelIndex &, int, int); - void dataChanged(const QModelIndex &, const QModelIndex &); + void rowsInserted(const QModelIndex &, int, int); + void rowsAboutToBeRemoved(const QModelIndex &, int, int); + void dataChanged(const QModelIndex &, const QModelIndex &); private slots: - void firstHandlePositionChanged(qreal xpos); - void secondHandlePositionChanged(qreal xpos); + void firstHandlePositionChanged(qreal xpos); + void secondHandlePositionChanged(qreal xpos); #ifdef HAVE_WEBKIT - void webPreviewNextStep(); + void webPreviewNextStep(); #endif - void showWebPreviewChanged(); + void showWebPreviewChanged(); - void rowsRemoved(); + void rowsRemoved(); - void clickTimeout(); + void clickTimeout(); private: - void setHandleXLimits(); - void updateSelection(const QPointF &pos); - - ChatView *_chatView; - QString _idString; - QAbstractItemModel *_model; - QList _lines; - BufferId _singleBufferId; - - // calls to QChatScene::sceneRect() are very expensive. As we manage the scenerect ourselves - // we store the size in a member variable. - QRectF _sceneRect; - int _firstLineRow; // the first row to display (aka: not a daychange msg) - void updateSceneRect(qreal width); - inline void updateSceneRect() { updateSceneRect(_sceneRect.width()); } - void updateSceneRect(const QRectF &rect); - qreal _viewportHeight; - - MarkerLineItem *_markerLine; - bool _markerLineVisible, _markerLineValid, _markerLineJumpPending; - - ColumnHandleItem *_firstColHandle, *_secondColHandle; - qreal _firstColHandlePos, _secondColHandlePos; - CutoffMode _cutoffMode; - - ChatItem *_selectingItem; - int _selectionStartCol, _selectionMinCol; - int _selectionStart; - int _selectionEnd; - int _firstSelectionRow; - bool _isSelecting; - - QTimer _clickTimer; - ClickMode _clickMode; - QPointF _clickPos; - bool _clickHandled; - bool _leftButtonPressed; - - bool _showWebPreview; + void setHandleXLimits(); + void updateSelection(const QPointF &pos); + + ChatView *_chatView; + QString _idString; + QAbstractItemModel *_model; + QList _lines; + BufferId _singleBufferId; + + // calls to QChatScene::sceneRect() are very expensive. As we manage the scenerect ourselves + // we store the size in a member variable. + QRectF _sceneRect; + int _firstLineRow; // the first row to display (aka: not a daychange msg) + void updateSceneRect(qreal width); + inline void updateSceneRect() { updateSceneRect(_sceneRect.width()); } + void updateSceneRect(const QRectF &rect); + qreal _viewportHeight; + + MarkerLineItem *_markerLine; + bool _markerLineVisible, _markerLineValid, _markerLineJumpPending; + + ColumnHandleItem *_firstColHandle, *_secondColHandle; + qreal _firstColHandlePos, _secondColHandlePos; + CutoffMode _cutoffMode; + + ChatItem *_selectingItem; + int _selectionStartCol, _selectionMinCol; + int _selectionStart; + int _selectionEnd; + int _firstSelectionRow; + bool _isSelecting; + + QTimer _clickTimer; + ClickMode _clickMode; + QPointF _clickPos; + bool _clickHandled; + bool _leftButtonPressed; + + bool _showWebPreview; #ifdef HAVE_WEBKIT - struct WebPreview { - enum PreviewState { - NoPreview, - NewPreview, - DelayPreview, - ShowPreview, - HidePreview + struct WebPreview { + enum PreviewState { + NoPreview, + NewPreview, + DelayPreview, + ShowPreview, + HidePreview + }; + ChatItem *parentItem; + QGraphicsItem *previewItem; + QUrl url; + QRectF urlRect; + PreviewState previewState; + QTimer timer; + WebPreview() : parentItem(0), previewItem(0), previewState(NoPreview) {} }; - ChatItem *parentItem; - QGraphicsItem *previewItem; - QUrl url; - QRectF urlRect; - PreviewState previewState; - QTimer timer; - WebPreview() : parentItem(0), previewItem(0), previewState(NoPreview) {} - }; - WebPreview webPreview; + WebPreview webPreview; #endif // HAVE_WEBKIT }; + #endif diff --git a/src/qtui/chatview.cpp b/src/qtui/chatview.cpp index cc5009b9..334a5604 100644 --- a/src/qtui/chatview.cpp +++ b/src/qtui/chatview.cpp @@ -35,320 +35,374 @@ #include "chatline.h" ChatView::ChatView(BufferId bufferId, QWidget *parent) - : QGraphicsView(parent), + : QGraphicsView(parent), AbstractChatView() { - QList filterList; - filterList.append(bufferId); - MessageFilter *filter = new MessageFilter(Client::messageModel(), filterList, this); - init(filter); + QList filterList; + filterList.append(bufferId); + MessageFilter *filter = new MessageFilter(Client::messageModel(), filterList, this); + init(filter); } + ChatView::ChatView(MessageFilter *filter, QWidget *parent) - : QGraphicsView(parent), + : QGraphicsView(parent), AbstractChatView() { - init(filter); + init(filter); } -void ChatView::init(MessageFilter *filter) { - _bufferContainer = 0; - _currentScaleFactor = 1; - _invalidateFilter = false; - - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); - setAlignment(Qt::AlignLeft|Qt::AlignBottom); - setInteractive(true); - //setOptimizationFlags(QGraphicsView::DontClipPainter | QGraphicsView::DontAdjustForAntialiasing); - // setOptimizationFlags(QGraphicsView::DontAdjustForAntialiasing); - setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); - // setTransformationAnchor(QGraphicsView::NoAnchor); - setTransformationAnchor(QGraphicsView::AnchorViewCenter); - - _scrollTimer.setInterval(100); - _scrollTimer.setSingleShot(true); - connect(&_scrollTimer, SIGNAL(timeout()), SLOT(scrollTimerTimeout())); - - _scene = new ChatScene(filter, filter->idString(), viewport()->width(), this); - connect(_scene, SIGNAL(sceneRectChanged(const QRectF &)), this, SLOT(adjustSceneRect())); - connect(_scene, SIGNAL(lastLineChanged(QGraphicsItem *, qreal)), this, SLOT(lastLineChanged(QGraphicsItem *, qreal))); - connect(_scene, SIGNAL(mouseMoveWhileSelecting(const QPointF &)), this, SLOT(mouseMoveWhileSelecting(const QPointF &))); - setScene(_scene); - - connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(verticalScrollbarChanged(int))); - _lastScrollbarPos = verticalScrollBar()->value(); - - connect(Client::networkModel(), SIGNAL(markerLineSet(BufferId,MsgId)), SLOT(markerLineSet(BufferId,MsgId))); - - // only connect if client is synched with a core - if(Client::isConnected()) - connect(Client::ignoreListManager(), SIGNAL(ignoreListChanged()), this, SLOT(invalidateFilter())); + +void ChatView::init(MessageFilter *filter) +{ + _bufferContainer = 0; + _currentScaleFactor = 1; + _invalidateFilter = false; + + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + setAlignment(Qt::AlignLeft|Qt::AlignBottom); + setInteractive(true); + //setOptimizationFlags(QGraphicsView::DontClipPainter | QGraphicsView::DontAdjustForAntialiasing); + // setOptimizationFlags(QGraphicsView::DontAdjustForAntialiasing); + setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); + // setTransformationAnchor(QGraphicsView::NoAnchor); + setTransformationAnchor(QGraphicsView::AnchorViewCenter); + + _scrollTimer.setInterval(100); + _scrollTimer.setSingleShot(true); + connect(&_scrollTimer, SIGNAL(timeout()), SLOT(scrollTimerTimeout())); + + _scene = new ChatScene(filter, filter->idString(), viewport()->width(), this); + connect(_scene, SIGNAL(sceneRectChanged(const QRectF &)), this, SLOT(adjustSceneRect())); + connect(_scene, SIGNAL(lastLineChanged(QGraphicsItem *, qreal)), this, SLOT(lastLineChanged(QGraphicsItem *, qreal))); + connect(_scene, SIGNAL(mouseMoveWhileSelecting(const QPointF &)), this, SLOT(mouseMoveWhileSelecting(const QPointF &))); + setScene(_scene); + + connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(verticalScrollbarChanged(int))); + _lastScrollbarPos = verticalScrollBar()->value(); + + connect(Client::networkModel(), SIGNAL(markerLineSet(BufferId, MsgId)), SLOT(markerLineSet(BufferId, MsgId))); + + // only connect if client is synched with a core + if (Client::isConnected()) + connect(Client::ignoreListManager(), SIGNAL(ignoreListChanged()), this, SLOT(invalidateFilter())); } -bool ChatView::event(QEvent *event) { - if(event->type() == QEvent::KeyPress) { - QKeyEvent *keyEvent = static_cast(event); - switch(keyEvent->key()) { - case Qt::Key_Up: - case Qt::Key_Down: - case Qt::Key_PageUp: - case Qt::Key_PageDown: - if(!verticalScrollBar()->isVisible()) { - scene()->requestBacklog(); - return true; - } - default: - break; + +bool ChatView::event(QEvent *event) +{ + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + switch (keyEvent->key()) { + case Qt::Key_Up: + case Qt::Key_Down: + case Qt::Key_PageUp: + case Qt::Key_PageDown: + if (!verticalScrollBar()->isVisible()) { + scene()->requestBacklog(); + return true; + } + default: + break; + } } - } - if(event->type() == QEvent::Wheel) { - if(!verticalScrollBar()->isVisible()) { - scene()->requestBacklog(); - return true; + if (event->type() == QEvent::Wheel) { + if (!verticalScrollBar()->isVisible()) { + scene()->requestBacklog(); + return true; + } } - } - if(event->type() == QEvent::Show) { - if(_invalidateFilter) - invalidateFilter(); - } + if (event->type() == QEvent::Show) { + if (_invalidateFilter) + invalidateFilter(); + } - return QGraphicsView::event(event); + return QGraphicsView::event(event); } -void ChatView::resizeEvent(QResizeEvent *event) { - QGraphicsView::resizeEvent(event); - // FIXME: do we really need to scroll down on resize? +void ChatView::resizeEvent(QResizeEvent *event) +{ + QGraphicsView::resizeEvent(event); + + // FIXME: do we really need to scroll down on resize? - // we can reduce viewport updates if we scroll to the bottom allready at the beginning - verticalScrollBar()->setValue(verticalScrollBar()->maximum()); - scene()->updateForViewport(viewport()->width(), viewport()->height()); - adjustSceneRect(); + // we can reduce viewport updates if we scroll to the bottom allready at the beginning + verticalScrollBar()->setValue(verticalScrollBar()->maximum()); + scene()->updateForViewport(viewport()->width(), viewport()->height()); + adjustSceneRect(); - _lastScrollbarPos = verticalScrollBar()->maximum(); - verticalScrollBar()->setValue(verticalScrollBar()->maximum()); + _lastScrollbarPos = verticalScrollBar()->maximum(); + verticalScrollBar()->setValue(verticalScrollBar()->maximum()); - checkChatLineCaches(); + checkChatLineCaches(); } -void ChatView::adjustSceneRect() { - // Workaround for QTBUG-6322 - // If the viewport's sceneRect() is (almost) as wide as as the viewport itself, - // Qt wants to reserve space for scrollbars even if they're turned off, resulting in - // an ugly white space at the bottom of the ChatView. - // Since the view's scene's width actually doesn't matter at all, we just adjust it - // by some hopefully large enough value to avoid this problem. - setSceneRect(scene()->sceneRect().adjusted(0, 0, -25 ,0)); +void ChatView::adjustSceneRect() +{ + // Workaround for QTBUG-6322 + // If the viewport's sceneRect() is (almost) as wide as as the viewport itself, + // Qt wants to reserve space for scrollbars even if they're turned off, resulting in + // an ugly white space at the bottom of the ChatView. + // Since the view's scene's width actually doesn't matter at all, we just adjust it + // by some hopefully large enough value to avoid this problem. + + setSceneRect(scene()->sceneRect().adjusted(0, 0, -25, 0)); } -void ChatView::mouseMoveWhileSelecting(const QPointF &scenePos) { - int y = (int)mapFromScene(scenePos).y(); - _scrollOffset = 0; - if(y < 0) - _scrollOffset = y; - else if(y > height()) - _scrollOffset = y - height(); - if(_scrollOffset && !_scrollTimer.isActive()) - _scrollTimer.start(); +void ChatView::mouseMoveWhileSelecting(const QPointF &scenePos) +{ + int y = (int)mapFromScene(scenePos).y(); + _scrollOffset = 0; + if (y < 0) + _scrollOffset = y; + else if (y > height()) + _scrollOffset = y - height(); + + if (_scrollOffset && !_scrollTimer.isActive()) + _scrollTimer.start(); } -void ChatView::scrollTimerTimeout() { - // scroll view - QAbstractSlider *vbar = verticalScrollBar(); - if(_scrollOffset < 0 && vbar->value() > 0) - vbar->setValue(qMax(vbar->value() + _scrollOffset, 0)); - else if(_scrollOffset > 0 && vbar->value() < vbar->maximum()) - vbar->setValue(qMin(vbar->value() + _scrollOffset, vbar->maximum())); -} -void ChatView::lastLineChanged(QGraphicsItem *chatLine, qreal offset) { - Q_UNUSED(chatLine) - // disabled until further testing/discussion - //if(!scene()->isScrollingAllowed()) - // return; - - QAbstractSlider *vbar = verticalScrollBar(); - Q_ASSERT(vbar); - if(vbar->maximum() - vbar->value() <= (offset + 5) * _currentScaleFactor ) { // 5px grace area - vbar->setValue(vbar->maximum()); - } +void ChatView::scrollTimerTimeout() +{ + // scroll view + QAbstractSlider *vbar = verticalScrollBar(); + if (_scrollOffset < 0 && vbar->value() > 0) + vbar->setValue(qMax(vbar->value() + _scrollOffset, 0)); + else if (_scrollOffset > 0 && vbar->value() < vbar->maximum()) + vbar->setValue(qMin(vbar->value() + _scrollOffset, vbar->maximum())); } -void ChatView::verticalScrollbarChanged(int newPos) { - QAbstractSlider *vbar = verticalScrollBar(); - Q_ASSERT(vbar); - // check for backlog request - if(newPos < _lastScrollbarPos) { - int relativePos = 100; - if(vbar->maximum() - vbar->minimum() != 0) - relativePos = (newPos - vbar->minimum()) * 100 / (vbar->maximum() - vbar->minimum()); +void ChatView::lastLineChanged(QGraphicsItem *chatLine, qreal offset) +{ + Q_UNUSED(chatLine) + // disabled until further testing/discussion + //if(!scene()->isScrollingAllowed()) + // return; + + QAbstractSlider *vbar = verticalScrollBar(); + Q_ASSERT(vbar); + if (vbar->maximum() - vbar->value() <= (offset + 5) * _currentScaleFactor) { // 5px grace area + vbar->setValue(vbar->maximum()); + } +} - if(relativePos < 20) { - scene()->requestBacklog(); + +void ChatView::verticalScrollbarChanged(int newPos) +{ + QAbstractSlider *vbar = verticalScrollBar(); + Q_ASSERT(vbar); + + // check for backlog request + if (newPos < _lastScrollbarPos) { + int relativePos = 100; + if (vbar->maximum() - vbar->minimum() != 0) + relativePos = (newPos - vbar->minimum()) * 100 / (vbar->maximum() - vbar->minimum()); + + if (relativePos < 20) { + scene()->requestBacklog(); + } } - } - _lastScrollbarPos = newPos; + _lastScrollbarPos = newPos; - // FIXME: Fugly workaround for the ChatView scrolling up 1px on buffer switch - if(vbar->maximum() - newPos <= 2) - vbar->setValue(vbar->maximum()); + // FIXME: Fugly workaround for the ChatView scrolling up 1px on buffer switch + if (vbar->maximum() - newPos <= 2) + vbar->setValue(vbar->maximum()); } -MsgId ChatView::lastMsgId() const { - if(!scene()) - return MsgId(); - QAbstractItemModel *model = scene()->model(); - if(!model || model->rowCount() == 0) - return MsgId(); +MsgId ChatView::lastMsgId() const +{ + if (!scene()) + return MsgId(); - return model->index(model->rowCount() - 1, 0).data(MessageModel::MsgIdRole).value(); + QAbstractItemModel *model = scene()->model(); + if (!model || model->rowCount() == 0) + return MsgId(); + + return model->index(model->rowCount() - 1, 0).data(MessageModel::MsgIdRole).value(); } -MsgId ChatView::lastVisibleMsgId() const { - ChatLine *line = lastVisibleChatLine(); - if(line) - return line->msgId(); +MsgId ChatView::lastVisibleMsgId() const +{ + ChatLine *line = lastVisibleChatLine(); + + if (line) + return line->msgId(); - return MsgId(); + return MsgId(); } -bool chatLinePtrLessThan(ChatLine *one, ChatLine *other) { - return one->row() < other->row(); + +bool chatLinePtrLessThan(ChatLine *one, ChatLine *other) +{ + return one->row() < other->row(); } + // TODO: figure out if it's cheaper to use a cached list (that we'd need to keep updated) -QSet ChatView::visibleChatLines(Qt::ItemSelectionMode mode) const { - QSet result; - foreach(QGraphicsItem *item, items(viewport()->rect().adjusted(-1, -1, 1, 1), mode)) { - ChatLine *line = qgraphicsitem_cast(item); - if(line) - result.insert(line); - } - return result; +QSet ChatView::visibleChatLines(Qt::ItemSelectionMode mode) const +{ + QSet result; + foreach(QGraphicsItem *item, items(viewport()->rect().adjusted(-1, -1, 1, 1), mode)) { + ChatLine *line = qgraphicsitem_cast(item); + if (line) + result.insert(line); + } + return result; } -QList ChatView::visibleChatLinesSorted(Qt::ItemSelectionMode mode) const { - QList result = visibleChatLines(mode).toList(); - qSort(result.begin(), result.end(), chatLinePtrLessThan); - return result; + +QList ChatView::visibleChatLinesSorted(Qt::ItemSelectionMode mode) const +{ + QList result = visibleChatLines(mode).toList(); + qSort(result.begin(), result.end(), chatLinePtrLessThan); + return result; } -ChatLine *ChatView::lastVisibleChatLine(bool ignoreDayChange) const { - if(!scene()) - return 0; - QAbstractItemModel *model = scene()->model(); - if(!model || model->rowCount() == 0) - return 0; +ChatLine *ChatView::lastVisibleChatLine(bool ignoreDayChange) const +{ + if (!scene()) + return 0; - int row = -1; + QAbstractItemModel *model = scene()->model(); + if (!model || model->rowCount() == 0) + return 0; - QSet visibleLines = visibleChatLines(Qt::ContainsItemBoundingRect); - foreach(ChatLine *line, visibleLines) { - if(line->row() > row && (ignoreDayChange? line->msgType() != Message::DayChange : true)) - row = line->row(); - } + int row = -1; - if(row >= 0) - return scene()->chatLine(row); + QSet visibleLines = visibleChatLines(Qt::ContainsItemBoundingRect); + foreach(ChatLine *line, visibleLines) { + if (line->row() > row && (ignoreDayChange ? line->msgType() != Message::DayChange : true)) + row = line->row(); + } - return 0; + if (row >= 0) + return scene()->chatLine(row); + + return 0; } -void ChatView::setMarkerLineVisible(bool visible) { - scene()->setMarkerLineVisible(visible); + +void ChatView::setMarkerLineVisible(bool visible) +{ + scene()->setMarkerLineVisible(visible); } -void ChatView::setMarkerLine(MsgId msgId) { - if(!scene()->isSingleBufferScene()) - return; - BufferId bufId = scene()->singleBufferId(); - Client::setMarkerLine(bufId, msgId); +void ChatView::setMarkerLine(MsgId msgId) +{ + if (!scene()->isSingleBufferScene()) + return; + + BufferId bufId = scene()->singleBufferId(); + Client::setMarkerLine(bufId, msgId); } -void ChatView::markerLineSet(BufferId buffer, MsgId msgId) { - if(!scene()->isSingleBufferScene() || scene()->singleBufferId() != buffer) - return; - scene()->setMarkerLine(msgId); - scene()->setMarkerLineVisible(true); +void ChatView::markerLineSet(BufferId buffer, MsgId msgId) +{ + if (!scene()->isSingleBufferScene() || scene()->singleBufferId() != buffer) + return; + + scene()->setMarkerLine(msgId); + scene()->setMarkerLineVisible(true); } -void ChatView::jumpToMarkerLine(bool requestBacklog) { - scene()->jumpToMarkerLine(requestBacklog); + +void ChatView::jumpToMarkerLine(bool requestBacklog) +{ + scene()->jumpToMarkerLine(requestBacklog); } -void ChatView::addActionsToMenu(QMenu *menu, const QPointF &pos) { - // zoom actions - BufferWidget *bw = qobject_cast(bufferContainer()); - if(bw) { - bw->addActionsToMenu(menu, pos); - menu->addSeparator(); - } + +void ChatView::addActionsToMenu(QMenu *menu, const QPointF &pos) +{ + // zoom actions + BufferWidget *bw = qobject_cast(bufferContainer()); + if (bw) { + bw->addActionsToMenu(menu, pos); + menu->addSeparator(); + } } -void ChatView::zoomIn() { + +void ChatView::zoomIn() +{ _currentScaleFactor *= 1.2; scale(1.2, 1.2); scene()->setWidth(viewport()->width() / _currentScaleFactor - 2); } -void ChatView::zoomOut() { + +void ChatView::zoomOut() +{ _currentScaleFactor /= 1.2; scale(1 / 1.2, 1 / 1.2); scene()->setWidth(viewport()->width() / _currentScaleFactor - 2); } -void ChatView::zoomOriginal() { + +void ChatView::zoomOriginal() +{ scale(1/_currentScaleFactor, 1/_currentScaleFactor); _currentScaleFactor = 1; scene()->setWidth(viewport()->width() - 2); } -void ChatView::invalidateFilter() { - // if this is the currently selected chatview - // invalidate immediately - if(isVisible()) { - _scene->filter()->invalidateFilter(); - _invalidateFilter = false; - } - // otherwise invalidate whenever the view is shown - else { - _invalidateFilter = true; - } + +void ChatView::invalidateFilter() +{ + // if this is the currently selected chatview + // invalidate immediately + if (isVisible()) { + _scene->filter()->invalidateFilter(); + _invalidateFilter = false; + } + // otherwise invalidate whenever the view is shown + else { + _invalidateFilter = true; + } } -void ChatView::scrollContentsBy(int dx, int dy) { - QGraphicsView::scrollContentsBy(dx, dy); - checkChatLineCaches(); + +void ChatView::scrollContentsBy(int dx, int dy) +{ + QGraphicsView::scrollContentsBy(dx, dy); + checkChatLineCaches(); } -void ChatView::setHasCache(ChatLine *line, bool hasCache) { - if(hasCache) - _linesWithCache.insert(line); - else - _linesWithCache.remove(line); + +void ChatView::setHasCache(ChatLine *line, bool hasCache) +{ + if (hasCache) + _linesWithCache.insert(line); + else + _linesWithCache.remove(line); } -void ChatView::checkChatLineCaches() { - qreal top = mapToScene(viewport()->rect().topLeft()).y() - 10; // some grace area to avoid premature cleaning - qreal bottom = mapToScene(viewport()->rect().bottomRight()).y() + 10; - QSet::iterator iter = _linesWithCache.begin(); - while(iter != _linesWithCache.end()) { - ChatLine *line = *iter; - if(line->pos().y() + line->height() < top || line->pos().y() > bottom) { - line->clearCache(); - iter = _linesWithCache.erase(iter); - } else - ++iter; - } + +void ChatView::checkChatLineCaches() +{ + qreal top = mapToScene(viewport()->rect().topLeft()).y() - 10; // some grace area to avoid premature cleaning + qreal bottom = mapToScene(viewport()->rect().bottomRight()).y() + 10; + QSet::iterator iter = _linesWithCache.begin(); + while (iter != _linesWithCache.end()) { + ChatLine *line = *iter; + if (line->pos().y() + line->height() < top || line->pos().y() > bottom) { + line->clearCache(); + iter = _linesWithCache.erase(iter); + } + else + ++iter; + } } diff --git a/src/qtui/chatview.h b/src/qtui/chatview.h index 51522d23..7607a7d7 100644 --- a/src/qtui/chatview.h +++ b/src/qtui/chatview.h @@ -34,88 +34,89 @@ class ChatScene; class MessageFilter; class QMenu; -class ChatView : public QGraphicsView, public AbstractChatView { - Q_OBJECT +class ChatView : public QGraphicsView, public AbstractChatView +{ + Q_OBJECT public: - ChatView(MessageFilter *, QWidget *parent = 0); - ChatView(BufferId bufferId, QWidget *parent = 0); - - virtual MsgId lastMsgId() const; - virtual MsgId lastVisibleMsgId() const; - inline AbstractBufferContainer *bufferContainer() const { return _bufferContainer; } - inline void setBufferContainer(AbstractBufferContainer *c) { _bufferContainer = c; } - - inline ChatScene *scene() const { return _scene; } - - //! Return a set of ChatLines currently visible in the view - /** \param mode How partially visible ChatLines are handled - * \return A set of visible ChatLines - */ - QSet visibleChatLines(Qt::ItemSelectionMode mode = Qt::ContainsItemBoundingRect) const; - - //! Return a sorted list of ChatLines currently visible in the view - /** \param mode How partially visible ChatLines are handled - * \return A list of visible ChatLines sorted by row - * \note If the order of ChatLines does not matter, use visibleChatLines() instead - */ - QList visibleChatLinesSorted(Qt::ItemSelectionMode mode = Qt::ContainsItemBoundingRect) const; - - //! Return the last fully visible ChatLine in this view - /** Using this method more efficient than calling visibleChatLinesSorted() and taking its last element. - * \return The last fully visible ChatLine in the view - */ - ChatLine *lastVisibleChatLine(bool ignoreDayChange = false) const; - - virtual void addActionsToMenu(QMenu *, const QPointF &pos); - - //! Tell the view that this ChatLine has cached data - /** ChatLines cache some layout data that should be cleared as soon as it's no - * longer visible. A ChatLine caching data registers itself with this method to - * tell the view about it. The view will call ChatLine::clearCache() when - * appropriate. - * \param line The ChatLine having cached data - */ - void setHasCache(ChatLine *line, bool hasCache = true); + ChatView(MessageFilter *, QWidget *parent = 0); + ChatView(BufferId bufferId, QWidget *parent = 0); + + virtual MsgId lastMsgId() const; + virtual MsgId lastVisibleMsgId() const; + inline AbstractBufferContainer *bufferContainer() const { return _bufferContainer; } + inline void setBufferContainer(AbstractBufferContainer *c) { _bufferContainer = c; } + + inline ChatScene *scene() const { return _scene; } + + //! Return a set of ChatLines currently visible in the view + /** \param mode How partially visible ChatLines are handled + * \return A set of visible ChatLines + */ + QSet visibleChatLines(Qt::ItemSelectionMode mode = Qt::ContainsItemBoundingRect) const; + + //! Return a sorted list of ChatLines currently visible in the view + /** \param mode How partially visible ChatLines are handled + * \return A list of visible ChatLines sorted by row + * \note If the order of ChatLines does not matter, use visibleChatLines() instead + */ + QList visibleChatLinesSorted(Qt::ItemSelectionMode mode = Qt::ContainsItemBoundingRect) const; + + //! Return the last fully visible ChatLine in this view + /** Using this method more efficient than calling visibleChatLinesSorted() and taking its last element. + * \return The last fully visible ChatLine in the view + */ + ChatLine *lastVisibleChatLine(bool ignoreDayChange = false) const; + + virtual void addActionsToMenu(QMenu *, const QPointF &pos); + + //! Tell the view that this ChatLine has cached data + /** ChatLines cache some layout data that should be cleared as soon as it's no + * longer visible. A ChatLine caching data registers itself with this method to + * tell the view about it. The view will call ChatLine::clearCache() when + * appropriate. + * \param line The ChatLine having cached data + */ + void setHasCache(ChatLine *line, bool hasCache = true); public slots: - inline virtual void clear() {} - void zoomIn(); - void zoomOut(); - void zoomOriginal(); + inline virtual void clear() {} + void zoomIn(); + void zoomOut(); + void zoomOriginal(); - void setMarkerLineVisible(bool visible = true); - void setMarkerLine(MsgId msgId); - void jumpToMarkerLine(bool requestBacklog); + void setMarkerLineVisible(bool visible = true); + void setMarkerLine(MsgId msgId); + void jumpToMarkerLine(bool requestBacklog); protected: - virtual bool event(QEvent *event); - virtual void resizeEvent(QResizeEvent *event); - virtual void scrollContentsBy(int dx, int dy); + virtual bool event(QEvent *event); + virtual void resizeEvent(QResizeEvent *event); + virtual void scrollContentsBy(int dx, int dy); protected slots: - virtual void verticalScrollbarChanged(int); + virtual void verticalScrollbarChanged(int); private slots: - void lastLineChanged(QGraphicsItem *chatLine, qreal offset); - void adjustSceneRect(); - void checkChatLineCaches(); - void mouseMoveWhileSelecting(const QPointF &scenePos); - void scrollTimerTimeout(); - void invalidateFilter(); - void markerLineSet(BufferId buffer, MsgId msg); + void lastLineChanged(QGraphicsItem *chatLine, qreal offset); + void adjustSceneRect(); + void checkChatLineCaches(); + void mouseMoveWhileSelecting(const QPointF &scenePos); + void scrollTimerTimeout(); + void invalidateFilter(); + void markerLineSet(BufferId buffer, MsgId msg); private: - void init(MessageFilter *filter); - - AbstractBufferContainer *_bufferContainer; - ChatScene *_scene; - int _lastScrollbarPos; - qreal _currentScaleFactor; - QTimer _scrollTimer; - int _scrollOffset; - bool _invalidateFilter; - QSet _linesWithCache; + void init(MessageFilter *filter); + + AbstractBufferContainer *_bufferContainer; + ChatScene *_scene; + int _lastScrollbarPos; + qreal _currentScaleFactor; + QTimer _scrollTimer; + int _scrollOffset; + bool _invalidateFilter; + QSet _linesWithCache; }; diff --git a/src/qtui/chatviewsearchbar.cpp b/src/qtui/chatviewsearchbar.cpp index 5dcc1124..dd6d1d92 100644 --- a/src/qtui/chatviewsearchbar.cpp +++ b/src/qtui/chatviewsearchbar.cpp @@ -26,48 +26,54 @@ #include "qtui.h" ChatViewSearchBar::ChatViewSearchBar(QWidget *parent) - : QWidget(parent) + : QWidget(parent) { - ui.setupUi(this); - ui.hideButton->setIcon(BarIcon("dialog-close")); - ui.searchUpButton->setIcon(SmallIcon("go-up")); - ui.searchDownButton->setIcon(SmallIcon("go-down")); - _searchDelayTimer.setSingleShot(true); + ui.setupUi(this); + ui.hideButton->setIcon(BarIcon("dialog-close")); + ui.searchUpButton->setIcon(SmallIcon("go-up")); + ui.searchDownButton->setIcon(SmallIcon("go-down")); + _searchDelayTimer.setSingleShot(true); - layout()->setContentsMargins(0, 0, 0, 0); + layout()->setContentsMargins(0, 0, 0, 0); - hide(); + hide(); - ActionCollection *coll = QtUi::actionCollection("General"); + ActionCollection *coll = QtUi::actionCollection("General"); - QAction *toggleSearchBar = coll->action("ToggleSearchBar"); - connect(toggleSearchBar, SIGNAL(toggled(bool)), SLOT(setVisible(bool))); + QAction *toggleSearchBar = coll->action("ToggleSearchBar"); + connect(toggleSearchBar, SIGNAL(toggled(bool)), SLOT(setVisible(bool))); - Action *hideSearchBar = coll->add("HideSearchBar", toggleSearchBar, SLOT(setChecked(bool))); - hideSearchBar->setShortcutConfigurable(false); - hideSearchBar->setShortcut(Qt::Key_Escape); + Action *hideSearchBar = coll->add("HideSearchBar", toggleSearchBar, SLOT(setChecked(bool))); + hideSearchBar->setShortcutConfigurable(false); + hideSearchBar->setShortcut(Qt::Key_Escape); - connect(ui.hideButton, SIGNAL(clicked()), toggleSearchBar, SLOT(toggle())); - connect(ui.searchEditLine, SIGNAL(textChanged(const QString &)), this, SLOT(delaySearch())); - connect(&_searchDelayTimer, SIGNAL(timeout()), this, SLOT(search())); + connect(ui.hideButton, SIGNAL(clicked()), toggleSearchBar, SLOT(toggle())); + connect(ui.searchEditLine, SIGNAL(textChanged(const QString &)), this, SLOT(delaySearch())); + connect(&_searchDelayTimer, SIGNAL(timeout()), this, SLOT(search())); } -void ChatViewSearchBar::setVisible(bool visible) { - // clearing the search field also removes the highlight items from the scene - // this should be done before the SearchBar is hidden, as the hiding triggers - // a resize event which can lead to strange side effects. - ui.searchEditLine->clear(); - QWidget::setVisible(visible); - if(visible) - ui.searchEditLine->setFocus(); - else - emit hidden(); + +void ChatViewSearchBar::setVisible(bool visible) +{ + // clearing the search field also removes the highlight items from the scene + // this should be done before the SearchBar is hidden, as the hiding triggers + // a resize event which can lead to strange side effects. + ui.searchEditLine->clear(); + QWidget::setVisible(visible); + if (visible) + ui.searchEditLine->setFocus(); + else + emit hidden(); } -void ChatViewSearchBar::delaySearch() { - _searchDelayTimer.start(300); + +void ChatViewSearchBar::delaySearch() +{ + _searchDelayTimer.start(300); } -void ChatViewSearchBar::search() { - emit searchChanged(ui.searchEditLine->text()); + +void ChatViewSearchBar::search() +{ + emit searchChanged(ui.searchEditLine->text()); } diff --git a/src/qtui/chatviewsearchbar.h b/src/qtui/chatviewsearchbar.h index d0068b92..c6ab053b 100644 --- a/src/qtui/chatviewsearchbar.h +++ b/src/qtui/chatviewsearchbar.h @@ -28,34 +28,36 @@ class QAction; -class ChatViewSearchBar : public QWidget { - Q_OBJECT +class ChatViewSearchBar : public QWidget +{ + Q_OBJECT public: - ChatViewSearchBar(QWidget *parent = 0); + ChatViewSearchBar(QWidget *parent = 0); - inline QLineEdit *searchEditLine() const { return ui.searchEditLine; } - inline QCheckBox *caseSensitiveBox() const { return ui.caseSensitiveBox; } - inline QCheckBox *searchSendersBox() const { return ui.searchSendersBox; } - inline QCheckBox *searchMsgsBox() const { return ui.searchMsgsBox; } - inline QCheckBox *searchOnlyRegularMsgsBox() const { return ui.searchOnlyRegularMsgsBox; } - inline QToolButton *searchUpButton() const { return ui.searchUpButton; } - inline QToolButton *searchDownButton() const { return ui.searchDownButton; } + inline QLineEdit *searchEditLine() const { return ui.searchEditLine; } + inline QCheckBox *caseSensitiveBox() const { return ui.caseSensitiveBox; } + inline QCheckBox *searchSendersBox() const { return ui.searchSendersBox; } + inline QCheckBox *searchMsgsBox() const { return ui.searchMsgsBox; } + inline QCheckBox *searchOnlyRegularMsgsBox() const { return ui.searchOnlyRegularMsgsBox; } + inline QToolButton *searchUpButton() const { return ui.searchUpButton; } + inline QToolButton *searchDownButton() const { return ui.searchDownButton; } public slots: - void setVisible(bool); + void setVisible(bool); signals: - void searchChanged(const QString &); - void hidden(); + void searchChanged(const QString &); + void hidden(); private slots: - void delaySearch(); - void search(); + void delaySearch(); + void search(); private: - Ui::ChatViewSearchBar ui; - QTimer _searchDelayTimer; + Ui::ChatViewSearchBar ui; + QTimer _searchDelayTimer; }; + #endif //CHATVIEWSEARCHBAR_H diff --git a/src/qtui/chatviewsearchcontroller.cpp b/src/qtui/chatviewsearchcontroller.cpp index ba1dcf36..1c01f699 100644 --- a/src/qtui/chatviewsearchcontroller.cpp +++ b/src/qtui/chatviewsearchcontroller.cpp @@ -30,7 +30,7 @@ #include "messagemodel.h" ChatViewSearchController::ChatViewSearchController(QObject *parent) - : QObject(parent), + : QObject(parent), _scene(0), _currentHighlight(0), _caseSensitive(false), @@ -40,319 +40,354 @@ ChatViewSearchController::ChatViewSearchController(QObject *parent) { } -void ChatViewSearchController::setSearchString(const QString &searchString) { - QString oldSearchString = _searchString; - _searchString = searchString; - if(_scene) { - if(!searchString.startsWith(oldSearchString) || oldSearchString.isEmpty()) { - // we can't reuse our all findings... cler the scene and do it all over - updateHighlights(); - } else { - // reuse all findings - updateHighlights(true); + +void ChatViewSearchController::setSearchString(const QString &searchString) +{ + QString oldSearchString = _searchString; + _searchString = searchString; + if (_scene) { + if (!searchString.startsWith(oldSearchString) || oldSearchString.isEmpty()) { + // we can't reuse our all findings... cler the scene and do it all over + updateHighlights(); + } + else { + // reuse all findings + updateHighlights(true); + } } - } } - void ChatViewSearchController::setScene(ChatScene *scene) { - Q_ASSERT(scene); - if(scene == _scene) - return; - if(_scene) { - disconnect(_scene, 0, this, 0); - disconnect(Client::messageModel(), 0, this, 0); - qDeleteAll(_highlightItems); - _highlightItems.clear(); - } - - _scene = scene; - if(!scene) - return; - - connect(_scene, SIGNAL(destroyed()), this, SLOT(sceneDestroyed())); - connect(_scene, SIGNAL(layoutChanged()), this, SLOT(repositionHighlights())); - connect(Client::messageModel(), SIGNAL(finishedBacklogFetch(BufferId)), this, SLOT(updateHighlights())); - updateHighlights(); - } - -void ChatViewSearchController::highlightNext() { - if(_highlightItems.isEmpty()) - return; - - if(_currentHighlight < _highlightItems.count()) { - _highlightItems.at(_currentHighlight)->setHighlighted(false); - } - - _currentHighlight++; - if(_currentHighlight >= _highlightItems.count()) - _currentHighlight = 0; - _highlightItems.at(_currentHighlight)->setHighlighted(true); - emit newCurrentHighlight(_highlightItems.at(_currentHighlight)); +void ChatViewSearchController::setScene(ChatScene *scene) +{ + Q_ASSERT(scene); + if (scene == _scene) + return; + + if (_scene) { + disconnect(_scene, 0, this, 0); + disconnect(Client::messageModel(), 0, this, 0); + qDeleteAll(_highlightItems); + _highlightItems.clear(); + } + + _scene = scene; + if (!scene) + return; + + connect(_scene, SIGNAL(destroyed()), this, SLOT(sceneDestroyed())); + connect(_scene, SIGNAL(layoutChanged()), this, SLOT(repositionHighlights())); + connect(Client::messageModel(), SIGNAL(finishedBacklogFetch(BufferId)), this, SLOT(updateHighlights())); + updateHighlights(); } -void ChatViewSearchController::highlightPrev() { - if(_highlightItems.isEmpty()) - return; - if(_currentHighlight < _highlightItems.count()) { - _highlightItems.at(_currentHighlight)->setHighlighted(false); - } +void ChatViewSearchController::highlightNext() +{ + if (_highlightItems.isEmpty()) + return; + + if (_currentHighlight < _highlightItems.count()) { + _highlightItems.at(_currentHighlight)->setHighlighted(false); + } - _currentHighlight--; - if(_currentHighlight < 0) - _currentHighlight = _highlightItems.count() - 1; - _highlightItems.at(_currentHighlight)->setHighlighted(true); - emit newCurrentHighlight(_highlightItems.at(_currentHighlight)); + _currentHighlight++; + if (_currentHighlight >= _highlightItems.count()) + _currentHighlight = 0; + _highlightItems.at(_currentHighlight)->setHighlighted(true); + emit newCurrentHighlight(_highlightItems.at(_currentHighlight)); } -void ChatViewSearchController::updateHighlights(bool reuse) { - if(!_scene) - return; - if(reuse) { - QSet chatLines; - foreach(SearchHighlightItem *highlightItem, _highlightItems) { - ChatLine *line = qgraphicsitem_cast(highlightItem->parentItem()); - if(line) - chatLines << line; - } - foreach(ChatLine *line, QList(chatLines.toList())) { - updateHighlights(line); +void ChatViewSearchController::highlightPrev() +{ + if (_highlightItems.isEmpty()) + return; + + if (_currentHighlight < _highlightItems.count()) { + _highlightItems.at(_currentHighlight)->setHighlighted(false); } - } else { - QPointF oldHighlightPos; - if(!_highlightItems.isEmpty() && _currentHighlight < _highlightItems.count()) { - oldHighlightPos = _highlightItems[_currentHighlight]->scenePos(); + + _currentHighlight--; + if (_currentHighlight < 0) + _currentHighlight = _highlightItems.count() - 1; + _highlightItems.at(_currentHighlight)->setHighlighted(true); + emit newCurrentHighlight(_highlightItems.at(_currentHighlight)); +} + + +void ChatViewSearchController::updateHighlights(bool reuse) +{ + if (!_scene) + return; + + if (reuse) { + QSet chatLines; + foreach(SearchHighlightItem *highlightItem, _highlightItems) { + ChatLine *line = qgraphicsitem_cast(highlightItem->parentItem()); + if (line) + chatLines << line; + } + foreach(ChatLine *line, QList(chatLines.toList())) { + updateHighlights(line); + } } - qDeleteAll(_highlightItems); - _highlightItems.clear(); - Q_ASSERT(_highlightItems.isEmpty()); - - if(searchString().isEmpty() || !(_searchSenders || _searchMsgs)) - return; - - checkMessagesForHighlight(); - - if(!_highlightItems.isEmpty()) { - if(!oldHighlightPos.isNull()) { - int start = 0; int end = _highlightItems.count() - 1; - QPointF startPos; - QPointF endPos; - while(1) { - startPos = _highlightItems[start]->scenePos(); - endPos = _highlightItems[end]->scenePos(); - if(startPos == oldHighlightPos) { - _currentHighlight = start; - break; - } - if(endPos == oldHighlightPos) { - _currentHighlight = end; - break; - } - if(end - start == 1) { - _currentHighlight = start; - break; - } - int pivot = (end + start) / 2; - QPointF pivotPos = _highlightItems[pivot]->scenePos(); - if(startPos.y() == endPos.y()) { - if(oldHighlightPos.x() <= pivotPos.x()) - end = pivot; - else - start = pivot; - } else { - if(oldHighlightPos.y() <= pivotPos.y()) - end = pivot; - else - start = pivot; - } + else { + QPointF oldHighlightPos; + if (!_highlightItems.isEmpty() && _currentHighlight < _highlightItems.count()) { + oldHighlightPos = _highlightItems[_currentHighlight]->scenePos(); + } + qDeleteAll(_highlightItems); + _highlightItems.clear(); + Q_ASSERT(_highlightItems.isEmpty()); + + if (searchString().isEmpty() || !(_searchSenders || _searchMsgs)) + return; + + checkMessagesForHighlight(); + + if (!_highlightItems.isEmpty()) { + if (!oldHighlightPos.isNull()) { + int start = 0; int end = _highlightItems.count() - 1; + QPointF startPos; + QPointF endPos; + while (1) { + startPos = _highlightItems[start]->scenePos(); + endPos = _highlightItems[end]->scenePos(); + if (startPos == oldHighlightPos) { + _currentHighlight = start; + break; + } + if (endPos == oldHighlightPos) { + _currentHighlight = end; + break; + } + if (end - start == 1) { + _currentHighlight = start; + break; + } + int pivot = (end + start) / 2; + QPointF pivotPos = _highlightItems[pivot]->scenePos(); + if (startPos.y() == endPos.y()) { + if (oldHighlightPos.x() <= pivotPos.x()) + end = pivot; + else + start = pivot; + } + else { + if (oldHighlightPos.y() <= pivotPos.y()) + end = pivot; + else + start = pivot; + } + } + } + else { + _currentHighlight = _highlightItems.count() - 1; + } + _highlightItems[_currentHighlight]->setHighlighted(true); + emit newCurrentHighlight(_highlightItems[_currentHighlight]); } - } else { - _currentHighlight = _highlightItems.count() - 1; - } - _highlightItems[_currentHighlight]->setHighlighted(true); - emit newCurrentHighlight(_highlightItems[_currentHighlight]); } - } } -void ChatViewSearchController::checkMessagesForHighlight(int start, int end) { - QAbstractItemModel *model = _scene->model(); - Q_ASSERT(model); - - if(end == -1) { - end = model->rowCount() - 1; - if(end == -1) - return; - } - - QModelIndex index; - for(int row = start; row <= end; row++) { - if(_searchOnlyRegularMsgs) { - index = model->index(row, 0); - if(!checkType((Message::Type)index.data(MessageModel::TypeRole).toInt())) - continue; + +void ChatViewSearchController::checkMessagesForHighlight(int start, int end) +{ + QAbstractItemModel *model = _scene->model(); + Q_ASSERT(model); + + if (end == -1) { + end = model->rowCount() - 1; + if (end == -1) + return; + } + + QModelIndex index; + for (int row = start; row <= end; row++) { + if (_searchOnlyRegularMsgs) { + index = model->index(row, 0); + if (!checkType((Message::Type)index.data(MessageModel::TypeRole).toInt())) + continue; + } + highlightLine(_scene->chatLine(row)); } - highlightLine(_scene->chatLine(row)); - } } -void ChatViewSearchController::updateHighlights(ChatLine *line) { - QList checkItems; - if(_searchSenders) - checkItems << line->item(MessageModel::SenderColumn); - if(_searchMsgs) - checkItems << line->item(MessageModel::ContentsColumn); +void ChatViewSearchController::updateHighlights(ChatLine *line) +{ + QList checkItems; + if (_searchSenders) + checkItems << line->item(MessageModel::SenderColumn); + + if (_searchMsgs) + checkItems << line->item(MessageModel::ContentsColumn); - QHash > wordRects; - foreach(ChatItem *item, checkItems) { - foreach(QRectF wordRect, item->findWords(searchString(), caseSensitive())) { - wordRects[(quint64)(wordRect.x() + item->x())][(quint64)(wordRect.y())] = wordRect; + QHash > wordRects; + foreach(ChatItem *item, checkItems) { + foreach(QRectF wordRect, item->findWords(searchString(), caseSensitive())) { + wordRects[(quint64)(wordRect.x() + item->x())][(quint64)(wordRect.y())] = wordRect; + } + } + + bool deleteAll = false; + QAbstractItemModel *model = _scene->model(); + Q_ASSERT(model); + if (_searchOnlyRegularMsgs) { + QModelIndex index = model->index(line->row(), 0); + if (!checkType((Message::Type)index.data(MessageModel::TypeRole).toInt())) + deleteAll = true; } - } - - bool deleteAll = false; - QAbstractItemModel *model = _scene->model(); - Q_ASSERT(model); - if(_searchOnlyRegularMsgs) { - QModelIndex index = model->index(line->row(), 0); - if(!checkType((Message::Type)index.data(MessageModel::TypeRole).toInt())) - deleteAll = true; - } - - - foreach(QGraphicsItem *child, line->childItems()) { - SearchHighlightItem *highlightItem = qgraphicsitem_cast(child); - if(!highlightItem) - continue; - - if(!deleteAll && wordRects.contains((quint64)(highlightItem->pos().x())) && wordRects[(quint64)(highlightItem->pos().x())].contains((quint64)(highlightItem->pos().y()))) { - QRectF &wordRect = wordRects[(quint64)(highlightItem->pos().x())][(quint64)(highlightItem->pos().y())]; - highlightItem->updateGeometry(wordRect.width(), wordRect.height()); - } else { - int pos = _highlightItems.indexOf(highlightItem); - if(pos == _currentHighlight) { - highlightPrev(); - } else if (pos < _currentHighlight) { - _currentHighlight--; - } - - _highlightItems.removeAt(pos); - delete highlightItem; + + foreach(QGraphicsItem *child, line->childItems()) { + SearchHighlightItem *highlightItem = qgraphicsitem_cast(child); + if (!highlightItem) + continue; + + if (!deleteAll && wordRects.contains((quint64)(highlightItem->pos().x())) && wordRects[(quint64)(highlightItem->pos().x())].contains((quint64)(highlightItem->pos().y()))) { + QRectF &wordRect = wordRects[(quint64)(highlightItem->pos().x())][(quint64)(highlightItem->pos().y())]; + highlightItem->updateGeometry(wordRect.width(), wordRect.height()); + } + else { + int pos = _highlightItems.indexOf(highlightItem); + if (pos == _currentHighlight) { + highlightPrev(); + } + else if (pos < _currentHighlight) { + _currentHighlight--; + } + + _highlightItems.removeAt(pos); + delete highlightItem; + } } - } } -void ChatViewSearchController::highlightLine(ChatLine *line) { - QList checkItems; - if(_searchSenders) - checkItems << line->item(MessageModel::SenderColumn); - if(_searchMsgs) - checkItems << line->item(MessageModel::ContentsColumn); +void ChatViewSearchController::highlightLine(ChatLine *line) +{ + QList checkItems; + if (_searchSenders) + checkItems << line->item(MessageModel::SenderColumn); + + if (_searchMsgs) + checkItems << line->item(MessageModel::ContentsColumn); - foreach(ChatItem *item, checkItems) { - foreach(QRectF wordRect, item->findWords(searchString(), caseSensitive())) { - _highlightItems << new SearchHighlightItem(wordRect.adjusted(item->x(), 0, item->x(), 0), line); + foreach(ChatItem *item, checkItems) { + foreach(QRectF wordRect, item->findWords(searchString(), caseSensitive())) { + _highlightItems << new SearchHighlightItem(wordRect.adjusted(item->x(), 0, item->x(), 0), line); + } } - } } -void ChatViewSearchController::repositionHighlights() { - QSet chatLines; - foreach(SearchHighlightItem *item, _highlightItems) { - ChatLine *line = qgraphicsitem_cast(item->parentItem()); - if(line) - chatLines << line; - } - QList chatLineList(chatLines.toList()); - foreach(ChatLine *line, chatLineList) { - repositionHighlights(line); - } + +void ChatViewSearchController::repositionHighlights() +{ + QSet chatLines; + foreach(SearchHighlightItem *item, _highlightItems) { + ChatLine *line = qgraphicsitem_cast(item->parentItem()); + if (line) + chatLines << line; + } + QList chatLineList(chatLines.toList()); + foreach(ChatLine *line, chatLineList) { + repositionHighlights(line); + } } -void ChatViewSearchController::repositionHighlights(ChatLine *line) { - QList searchHighlights; - foreach(QGraphicsItem *child, line->childItems()) { - SearchHighlightItem *highlightItem = qgraphicsitem_cast(child); - if(highlightItem) - searchHighlights << highlightItem; - } - - if(searchHighlights.isEmpty()) - return; - - QList wordPos; - if(_searchSenders) { - foreach(QRectF wordRect, line->senderItem()->findWords(searchString(), caseSensitive())) { - wordPos << QPointF(wordRect.x() + line->senderItem()->x(), wordRect.y()); + +void ChatViewSearchController::repositionHighlights(ChatLine *line) +{ + QList searchHighlights; + foreach(QGraphicsItem *child, line->childItems()) { + SearchHighlightItem *highlightItem = qgraphicsitem_cast(child); + if (highlightItem) + searchHighlights << highlightItem; + } + + if (searchHighlights.isEmpty()) + return; + + QList wordPos; + if (_searchSenders) { + foreach(QRectF wordRect, line->senderItem()->findWords(searchString(), caseSensitive())) { + wordPos << QPointF(wordRect.x() + line->senderItem()->x(), wordRect.y()); + } } - } - if(_searchMsgs) { - foreach(QRectF wordRect, line->contentsItem()->findWords(searchString(), caseSensitive())) { - wordPos << QPointF(wordRect.x() + line->contentsItem()->x(), wordRect.y()); + if (_searchMsgs) { + foreach(QRectF wordRect, line->contentsItem()->findWords(searchString(), caseSensitive())) { + wordPos << QPointF(wordRect.x() + line->contentsItem()->x(), wordRect.y()); + } } - } - qSort(searchHighlights.begin(), searchHighlights.end(), SearchHighlightItem::firstInLine); + qSort(searchHighlights.begin(), searchHighlights.end(), SearchHighlightItem::firstInLine); - Q_ASSERT(wordPos.count() == searchHighlights.count()); - for(int i = 0; i < searchHighlights.count(); i++) { - searchHighlights.at(i)->setPos(wordPos.at(i)); - } + Q_ASSERT(wordPos.count() == searchHighlights.count()); + for (int i = 0; i < searchHighlights.count(); i++) { + searchHighlights.at(i)->setPos(wordPos.at(i)); + } } -void ChatViewSearchController::sceneDestroyed() { - // WARNING: don't call any methods on scene! - _scene = 0; - // the items will be automatically deleted when the scene is destroyed - // so we just have to clear the list; - _highlightItems.clear(); + +void ChatViewSearchController::sceneDestroyed() +{ + // WARNING: don't call any methods on scene! + _scene = 0; + // the items will be automatically deleted when the scene is destroyed + // so we just have to clear the list; + _highlightItems.clear(); } -void ChatViewSearchController::setCaseSensitive(bool caseSensitive) { - if(_caseSensitive == caseSensitive) - return; - _caseSensitive = caseSensitive; +void ChatViewSearchController::setCaseSensitive(bool caseSensitive) +{ + if (_caseSensitive == caseSensitive) + return; - // we can reuse the original search results if the new search - // parameters are a restriction of the original one - updateHighlights(caseSensitive); + _caseSensitive = caseSensitive; + + // we can reuse the original search results if the new search + // parameters are a restriction of the original one + updateHighlights(caseSensitive); } -void ChatViewSearchController::setSearchSenders(bool searchSenders) { - if(_searchSenders == searchSenders) - return; - _searchSenders = searchSenders; - // we can reuse the original search results if the new search - // parameters are a restriction of the original one - updateHighlights(!searchSenders); +void ChatViewSearchController::setSearchSenders(bool searchSenders) +{ + if (_searchSenders == searchSenders) + return; + + _searchSenders = searchSenders; + // we can reuse the original search results if the new search + // parameters are a restriction of the original one + updateHighlights(!searchSenders); } -void ChatViewSearchController::setSearchMsgs(bool searchMsgs) { - if(_searchMsgs == searchMsgs) - return; - _searchMsgs = searchMsgs; +void ChatViewSearchController::setSearchMsgs(bool searchMsgs) +{ + if (_searchMsgs == searchMsgs) + return; + + _searchMsgs = searchMsgs; - // we can reuse the original search results if the new search - // parameters are a restriction of the original one - updateHighlights(!searchMsgs); + // we can reuse the original search results if the new search + // parameters are a restriction of the original one + updateHighlights(!searchMsgs); } -void ChatViewSearchController::setSearchOnlyRegularMsgs(bool searchOnlyRegularMsgs) { - if(_searchOnlyRegularMsgs == searchOnlyRegularMsgs) - return; - _searchOnlyRegularMsgs = searchOnlyRegularMsgs; +void ChatViewSearchController::setSearchOnlyRegularMsgs(bool searchOnlyRegularMsgs) +{ + if (_searchOnlyRegularMsgs == searchOnlyRegularMsgs) + return; + + _searchOnlyRegularMsgs = searchOnlyRegularMsgs; - // we can reuse the original search results if the new search - // parameters are a restriction of the original one - updateHighlights(searchOnlyRegularMsgs); + // we can reuse the original search results if the new search + // parameters are a restriction of the original one + updateHighlights(searchOnlyRegularMsgs); } @@ -360,58 +395,68 @@ void ChatViewSearchController::setSearchOnlyRegularMsgs(bool searchOnlyRegularMs // SearchHighlightItem // ================================================== SearchHighlightItem::SearchHighlightItem(QRectF wordRect, QGraphicsItem *parent) - : QObject(), + : QObject(), QGraphicsItem(parent), _highlighted(false), _alpha(70), _timeLine(150) { - setPos(wordRect.x(), wordRect.y()); - updateGeometry(wordRect.width(), wordRect.height()); + setPos(wordRect.x(), wordRect.y()); + updateGeometry(wordRect.width(), wordRect.height()); - connect(&_timeLine, SIGNAL(valueChanged(qreal)), this, SLOT(updateHighlight(qreal))); + connect(&_timeLine, SIGNAL(valueChanged(qreal)), this, SLOT(updateHighlight(qreal))); } -void SearchHighlightItem::setHighlighted(bool highlighted) { - _highlighted = highlighted; - if(highlighted) - _timeLine.setDirection(QTimeLine::Forward); - else - _timeLine.setDirection(QTimeLine::Backward); +void SearchHighlightItem::setHighlighted(bool highlighted) +{ + _highlighted = highlighted; + + if (highlighted) + _timeLine.setDirection(QTimeLine::Forward); + else + _timeLine.setDirection(QTimeLine::Backward); - if(_timeLine.state() != QTimeLine::Running) - _timeLine.start(); + if (_timeLine.state() != QTimeLine::Running) + _timeLine.start(); - update(); + update(); } -void SearchHighlightItem::updateHighlight(qreal value) { - _alpha = 70 + (int)(80 * value); - update(); + +void SearchHighlightItem::updateHighlight(qreal value) +{ + _alpha = 70 + (int)(80 * value); + update(); } -void SearchHighlightItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { - Q_UNUSED(option); - Q_UNUSED(widget); - painter->setPen(QPen(QColor(0, 0, 0), 1.5)); - painter->setBrush(QColor(254, 237, 45, _alpha)); - painter->setRenderHints(QPainter::Antialiasing); - qreal radius = boundingRect().height() * 0.30; - painter->drawRoundedRect(boundingRect(), radius, radius); +void SearchHighlightItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(option); + Q_UNUSED(widget); + + painter->setPen(QPen(QColor(0, 0, 0), 1.5)); + painter->setBrush(QColor(254, 237, 45, _alpha)); + painter->setRenderHints(QPainter::Antialiasing); + qreal radius = boundingRect().height() * 0.30; + painter->drawRoundedRect(boundingRect(), radius, radius); } -void SearchHighlightItem::updateGeometry(qreal width, qreal height) { - prepareGeometryChange(); - qreal sizedelta = height * 0.1; - _boundingRect = QRectF(-sizedelta, -sizedelta, width + 2 * sizedelta, height + 2 * sizedelta); - update(); + +void SearchHighlightItem::updateGeometry(qreal width, qreal height) +{ + prepareGeometryChange(); + qreal sizedelta = height * 0.1; + _boundingRect = QRectF(-sizedelta, -sizedelta, width + 2 * sizedelta, height + 2 * sizedelta); + update(); } -bool SearchHighlightItem::firstInLine(QGraphicsItem *item1, QGraphicsItem *item2) { - if(item1->pos().y() != item2->pos().y()) - return item1->pos().y() < item2->pos().y(); - else - return item1->pos().x() < item2->pos().x(); + +bool SearchHighlightItem::firstInLine(QGraphicsItem *item1, QGraphicsItem *item2) +{ + if (item1->pos().y() != item2->pos().y()) + return item1->pos().y() < item2->pos().y(); + else + return item1->pos().x() < item2->pos().x(); } diff --git a/src/qtui/chatviewsearchcontroller.h b/src/qtui/chatviewsearchcontroller.h index 757bd22f..3e5d3bfd 100644 --- a/src/qtui/chatviewsearchcontroller.h +++ b/src/qtui/chatviewsearchcontroller.h @@ -34,86 +34,89 @@ class QGraphicsItem; class ChatLine; class SearchHighlightItem; -class ChatViewSearchController : public QObject { - Q_OBJECT +class ChatViewSearchController : public QObject +{ + Q_OBJECT public: - ChatViewSearchController(QObject *parent = 0); + ChatViewSearchController(QObject *parent = 0); - inline const QString &searchString() const { return _searchString; } + inline const QString &searchString() const { return _searchString; } - void setScene(ChatScene *scene); + void setScene(ChatScene *scene); public slots: - void setSearchString(const QString &searchString); - void setCaseSensitive(bool caseSensitive); - void setSearchSenders(bool searchSenders); - void setSearchMsgs(bool searchMsgs); - void setSearchOnlyRegularMsgs(bool searchOnlyRegularMsgs); + void setSearchString(const QString &searchString); + void setCaseSensitive(bool caseSensitive); + void setSearchSenders(bool searchSenders); + void setSearchMsgs(bool searchMsgs); + void setSearchOnlyRegularMsgs(bool searchOnlyRegularMsgs); - void highlightNext(); - void highlightPrev(); + void highlightNext(); + void highlightPrev(); private slots: - void sceneDestroyed(); - void updateHighlights(bool reuse = false); + void sceneDestroyed(); + void updateHighlights(bool reuse = false); - void repositionHighlights(); - void repositionHighlights(ChatLine *line); + void repositionHighlights(); + void repositionHighlights(ChatLine *line); signals: - void newCurrentHighlight(QGraphicsItem *highlightItem); + void newCurrentHighlight(QGraphicsItem *highlightItem); private: - QString _searchString; - ChatScene *_scene; - QList _highlightItems; - int _currentHighlight; + QString _searchString; + ChatScene *_scene; + QList _highlightItems; + int _currentHighlight; - bool _caseSensitive; - bool _searchSenders; - bool _searchMsgs; - bool _searchOnlyRegularMsgs; + bool _caseSensitive; + bool _searchSenders; + bool _searchMsgs; + bool _searchOnlyRegularMsgs; - inline Qt::CaseSensitivity caseSensitive() const { return _caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive; } + inline Qt::CaseSensitivity caseSensitive() const { return _caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive; } - inline bool checkType(Message::Type type) const { return type & (Message::Plain | Message::Notice | Message::Action); } + inline bool checkType(Message::Type type) const { return type & (Message::Plain | Message::Notice | Message::Action); } - void checkMessagesForHighlight(int start = 0, int end = -1); - void highlightLine(ChatLine *line); - void updateHighlights(ChatLine *line); + void checkMessagesForHighlight(int start = 0, int end = -1); + void highlightLine(ChatLine *line); + void updateHighlights(ChatLine *line); }; // Highlight Items #include -class SearchHighlightItem : public QObject, public QGraphicsItem { - Q_OBJECT +class SearchHighlightItem : public QObject, public QGraphicsItem +{ + Q_OBJECT #if QT_VERSION >= 0x040600 - Q_INTERFACES(QGraphicsItem) + Q_INTERFACES(QGraphicsItem) #endif -public: - SearchHighlightItem(QRectF wordRect, QGraphicsItem *parent = 0); - virtual inline QRectF boundingRect() const { return _boundingRect; } - void updateGeometry(qreal width, qreal height); - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - enum { Type = ChatScene::SearchHighlightType }; - virtual inline int type() const { return Type; } +public : + SearchHighlightItem(QRectF wordRect, QGraphicsItem *parent = 0); + virtual inline QRectF boundingRect() const { return _boundingRect; } + void updateGeometry(qreal width, qreal height); + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); + enum { Type = ChatScene::SearchHighlightType }; + virtual inline int type() const { return Type; } - void setHighlighted(bool highlighted); + void setHighlighted(bool highlighted); - static bool firstInLine(QGraphicsItem *item1, QGraphicsItem *item2); + static bool firstInLine(QGraphicsItem *item1, QGraphicsItem *item2); private slots: - void updateHighlight(qreal value); + void updateHighlight(qreal value); private: - QRectF _boundingRect; - bool _highlighted; - int _alpha; - QTimeLine _timeLine; + QRectF _boundingRect; + bool _highlighted; + int _alpha; + QTimeLine _timeLine; }; + #endif //CHATVIEWSEARCHCONTROLLER_H diff --git a/src/qtui/chatviewsettings.cpp b/src/qtui/chatviewsettings.cpp index fee9de4e..97c16a3f 100644 --- a/src/qtui/chatviewsettings.cpp +++ b/src/qtui/chatviewsettings.cpp @@ -24,17 +24,18 @@ #include "chatview.h" ChatViewSettings::ChatViewSettings(const QString &id) - : QtUiSettings(QString("ChatView/%1").arg(id)) + : QtUiSettings(QString("ChatView/%1").arg(id)) { } + ChatViewSettings::ChatViewSettings(ChatScene *scene) - : QtUiSettings(QString("ChatView/%1").arg(scene->idString())) + : QtUiSettings(QString("ChatView/%1").arg(scene->idString())) { } + ChatViewSettings::ChatViewSettings(ChatView *view) - : QtUiSettings(QString("ChatView/%1").arg(view->scene()->idString())) + : QtUiSettings(QString("ChatView/%1").arg(view->scene()->idString())) { } - diff --git a/src/qtui/chatviewsettings.h b/src/qtui/chatviewsettings.h index ef5f4d38..248b06ee 100644 --- a/src/qtui/chatviewsettings.h +++ b/src/qtui/chatviewsettings.h @@ -26,26 +26,29 @@ class ChatScene; class ChatView; -class ChatViewSettings : public QtUiSettings { +class ChatViewSettings : public QtUiSettings +{ +public: + Q_ENUMS(OperationMode) public: - Q_ENUMS(OperationMode) - public: enum OperationMode { - InvalidMode = 0, - OptIn = 1, - OptOut = 2 + InvalidMode = 0, + OptIn = 1, + OptOut = 2 }; - Q_DECLARE_FLAGS(operationModes, OperationMode); + Q_DECLARE_FLAGS(operationModes, OperationMode); - ChatViewSettings(const QString &id = "__default__"); - ChatViewSettings(ChatScene *scene); - ChatViewSettings(ChatView *view); + ChatViewSettings(const QString &id = "__default__"); + ChatViewSettings(ChatScene *scene); + ChatViewSettings(ChatView *view); - inline bool showWebPreview() { return localValue("ShowWebPreview", true).toBool(); } - inline void enableWebPreview(bool enabled) { setLocalValue("ShowWebPreview", enabled); } + inline bool showWebPreview() { return localValue("ShowWebPreview", true).toBool(); } + inline void enableWebPreview(bool enabled) { setLocalValue("ShowWebPreview", enabled); } - inline QString timestampFormatString() { return localValue("TimestampFormat", "[hh:mm:ss]").toString(); } - inline void setTimestampFormatString(const QString &format) { setLocalValue("TimestampFormat", format); } + inline QString timestampFormatString() { return localValue("TimestampFormat", "[hh:mm:ss]").toString(); } + inline void setTimestampFormatString(const QString &format) { setLocalValue("TimestampFormat", format); } }; + + Q_DECLARE_METATYPE(ChatViewSettings::OperationMode); #endif //CHATVIEWSETTINGS_H diff --git a/src/qtui/columnhandleitem.cpp b/src/qtui/columnhandleitem.cpp index 6ae191e4..2a5ad2d5 100644 --- a/src/qtui/columnhandleitem.cpp +++ b/src/qtui/columnhandleitem.cpp @@ -28,7 +28,7 @@ #include ColumnHandleItem::ColumnHandleItem(qreal w, QGraphicsItem *parent) - : QGraphicsObject(parent), + : QGraphicsObject(parent), _width(w), _boundingRect(-_width/2, 0, _width, 0), _moving(false), @@ -38,107 +38,129 @@ ColumnHandleItem::ColumnHandleItem(qreal w, QGraphicsItem *parent) _opacity(0), _animation(new QPropertyAnimation(this, "opacity", this)) { + setAcceptsHoverEvents(true); + setZValue(10); + setCursor(QCursor(Qt::OpenHandCursor)); - setAcceptsHoverEvents(true); - setZValue(10); - setCursor(QCursor(Qt::OpenHandCursor)); + _animation->setStartValue(0); + _animation->setEndValue(1); + _animation->setDirection(QPropertyAnimation::Forward); + _animation->setDuration(350); + _animation->setEasingCurve(QEasingCurve::InOutSine); - _animation->setStartValue(0); - _animation->setEndValue(1); - _animation->setDirection(QPropertyAnimation::Forward); - _animation->setDuration(350); - _animation->setEasingCurve(QEasingCurve::InOutSine); - - //connect(&_timeLine, SIGNAL(valueChanged(qreal)), this, SLOT(hoverChanged(qreal))); + //connect(&_timeLine, SIGNAL(valueChanged(qreal)), this, SLOT(hoverChanged(qreal))); } -void ColumnHandleItem::setXPos(qreal xpos) { - setPos(xpos, 0); - QRectF sceneBRect = _boundingRect.translated(x(), 0); - _sceneLeft = sceneBRect.left(); - _sceneRight = sceneBRect.right(); + +void ColumnHandleItem::setXPos(qreal xpos) +{ + setPos(xpos, 0); + QRectF sceneBRect = _boundingRect.translated(x(), 0); + _sceneLeft = sceneBRect.left(); + _sceneRight = sceneBRect.right(); } -void ColumnHandleItem::setXLimits(qreal min, qreal max) { - _minXPos = min; - _maxXPos = max; - //if(x() < min) setPos(min, 0); - //else if(x() > max) setPos(max - width(), 0); + +void ColumnHandleItem::setXLimits(qreal min, qreal max) +{ + _minXPos = min; + _maxXPos = max; + //if(x() < min) setPos(min, 0); + //else if(x() > max) setPos(max - width(), 0); } -void ColumnHandleItem::sceneRectChanged(const QRectF &rect) { - prepareGeometryChange(); - _boundingRect = QRectF(-_width/2, rect.y(), _width, rect.height()); + +void ColumnHandleItem::sceneRectChanged(const QRectF &rect) +{ + prepareGeometryChange(); + _boundingRect = QRectF(-_width/2, rect.y(), _width, rect.height()); } -void ColumnHandleItem::setOpacity(qreal opacity) { - _opacity = opacity; - update(); + +void ColumnHandleItem::setOpacity(qreal opacity) +{ + _opacity = opacity; + update(); } -void ColumnHandleItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { - if(event->buttons() & Qt::LeftButton && _moving) { - qreal newx = event->scenePos().x() - _offset; - if(newx < _minXPos) - newx = _minXPos; - else if(newx + width() > _maxXPos) - newx = _maxXPos - width(); - setPos(newx, 0); - event->accept(); - } else { - event->ignore(); - } + +void ColumnHandleItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + if (event->buttons() & Qt::LeftButton && _moving) { + qreal newx = event->scenePos().x() - _offset; + if (newx < _minXPos) + newx = _minXPos; + else if (newx + width() > _maxXPos) + newx = _maxXPos - width(); + setPos(newx, 0); + event->accept(); + } + else { + event->ignore(); + } } -void ColumnHandleItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { - if(event->buttons() & Qt::LeftButton) { - QApplication::setOverrideCursor(Qt::ClosedHandCursor); - _moving = true; - _offset = event->pos().x(); - event->accept(); - } else { - event->ignore(); - } + +void ColumnHandleItem::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + if (event->buttons() & Qt::LeftButton) { + QApplication::setOverrideCursor(Qt::ClosedHandCursor); + _moving = true; + _offset = event->pos().x(); + event->accept(); + } + else { + event->ignore(); + } } -void ColumnHandleItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { - if(_moving) { - _moving = false; - QRectF sceneBRect = _boundingRect.translated(x(), 0); - _sceneLeft = sceneBRect.left(); - _sceneRight = sceneBRect.right(); - emit positionChanged(x()); - QApplication::restoreOverrideCursor(); - event->accept(); - } else { - event->ignore(); - } + +void ColumnHandleItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + if (_moving) { + _moving = false; + QRectF sceneBRect = _boundingRect.translated(x(), 0); + _sceneLeft = sceneBRect.left(); + _sceneRight = sceneBRect.right(); + emit positionChanged(x()); + QApplication::restoreOverrideCursor(); + event->accept(); + } + else { + event->ignore(); + } } -void ColumnHandleItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { - Q_UNUSED(event); - _animation->setDirection(QPropertyAnimation::Forward); - _animation->start(); +void ColumnHandleItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) +{ + Q_UNUSED(event); + + _animation->setDirection(QPropertyAnimation::Forward); + _animation->start(); } -void ColumnHandleItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { - Q_UNUSED(event); - _animation->setDirection(QPropertyAnimation::Backward); - _animation->start(); +void ColumnHandleItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) +{ + Q_UNUSED(event); + + _animation->setDirection(QPropertyAnimation::Backward); + _animation->start(); } -void ColumnHandleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { - Q_UNUSED(option); - Q_UNUSED(widget); - - QLinearGradient gradient(boundingRect().topLeft(), boundingRect().topRight()); - QColor color = QApplication::palette().windowText().color(); - color.setAlphaF(_opacity); - gradient.setColorAt(0, Qt::transparent); - gradient.setColorAt(0.45, color); - gradient.setColorAt(0.55, color); - gradient.setColorAt(1, Qt::transparent); - painter->fillRect(boundingRect(), gradient); + +void ColumnHandleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(option); + Q_UNUSED(widget); + + QLinearGradient gradient(boundingRect().topLeft(), boundingRect().topRight()); + QColor color = QApplication::palette().windowText().color(); + color.setAlphaF(_opacity); + gradient.setColorAt(0, Qt::transparent); + gradient.setColorAt(0.45, color); + gradient.setColorAt(0.55, color); + gradient.setColorAt(1, Qt::transparent); + painter->fillRect(boundingRect(), gradient); } diff --git a/src/qtui/columnhandleitem.h b/src/qtui/columnhandleitem.h index 67377407..2c5aca5b 100644 --- a/src/qtui/columnhandleitem.h +++ b/src/qtui/columnhandleitem.h @@ -27,49 +27,51 @@ #include "chatscene.h" -class ColumnHandleItem : public QGraphicsObject { - Q_OBJECT - Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity) +class ColumnHandleItem : public QGraphicsObject +{ + Q_OBJECT + Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity) -public: - ColumnHandleItem(qreal width, QGraphicsItem *parent = 0); - virtual inline int type() const { return ChatScene::ColumnHandleType; } +public : + ColumnHandleItem(qreal width, QGraphicsItem *parent = 0); + virtual inline int type() const { return ChatScene::ColumnHandleType; } - inline qreal width() const { return _width; } - inline QRectF boundingRect() const { return _boundingRect; } - inline qreal sceneLeft() const { return _sceneLeft; } - inline qreal sceneRight() const { return _sceneRight; } + inline qreal width() const { return _width; } + inline QRectF boundingRect() const { return _boundingRect; } + inline qreal sceneLeft() const { return _sceneLeft; } + inline qreal sceneRight() const { return _sceneRight; } - inline qreal opacity() const { return _opacity; } + inline qreal opacity() const { return _opacity; } - void setXPos(qreal xpos); - void setXLimits(qreal min, qreal max); + void setXPos(qreal xpos); + void setXLimits(qreal min, qreal max); - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); public slots: - void sceneRectChanged(const QRectF &); - void setOpacity(qreal opacity); + void sceneRectChanged(const QRectF &); + void setOpacity(qreal opacity); protected: - void hoverEnterEvent(QGraphicsSceneHoverEvent *event); - void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); - void mouseMoveEvent(QGraphicsSceneMouseEvent *event); - void mousePressEvent(QGraphicsSceneMouseEvent *event); - void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + void hoverEnterEvent(QGraphicsSceneHoverEvent *event); + void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); + void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + void mousePressEvent(QGraphicsSceneMouseEvent *event); + void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); signals: - void positionChanged(qreal x); + void positionChanged(qreal x); private: - qreal _width; - qreal _sceneLeft, _sceneRight; - QRectF _boundingRect; - bool _moving; - qreal _offset; - qreal _minXPos, _maxXPos; - qreal _opacity; - QPropertyAnimation *_animation; + qreal _width; + qreal _sceneLeft, _sceneRight; + QRectF _boundingRect; + bool _moving; + qreal _offset; + qreal _minXPos, _maxXPos; + qreal _opacity; + QPropertyAnimation *_animation; }; + #endif diff --git a/src/qtui/coreconfigwizard.cpp b/src/qtui/coreconfigwizard.cpp index 837b0844..5ebe80a6 100644 --- a/src/qtui/coreconfigwizard.cpp +++ b/src/qtui/coreconfigwizard.cpp @@ -28,211 +28,237 @@ #include "iconloader.h" CoreConfigWizard::CoreConfigWizard(CoreConnection *connection, const QList &backends, QWidget *parent) - : QWizard(parent), - _connection(connection) + : QWizard(parent), + _connection(connection) { - setModal(true); - setAttribute(Qt::WA_DeleteOnClose); + setModal(true); + setAttribute(Qt::WA_DeleteOnClose); - foreach(const QVariant &v, backends) + foreach(const QVariant &v, backends) _backends[v.toMap()["DisplayName"].toString()] = v; - setPage(IntroPage, new CoreConfigWizardPages::IntroPage(this)); - setPage(AdminUserPage, new CoreConfigWizardPages::AdminUserPage(this)); - setPage(StorageSelectionPage, new CoreConfigWizardPages::StorageSelectionPage(_backends, this)); - syncPage = new CoreConfigWizardPages::SyncPage(this); - connect(syncPage, SIGNAL(setupCore(const QString &, const QVariantMap &)), SLOT(prepareCoreSetup(const QString &, const QVariantMap &))); - setPage(SyncPage, syncPage); - syncRelayPage = new CoreConfigWizardPages::SyncRelayPage(this); - connect(syncRelayPage, SIGNAL(startOver()), this, SLOT(startOver())); - setPage(SyncRelayPage, syncRelayPage); - //setPage(Page_StorageDetails, new StorageDetailsPage()); - //setPage(Page_Conclusion, new ConclusionPage(storageProviders)); - - setStartId(IntroPage); - //setStartId(StorageSelectionPage); + setPage(IntroPage, new CoreConfigWizardPages::IntroPage(this)); + setPage(AdminUserPage, new CoreConfigWizardPages::AdminUserPage(this)); + setPage(StorageSelectionPage, new CoreConfigWizardPages::StorageSelectionPage(_backends, this)); + syncPage = new CoreConfigWizardPages::SyncPage(this); + connect(syncPage, SIGNAL(setupCore(const QString &, const QVariantMap &)), SLOT(prepareCoreSetup(const QString &, const QVariantMap &))); + setPage(SyncPage, syncPage); + syncRelayPage = new CoreConfigWizardPages::SyncRelayPage(this); + connect(syncRelayPage, SIGNAL(startOver()), this, SLOT(startOver())); + setPage(SyncRelayPage, syncRelayPage); + //setPage(Page_StorageDetails, new StorageDetailsPage()); + //setPage(Page_Conclusion, new ConclusionPage(storageProviders)); + + setStartId(IntroPage); + //setStartId(StorageSelectionPage); #ifndef Q_WS_MAC - setWizardStyle(ModernStyle); + setWizardStyle(ModernStyle); #endif - setOption(HaveHelpButton, false); - setOption(NoBackButtonOnStartPage, true); - setOption(HaveNextButtonOnLastPage, false); - setOption(HaveFinishButtonOnEarlyPages, false); - setOption(NoCancelButton, true); - setOption(IndependentPages, true); - //setOption(ExtendedWatermarkPixmap, true); + setOption(HaveHelpButton, false); + setOption(NoBackButtonOnStartPage, true); + setOption(HaveNextButtonOnLastPage, false); + setOption(HaveFinishButtonOnEarlyPages, false); + setOption(NoCancelButton, true); + setOption(IndependentPages, true); + //setOption(ExtendedWatermarkPixmap, true); - setModal(true); + setModal(true); - setWindowTitle(tr("Core Configuration Wizard")); - setPixmap(QWizard::LogoPixmap, DesktopIcon("quassel")); + setWindowTitle(tr("Core Configuration Wizard")); + setPixmap(QWizard::LogoPixmap, DesktopIcon("quassel")); - connect(connection, SIGNAL(coreSetupSuccess()), SLOT(coreSetupSuccess())); - connect(connection, SIGNAL(coreSetupFailed(QString)), SLOT(coreSetupFailed(QString))); - //connect(connection, SIGNAL(loginSuccess()), SLOT(loginSuccess())); - connect(connection, SIGNAL(synchronized()), SLOT(syncFinished())); - connect(this, SIGNAL(rejected()), connection, SLOT(disconnectFromCore())); + connect(connection, SIGNAL(coreSetupSuccess()), SLOT(coreSetupSuccess())); + connect(connection, SIGNAL(coreSetupFailed(QString)), SLOT(coreSetupFailed(QString))); + //connect(connection, SIGNAL(loginSuccess()), SLOT(loginSuccess())); + connect(connection, SIGNAL(synchronized()), SLOT(syncFinished())); + connect(this, SIGNAL(rejected()), connection, SLOT(disconnectFromCore())); } -QHash CoreConfigWizard::backends() const { - return _backends; + +QHash CoreConfigWizard::backends() const +{ + return _backends; } -void CoreConfigWizard::prepareCoreSetup(const QString &backend, const QVariantMap &properties) { - // Prevent the user from changing any settings he already specified... - foreach(int idx, visitedPages()) + +void CoreConfigWizard::prepareCoreSetup(const QString &backend, const QVariantMap &properties) +{ + // Prevent the user from changing any settings he already specified... + foreach(int idx, visitedPages()) page(idx)->setEnabled(false); - QVariantMap foo; - foo["AdminUser"] = field("adminUser.user").toString(); - foo["AdminPasswd"] = field("adminUser.password").toString(); - foo["Backend"] = backend; - foo["ConnectionProperties"] = properties; - coreConnection()->doCoreSetup(foo); + QVariantMap foo; + foo["AdminUser"] = field("adminUser.user").toString(); + foo["AdminPasswd"] = field("adminUser.password").toString(); + foo["Backend"] = backend; + foo["ConnectionProperties"] = properties; + coreConnection()->doCoreSetup(foo); } -void CoreConfigWizard::coreSetupSuccess() { - syncPage->setStatus(tr("Your core has been successfully configured. Logging you in...")); - syncPage->setError(false); - syncRelayPage->setMode(CoreConfigWizardPages::SyncRelayPage::Error); - coreConnection()->loginToCore(field("adminUser.user").toString(), field("adminUser.password").toString(), field("adminUser.rememberPasswd").toBool()); + +void CoreConfigWizard::coreSetupSuccess() +{ + syncPage->setStatus(tr("Your core has been successfully configured. Logging you in...")); + syncPage->setError(false); + syncRelayPage->setMode(CoreConfigWizardPages::SyncRelayPage::Error); + coreConnection()->loginToCore(field("adminUser.user").toString(), field("adminUser.password").toString(), field("adminUser.rememberPasswd").toBool()); } -void CoreConfigWizard::coreSetupFailed(const QString &error) { - syncPage->setStatus(tr("Core configuration failed:
%1
Press Next to start over.").arg(error)); - syncPage->setError(true); - syncRelayPage->setMode(CoreConfigWizardPages::SyncRelayPage::Error); - //foreach(int idx, visitedPages()) page(idx)->setEnabled(true); - //setStartId(SyncPage); - //restart(); + +void CoreConfigWizard::coreSetupFailed(const QString &error) +{ + syncPage->setStatus(tr("Core configuration failed:
%1
Press Next to start over.").arg(error)); + syncPage->setError(true); + syncRelayPage->setMode(CoreConfigWizardPages::SyncRelayPage::Error); + //foreach(int idx, visitedPages()) page(idx)->setEnabled(true); + //setStartId(SyncPage); + //restart(); } -void CoreConfigWizard::startOver() { - foreach(int idx, visitedPages()) page(idx)->setEnabled(true); - setStartId(CoreConfigWizard::AdminUserPage); - restart(); + +void CoreConfigWizard::startOver() +{ + foreach(int idx, visitedPages()) page(idx)->setEnabled(true); + setStartId(CoreConfigWizard::AdminUserPage); + restart(); } -void CoreConfigWizard::loginSuccess() { - syncPage->setStatus(tr("Your are now logged into your freshly configured Quassel Core!
" - "Please remember to configure your identities and networks now.")); - syncPage->setComplete(true); - syncPage->setFinalPage(true); + +void CoreConfigWizard::loginSuccess() +{ + syncPage->setStatus(tr("Your are now logged into your freshly configured Quassel Core!
" + "Please remember to configure your identities and networks now.")); + syncPage->setComplete(true); + syncPage->setFinalPage(true); } -void CoreConfigWizard::syncFinished() { - accept(); + +void CoreConfigWizard::syncFinished() +{ + accept(); } -namespace CoreConfigWizardPages { +namespace CoreConfigWizardPages { /*** Intro Page ***/ -IntroPage::IntroPage(QWidget *parent) : QWizardPage(parent) { - ui.setupUi(this); - setTitle(tr("Introduction")); - //setSubTitle(tr("foobar")); - //setPixmap(QWizard::WatermarkPixmap, QPixmap(":icons/quassel-icon.png")); - +IntroPage::IntroPage(QWidget *parent) : QWizardPage(parent) +{ + ui.setupUi(this); + setTitle(tr("Introduction")); + //setSubTitle(tr("foobar")); + //setPixmap(QWizard::WatermarkPixmap, QPixmap(":icons/quassel-icon.png")); } -int IntroPage::nextId() const { - return CoreConfigWizard::AdminUserPage; +int IntroPage::nextId() const +{ + return CoreConfigWizard::AdminUserPage; } + /*** Admin User Page ***/ -AdminUserPage::AdminUserPage(QWidget *parent) : QWizardPage(parent) { - ui.setupUi(this); - setTitle(tr("Create Admin User")); - setSubTitle(tr("First, we will create a user on the core. This first user will have administrator privileges.")); +AdminUserPage::AdminUserPage(QWidget *parent) : QWizardPage(parent) +{ + ui.setupUi(this); + setTitle(tr("Create Admin User")); + setSubTitle(tr("First, we will create a user on the core. This first user will have administrator privileges.")); + + registerField("adminUser.user*", ui.user); + registerField("adminUser.password*", ui.password); + registerField("adminUser.password2*", ui.password2); + registerField("adminUser.rememberPasswd", ui.rememberPasswd); + + //ui.user->setText("foo"); + //ui.password->setText("foo"); + //ui.password2->setText("foo"); +} - registerField("adminUser.user*", ui.user); - registerField("adminUser.password*", ui.password); - registerField("adminUser.password2*", ui.password2); - registerField("adminUser.rememberPasswd", ui.rememberPasswd); - //ui.user->setText("foo"); - //ui.password->setText("foo"); - //ui.password2->setText("foo"); +int AdminUserPage::nextId() const +{ + return CoreConfigWizard::StorageSelectionPage; } -int AdminUserPage::nextId() const { - return CoreConfigWizard::StorageSelectionPage; +bool AdminUserPage::isComplete() const +{ + bool ok = !ui.user->text().isEmpty() && !ui.password->text().isEmpty() && ui.password->text() == ui.password2->text(); + return ok; } -bool AdminUserPage::isComplete() const { - bool ok = !ui.user->text().isEmpty() && !ui.password->text().isEmpty() && ui.password->text() == ui.password2->text(); - return ok; -} /*** Storage Selection Page ***/ StorageSelectionPage::StorageSelectionPage(const QHash &backends, QWidget *parent) - : QWizardPage(parent), + : QWizardPage(parent), _connectionBox(0), _backends(backends) { - ui.setupUi(this); + ui.setupUi(this); - setTitle(tr("Select Storage Backend")); - setSubTitle(tr("Please select a database backend for the Quassel Core storage to store the backlog and other data in.")); - setCommitPage(true); + setTitle(tr("Select Storage Backend")); + setSubTitle(tr("Please select a database backend for the Quassel Core storage to store the backlog and other data in.")); + setCommitPage(true); - registerField("storage.backend", ui.backendList); + registerField("storage.backend", ui.backendList); - foreach(QString key, _backends.keys()) { - ui.backendList->addItem(_backends[key].toMap()["DisplayName"].toString(), key); - } + foreach(QString key, _backends.keys()) { + ui.backendList->addItem(_backends[key].toMap()["DisplayName"].toString(), key); + } - on_backendList_currentIndexChanged(); + on_backendList_currentIndexChanged(); } -int StorageSelectionPage::nextId() const { - return CoreConfigWizard::SyncPage; + +int StorageSelectionPage::nextId() const +{ + return CoreConfigWizard::SyncPage; } -QString StorageSelectionPage::selectedBackend() const { - return ui.backendList->currentText(); + +QString StorageSelectionPage::selectedBackend() const +{ + return ui.backendList->currentText(); } -QVariantMap StorageSelectionPage::connectionProperties() const { - QString backend = ui.backendList->itemData(ui.backendList->currentIndex()).toString(); - - QVariantMap properties; - QStringList setupKeys = _backends[backend].toMap()["SetupKeys"].toStringList(); - if(!setupKeys.isEmpty()) { - QVariantMap defaults = _backends[backend].toMap()["SetupDefaults"].toMap(); - foreach(QString key, setupKeys) { - QWidget *widget = _connectionBox->findChild(key); - QVariant def; - if(defaults.contains(key)) { - def = defaults[key]; - } - switch(def.type()) { - case QVariant::Int: - { - QSpinBox *spinbox = qobject_cast(widget); - Q_ASSERT(spinbox); - def = QVariant(spinbox->value()); - } - break; - default: - { - QLineEdit *lineEdit = qobject_cast(widget); - Q_ASSERT(lineEdit); - def = QVariant(lineEdit->text()); + +QVariantMap StorageSelectionPage::connectionProperties() const +{ + QString backend = ui.backendList->itemData(ui.backendList->currentIndex()).toString(); + + QVariantMap properties; + QStringList setupKeys = _backends[backend].toMap()["SetupKeys"].toStringList(); + if (!setupKeys.isEmpty()) { + QVariantMap defaults = _backends[backend].toMap()["SetupDefaults"].toMap(); + foreach(QString key, setupKeys) { + QWidget *widget = _connectionBox->findChild(key); + QVariant def; + if (defaults.contains(key)) { + def = defaults[key]; + } + switch (def.type()) { + case QVariant::Int: + { + QSpinBox *spinbox = qobject_cast(widget); + Q_ASSERT(spinbox); + def = QVariant(spinbox->value()); + } + break; + default: + { + QLineEdit *lineEdit = qobject_cast(widget); + Q_ASSERT(lineEdit); + def = QVariant(lineEdit->text()); + } + } + properties[key] = def; } - } - properties[key] = def; } - } - qDebug() << properties; - + qDebug() << properties; // QVariantMap properties = _backends[backend].toMap()["ConnectionProperties"].toMap(); // if(!properties.isEmpty() && _connectionBox) { @@ -241,128 +267,149 @@ QVariantMap StorageSelectionPage::connectionProperties() const { // QWidget *widget = _connectionBox->findChild(propertyIter.key()); // switch(propertyIter.value().type()) { // case QVariant::Int: -// { -// QSpinBox *spinbox = qobject_cast(widget); -// Q_ASSERT(spinbox); -// propertyIter.value() = QVariant(spinbox->value()); -// } -// break; +// { +// QSpinBox *spinbox = qobject_cast(widget); +// Q_ASSERT(spinbox); +// propertyIter.value() = QVariant(spinbox->value()); +// } +// break; // default: -// { -// QLineEdit *lineEdit = qobject_cast(widget); -// Q_ASSERT(lineEdit); -// propertyIter.value() = QVariant(lineEdit->text()); -// } +// { +// QLineEdit *lineEdit = qobject_cast(widget); +// Q_ASSERT(lineEdit); +// propertyIter.value() = QVariant(lineEdit->text()); +// } // } // propertyIter++; // } // } - return properties; + return properties; } -void StorageSelectionPage::on_backendList_currentIndexChanged() { - QString backend = ui.backendList->itemData(ui.backendList->currentIndex()).toString(); - ui.description->setText(_backends[backend].toMap()["Description"].toString()); - if(_connectionBox) { - layout()->removeWidget(_connectionBox); - _connectionBox->deleteLater(); - _connectionBox = 0; - } +void StorageSelectionPage::on_backendList_currentIndexChanged() +{ + QString backend = ui.backendList->itemData(ui.backendList->currentIndex()).toString(); + ui.description->setText(_backends[backend].toMap()["Description"].toString()); - QStringList setupKeys = _backends[backend].toMap()["SetupKeys"].toStringList(); - if(!setupKeys.isEmpty()) { - QVariantMap defaults = _backends[backend].toMap()["SetupDefaults"].toMap(); - QGroupBox *propertyBox = new QGroupBox(this); - propertyBox->setTitle(tr("Connection Properties")); - QFormLayout *formlayout = new QFormLayout; - - foreach(QString key, setupKeys) { - QWidget *widget = 0; - QVariant def; - if(defaults.contains(key)) { - def = defaults[key]; - } - switch(def.type()) { - case QVariant::Int: - { - QSpinBox *spinbox = new QSpinBox(propertyBox); - spinbox->setMaximum(64000); - spinbox->setValue(def.toInt()); - widget = spinbox; - } - break; - default: - { - QLineEdit *lineEdit = new QLineEdit(def.toString(), propertyBox); - if(key.toLower().contains("password")) { - lineEdit->setEchoMode(QLineEdit::Password); - } - widget = lineEdit; + if (_connectionBox) { + layout()->removeWidget(_connectionBox); + _connectionBox->deleteLater(); + _connectionBox = 0; + } + + QStringList setupKeys = _backends[backend].toMap()["SetupKeys"].toStringList(); + if (!setupKeys.isEmpty()) { + QVariantMap defaults = _backends[backend].toMap()["SetupDefaults"].toMap(); + QGroupBox *propertyBox = new QGroupBox(this); + propertyBox->setTitle(tr("Connection Properties")); + QFormLayout *formlayout = new QFormLayout; + + foreach(QString key, setupKeys) { + QWidget *widget = 0; + QVariant def; + if (defaults.contains(key)) { + def = defaults[key]; + } + switch (def.type()) { + case QVariant::Int: + { + QSpinBox *spinbox = new QSpinBox(propertyBox); + spinbox->setMaximum(64000); + spinbox->setValue(def.toInt()); + widget = spinbox; + } + break; + default: + { + QLineEdit *lineEdit = new QLineEdit(def.toString(), propertyBox); + if (key.toLower().contains("password")) { + lineEdit->setEchoMode(QLineEdit::Password); + } + widget = lineEdit; + } + } + widget->setObjectName(key); + formlayout->addRow(key + ":", widget); } - } - widget->setObjectName(key); - formlayout->addRow(key + ":", widget); + propertyBox->setLayout(formlayout); + static_cast(layout())->insertWidget(layout()->indexOf(ui.descriptionBox) + 1, propertyBox); + _connectionBox = propertyBox; } - propertyBox->setLayout(formlayout); - static_cast(layout())->insertWidget(layout()->indexOf(ui.descriptionBox) + 1, propertyBox); - _connectionBox = propertyBox; - } } + /*** Sync Page ***/ -SyncPage::SyncPage(QWidget *parent) : QWizardPage(parent) { - ui.setupUi(this); - setTitle(tr("Storing Your Settings")); - setSubTitle(tr("Your settings are now stored in the core, and you will be logged in automatically.")); +SyncPage::SyncPage(QWidget *parent) : QWizardPage(parent) +{ + ui.setupUi(this); + setTitle(tr("Storing Your Settings")); + setSubTitle(tr("Your settings are now stored in the core, and you will be logged in automatically.")); } -void SyncPage::initializePage() { - complete = false; - hasError = false; - - StorageSelectionPage *storagePage = qobject_cast(wizard()->page(CoreConfigWizard::StorageSelectionPage)); - QString backend = storagePage->selectedBackend(); - QVariantMap properties = storagePage->connectionProperties(); - Q_ASSERT(!backend.isEmpty()); - ui.user->setText(wizard()->field("adminUser.user").toString()); - ui.backend->setText(backend); - emit setupCore(backend, properties); + +void SyncPage::initializePage() +{ + complete = false; + hasError = false; + + StorageSelectionPage *storagePage = qobject_cast(wizard()->page(CoreConfigWizard::StorageSelectionPage)); + QString backend = storagePage->selectedBackend(); + QVariantMap properties = storagePage->connectionProperties(); + Q_ASSERT(!backend.isEmpty()); + ui.user->setText(wizard()->field("adminUser.user").toString()); + ui.backend->setText(backend); + emit setupCore(backend, properties); } -int SyncPage::nextId() const { - if(!hasError) return -1; - return CoreConfigWizard::SyncRelayPage; + +int SyncPage::nextId() const +{ + if (!hasError) return -1; + return CoreConfigWizard::SyncRelayPage; } -bool SyncPage::isComplete() const { - return complete; + +bool SyncPage::isComplete() const +{ + return complete; } -void SyncPage::setStatus(const QString &status) { - ui.status->setText(status); + +void SyncPage::setStatus(const QString &status) +{ + ui.status->setText(status); } -void SyncPage::setError(bool e) { - hasError = e; + +void SyncPage::setError(bool e) +{ + hasError = e; } -void SyncPage::setComplete(bool c) { - complete = c; - completeChanged(); + +void SyncPage::setComplete(bool c) +{ + complete = c; + completeChanged(); } + /*** Sync Relay Page ***/ -SyncRelayPage::SyncRelayPage(QWidget *parent) : QWizardPage(parent) { - mode = Success; +SyncRelayPage::SyncRelayPage(QWidget *parent) : QWizardPage(parent) +{ + mode = Success; } -void SyncRelayPage::setMode(Mode m) { - mode = m; + +void SyncRelayPage::setMode(Mode m) +{ + mode = m; } + /* void SyncRelayPage::initializePage() { return; @@ -374,9 +421,9 @@ void SyncRelayPage::initializePage() { } */ -int SyncRelayPage::nextId() const { - emit startOver(); - return 0; +int SyncRelayPage::nextId() const +{ + emit startOver(); + return 0; } - }; /* namespace CoreConfigWizardPages */ diff --git a/src/qtui/coreconfigwizard.h b/src/qtui/coreconfigwizard.h index b6d9de8d..795547d5 100644 --- a/src/qtui/coreconfigwizard.h +++ b/src/qtui/coreconfigwizard.h @@ -33,22 +33,23 @@ class CoreConnection; namespace CoreConfigWizardPages { - class SyncPage; - class SyncRelayPage; +class SyncPage; +class SyncRelayPage; }; -class CoreConfigWizard : public QWizard { - Q_OBJECT +class CoreConfigWizard : public QWizard +{ + Q_OBJECT - public: +public: enum { - IntroPage, - AdminUserPage, - StorageSelectionPage, - SyncPage, - SyncRelayPage, - StorageDetailsPage, - ConclusionPage + IntroPage, + AdminUserPage, + StorageSelectionPage, + SyncPage, + SyncRelayPage, + StorageDetailsPage, + ConclusionPage }; CoreConfigWizard(CoreConnection *connection, const QList &backends, QWidget *parent = 0); @@ -56,21 +57,21 @@ class CoreConfigWizard : public QWizard { inline CoreConnection *coreConnection() const { return _connection; } - signals: +signals: void setupCore(const QVariant &setupData); void loginToCore(const QString &user, const QString &password, bool rememberPassword); - public slots: +public slots: void loginSuccess(); void syncFinished(); - private slots: +private slots: void prepareCoreSetup(const QString &backend, const QVariantMap &connectionProperties); void coreSetupSuccess(); void coreSetupFailed(const QString &); void startOver(); - private: +private: QHash _backends; CoreConfigWizardPages::SyncPage *syncPage; CoreConfigWizardPages::SyncRelayPage *syncRelayPage; @@ -78,87 +79,95 @@ class CoreConfigWizard : public QWizard { CoreConnection *_connection; }; -namespace CoreConfigWizardPages { - class IntroPage : public QWizardPage { +namespace CoreConfigWizardPages { +class IntroPage : public QWizardPage +{ Q_OBJECT - public: - IntroPage(QWidget *parent = 0); - int nextId() const; - private: - Ui::CoreConfigWizardIntroPage ui; - }; +public: + IntroPage(QWidget *parent = 0); + int nextId() const; +private: + Ui::CoreConfigWizardIntroPage ui; +}; + - class AdminUserPage : public QWizardPage { +class AdminUserPage : public QWizardPage +{ Q_OBJECT - public: - AdminUserPage(QWidget *parent = 0); - int nextId() const; - bool isComplete() const; - private: - Ui::CoreConfigWizardAdminUserPage ui; - }; +public: + AdminUserPage(QWidget *parent = 0); + int nextId() const; + bool isComplete() const; +private: + Ui::CoreConfigWizardAdminUserPage ui; +}; + - class StorageSelectionPage : public QWizardPage { +class StorageSelectionPage : public QWizardPage +{ Q_OBJECT - public: - StorageSelectionPage(const QHash &backends, QWidget *parent = 0); - int nextId() const; - QString selectedBackend() const; - QVariantMap connectionProperties() const; - - private slots: - void on_backendList_currentIndexChanged(); - private: - Ui::CoreConfigWizardStorageSelectionPage ui; - QGroupBox *_connectionBox; - QHash _backends; - }; - - class SyncPage : public QWizardPage { +public: + StorageSelectionPage(const QHash &backends, QWidget *parent = 0); + int nextId() const; + QString selectedBackend() const; + QVariantMap connectionProperties() const; + +private slots: + void on_backendList_currentIndexChanged(); +private: + Ui::CoreConfigWizardStorageSelectionPage ui; + QGroupBox *_connectionBox; + QHash _backends; +}; + + +class SyncPage : public QWizardPage +{ Q_OBJECT - public: - SyncPage(QWidget *parent = 0); - void initializePage(); - int nextId() const; - bool isComplete() const; +public: + SyncPage(QWidget *parent = 0); + void initializePage(); + int nextId() const; + bool isComplete() const; - public slots: - void setStatus(const QString &status); - void setError(bool); - void setComplete(bool); +public slots: + void setStatus(const QString &status); + void setError(bool); + void setComplete(bool); - signals: - void setupCore(const QString &backend, const QVariantMap &); +signals: + void setupCore(const QString &backend, const QVariantMap &); - private: - Ui::CoreConfigWizardSyncPage ui; - bool complete; - bool hasError; - }; +private: + Ui::CoreConfigWizardSyncPage ui; + bool complete; + bool hasError; +}; - class SyncRelayPage : public QWizardPage { - Q_OBJECT - public: - SyncRelayPage(QWidget *parent = 0); - int nextId() const; - enum Mode { Success, Error }; +class SyncRelayPage : public QWizardPage +{ + Q_OBJECT - public slots: - void setMode(Mode); +public: + SyncRelayPage(QWidget *parent = 0); + int nextId() const; + enum Mode { Success, Error }; - signals: - void startOver() const; +public slots: + void setMode(Mode); - private: - Mode mode; - }; +signals: + void startOver() const; +private: + Mode mode; +}; } #endif diff --git a/src/qtui/coreconnectdlg.cpp b/src/qtui/coreconnectdlg.cpp index d3ebb7ac..9cc34277 100644 --- a/src/qtui/coreconnectdlg.cpp +++ b/src/qtui/coreconnectdlg.cpp @@ -27,71 +27,81 @@ #include "clientsettings.h" #include "coreaccountsettingspage.h" -CoreConnectDlg::CoreConnectDlg(QWidget *parent) : QDialog(parent) { - _settingsPage = new CoreAccountSettingsPage(this); - _settingsPage->setStandAlone(true); - _settingsPage->load(); +CoreConnectDlg::CoreConnectDlg(QWidget *parent) : QDialog(parent) +{ + _settingsPage = new CoreAccountSettingsPage(this); + _settingsPage->setStandAlone(true); + _settingsPage->load(); - CoreAccountSettings s; - AccountId lastAccount = s.lastAccount(); - if(lastAccount.isValid()) - _settingsPage->setSelectedAccount(lastAccount); + CoreAccountSettings s; + AccountId lastAccount = s.lastAccount(); + if (lastAccount.isValid()) + _settingsPage->setSelectedAccount(lastAccount); - setWindowTitle(tr("Connect to Core")); - setWindowIcon(SmallIcon("network-disconnect")); + setWindowTitle(tr("Connect to Core")); + setWindowIcon(SmallIcon("network-disconnect")); - QVBoxLayout *layout = new QVBoxLayout(this); - layout->addWidget(_settingsPage); + QVBoxLayout *layout = new QVBoxLayout(this); + layout->addWidget(_settingsPage); - QDialogButtonBox *buttonBox = new QDialogButtonBox(this); - buttonBox->setStandardButtons(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); - layout->addWidget(buttonBox); + QDialogButtonBox *buttonBox = new QDialogButtonBox(this); + buttonBox->setStandardButtons(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); + layout->addWidget(buttonBox); - connect(_settingsPage, SIGNAL(connectToCore(AccountId)), SLOT(accept())); - connect(buttonBox, SIGNAL(accepted()), SLOT(accept())); - connect(buttonBox, SIGNAL(rejected()), SLOT(reject())); + connect(_settingsPage, SIGNAL(connectToCore(AccountId)), SLOT(accept())); + connect(buttonBox, SIGNAL(accepted()), SLOT(accept())); + connect(buttonBox, SIGNAL(rejected()), SLOT(reject())); } -AccountId CoreConnectDlg::selectedAccount() const { - return _settingsPage->selectedAccount(); + +AccountId CoreConnectDlg::selectedAccount() const +{ + return _settingsPage->selectedAccount(); } -void CoreConnectDlg::accept() { - _settingsPage->save(); - QDialog::accept(); + +void CoreConnectDlg::accept() +{ + _settingsPage->save(); + QDialog::accept(); } + /******** CoreConnectAuthDlg ****************************************************************/ CoreConnectAuthDlg::CoreConnectAuthDlg(CoreAccount *account, QWidget *parent) - : QDialog(parent), - _account(account) + : QDialog(parent), + _account(account) { - ui.setupUi(this); + ui.setupUi(this); - connect(ui.user, SIGNAL(textChanged(QString)), SLOT(setButtonStates())); - connect(ui.password, SIGNAL(textChanged(QString)), SLOT(setButtonStates())); + connect(ui.user, SIGNAL(textChanged(QString)), SLOT(setButtonStates())); + connect(ui.password, SIGNAL(textChanged(QString)), SLOT(setButtonStates())); - ui.label->setText(tr("Please enter your credentials for %1:").arg(account->accountName())); - ui.user->setText(account->user()); - ui.password->setText(account->password()); - ui.rememberPasswd->setChecked(account->storePassword()); + ui.label->setText(tr("Please enter your credentials for %1:").arg(account->accountName())); + ui.user->setText(account->user()); + ui.password->setText(account->password()); + ui.rememberPasswd->setChecked(account->storePassword()); - if(ui.user->text().isEmpty()) - ui.user->setFocus(); - else - ui.password->setFocus(); + if (ui.user->text().isEmpty()) + ui.user->setFocus(); + else + ui.password->setFocus(); } -void CoreConnectAuthDlg::accept() { - _account->setUser(ui.user->text()); - _account->setPassword(ui.password->text()); - _account->setStorePassword(ui.rememberPasswd->isChecked()); - QDialog::accept(); +void CoreConnectAuthDlg::accept() +{ + _account->setUser(ui.user->text()); + _account->setPassword(ui.password->text()); + _account->setStorePassword(ui.rememberPasswd->isChecked()); + + QDialog::accept(); } -void CoreConnectAuthDlg::setButtonStates() { - bool valid = !(ui.user->text().isEmpty() || ui.password->text().isEmpty()); - ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(valid); + +void CoreConnectAuthDlg::setButtonStates() +{ + bool valid = !(ui.user->text().isEmpty() || ui.password->text().isEmpty()); + ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(valid); } diff --git a/src/qtui/coreconnectdlg.h b/src/qtui/coreconnectdlg.h index b892a20d..5d34d2a8 100644 --- a/src/qtui/coreconnectdlg.h +++ b/src/qtui/coreconnectdlg.h @@ -29,33 +29,37 @@ class CoreAccountSettingsPage; -class CoreConnectDlg : public QDialog { - Q_OBJECT +class CoreConnectDlg : public QDialog +{ + Q_OBJECT public: - CoreConnectDlg(QWidget *parent = 0); - AccountId selectedAccount() const; + CoreConnectDlg(QWidget *parent = 0); + AccountId selectedAccount() const; - void accept(); + void accept(); private: - CoreAccountSettingsPage *_settingsPage; + CoreAccountSettingsPage *_settingsPage; }; -class CoreConnectAuthDlg : public QDialog { - Q_OBJECT + +class CoreConnectAuthDlg : public QDialog +{ + Q_OBJECT public: - CoreConnectAuthDlg(CoreAccount *account, QWidget *parent = 0); + CoreConnectAuthDlg(CoreAccount *account, QWidget *parent = 0); - void accept(); + void accept(); private slots: - void setButtonStates(); + void setButtonStates(); private: - Ui::CoreConnectAuthDlg ui; - CoreAccount *_account; + Ui::CoreConnectAuthDlg ui; + CoreAccount *_account; }; + #endif diff --git a/src/qtui/coreconnectionstatuswidget.cpp b/src/qtui/coreconnectionstatuswidget.cpp index 7910fb8a..a7b57f84 100644 --- a/src/qtui/coreconnectionstatuswidget.cpp +++ b/src/qtui/coreconnectionstatuswidget.cpp @@ -25,64 +25,76 @@ #include "signalproxy.h" CoreConnectionStatusWidget::CoreConnectionStatusWidget(CoreConnection *connection, QWidget *parent) - : QWidget(parent), - _coreConnection(connection) + : QWidget(parent), + _coreConnection(connection) { - ui.setupUi(this); - ui.lagLabel->hide(); - ui.sslLabel->hide(); - update(); + ui.setupUi(this); + ui.lagLabel->hide(); + ui.sslLabel->hide(); + update(); - connect(coreConnection(), SIGNAL(progressTextChanged(QString)), ui.messageLabel, SLOT(setText(QString))); - connect(coreConnection(), SIGNAL(progressValueChanged(int)), ui.progressBar, SLOT(setValue(int))); - connect(coreConnection(), SIGNAL(progressRangeChanged(int, int)), ui.progressBar, SLOT(setRange(int, int))); - connect(coreConnection(), SIGNAL(progressRangeChanged(int, int)), this, SLOT(progressRangeChanged(int, int))); + connect(coreConnection(), SIGNAL(progressTextChanged(QString)), ui.messageLabel, SLOT(setText(QString))); + connect(coreConnection(), SIGNAL(progressValueChanged(int)), ui.progressBar, SLOT(setValue(int))); + connect(coreConnection(), SIGNAL(progressRangeChanged(int, int)), ui.progressBar, SLOT(setRange(int, int))); + connect(coreConnection(), SIGNAL(progressRangeChanged(int, int)), this, SLOT(progressRangeChanged(int, int))); - connect(coreConnection(), SIGNAL(stateChanged(CoreConnection::ConnectionState)), SLOT(connectionStateChanged(CoreConnection::ConnectionState))); - connect(coreConnection(), SIGNAL(connectionError(QString)), ui.messageLabel, SLOT(setText(QString))); - connect(coreConnection(), SIGNAL(lagUpdated(int)), SLOT(updateLag(int))); + connect(coreConnection(), SIGNAL(stateChanged(CoreConnection::ConnectionState)), SLOT(connectionStateChanged(CoreConnection::ConnectionState))); + connect(coreConnection(), SIGNAL(connectionError(QString)), ui.messageLabel, SLOT(setText(QString))); + connect(coreConnection(), SIGNAL(lagUpdated(int)), SLOT(updateLag(int))); } -void CoreConnectionStatusWidget::update() { - CoreConnection *conn = coreConnection(); - if(conn->progressMaximum() >= 0) { - ui.progressBar->setMinimum(conn->progressMinimum()); - ui.progressBar->setMaximum(conn->progressMaximum()); - ui.progressBar->setValue(conn->progressValue()); - ui.progressBar->show(); - } else - ui.progressBar->hide(); - ui.messageLabel->setText(conn->progressText()); +void CoreConnectionStatusWidget::update() +{ + CoreConnection *conn = coreConnection(); + if (conn->progressMaximum() >= 0) { + ui.progressBar->setMinimum(conn->progressMinimum()); + ui.progressBar->setMaximum(conn->progressMaximum()); + ui.progressBar->setValue(conn->progressValue()); + ui.progressBar->show(); + } + else + ui.progressBar->hide(); + + ui.messageLabel->setText(conn->progressText()); } -void CoreConnectionStatusWidget::updateLag(int msecs) { - if(msecs >= 0) { - QString unit = msecs >= 100 ? tr("s", "seconds") : tr("ms", "milliseconds"); - ui.lagLabel->setText(tr("(Lag: %1 %2)").arg(msecs >= 100 ? msecs / 1000. : msecs, 0, 'f', (int)(msecs >= 100)).arg(unit)); - if(!ui.lagLabel->isVisible()) - ui.lagLabel->show(); - } else { - if(ui.lagLabel->isVisible()) - ui.lagLabel->hide(); - } + +void CoreConnectionStatusWidget::updateLag(int msecs) +{ + if (msecs >= 0) { + QString unit = msecs >= 100 ? tr("s", "seconds") : tr("ms", "milliseconds"); + ui.lagLabel->setText(tr("(Lag: %1 %2)").arg(msecs >= 100 ? msecs / 1000. : msecs, 0, 'f', (int)(msecs >= 100)).arg(unit)); + if (!ui.lagLabel->isVisible()) + ui.lagLabel->show(); + } + else { + if (ui.lagLabel->isVisible()) + ui.lagLabel->hide(); + } } -void CoreConnectionStatusWidget::connectionStateChanged(CoreConnection::ConnectionState state) { - if(state >= CoreConnection::Connected) { - if(coreConnection()->isEncrypted()) { - ui.sslLabel->setPixmap(SmallIcon("security-high")); - ui.sslLabel->setToolTip(tr("The connection to your core is encrypted with SSL.")); - } else { - ui.sslLabel->setPixmap(SmallIcon("security-low")); - ui.sslLabel->setToolTip(tr("The connection to your core is not encrypted.")); + +void CoreConnectionStatusWidget::connectionStateChanged(CoreConnection::ConnectionState state) +{ + if (state >= CoreConnection::Connected) { + if (coreConnection()->isEncrypted()) { + ui.sslLabel->setPixmap(SmallIcon("security-high")); + ui.sslLabel->setToolTip(tr("The connection to your core is encrypted with SSL.")); + } + else { + ui.sslLabel->setPixmap(SmallIcon("security-low")); + ui.sslLabel->setToolTip(tr("The connection to your core is not encrypted.")); + } + ui.sslLabel->show(); } - ui.sslLabel->show(); - } else - ui.sslLabel->hide(); + else + ui.sslLabel->hide(); } -void CoreConnectionStatusWidget::progressRangeChanged(int min, int max) { - Q_UNUSED(min) - ui.progressBar->setVisible(max >= 0); + +void CoreConnectionStatusWidget::progressRangeChanged(int min, int max) +{ + Q_UNUSED(min) + ui.progressBar->setVisible(max >= 0); } diff --git a/src/qtui/coreconnectionstatuswidget.h b/src/qtui/coreconnectionstatuswidget.h index f07926ed..b6f5be74 100644 --- a/src/qtui/coreconnectionstatuswidget.h +++ b/src/qtui/coreconnectionstatuswidget.h @@ -27,26 +27,28 @@ #include "coreconnection.h" -class CoreConnectionStatusWidget : public QWidget { - Q_OBJECT +class CoreConnectionStatusWidget : public QWidget +{ + Q_OBJECT public: - CoreConnectionStatusWidget(CoreConnection *connection, QWidget *parent = 0); + CoreConnectionStatusWidget(CoreConnection *connection, QWidget *parent = 0); - inline CoreConnection *coreConnection() const { return _coreConnection; } + inline CoreConnection *coreConnection() const { return _coreConnection; } public slots: - void update(); - void updateLag(int msecs); + void update(); + void updateLag(int msecs); private slots: - void connectionStateChanged(CoreConnection::ConnectionState); - void progressRangeChanged(int min, int max); + void connectionStateChanged(CoreConnection::ConnectionState); + void progressRangeChanged(int min, int max); private: - Ui::CoreConnectionStatusWidget ui; + Ui::CoreConnectionStatusWidget ui; - CoreConnection *_coreConnection; + CoreConnection *_coreConnection; }; + #endif // CORECONNECTIONSTATUSWIDGET_H diff --git a/src/qtui/coreinfodlg.cpp b/src/qtui/coreinfodlg.cpp index ce36d018..f7ffa0bb 100644 --- a/src/qtui/coreinfodlg.cpp +++ b/src/qtui/coreinfodlg.cpp @@ -26,31 +26,35 @@ #include "signalproxy.h" CoreInfoDlg::CoreInfoDlg(QWidget *parent) - : QDialog(parent), + : QDialog(parent), _coreInfo(this) { - ui.setupUi(this); - connect(&_coreInfo, SIGNAL(initDone()), this, SLOT(coreInfoAvailable())); - Client::signalProxy()->synchronize(&_coreInfo); + ui.setupUi(this); + connect(&_coreInfo, SIGNAL(initDone()), this, SLOT(coreInfoAvailable())); + Client::signalProxy()->synchronize(&_coreInfo); } -void CoreInfoDlg::coreInfoAvailable() { - ui.labelCoreVersion->setText(_coreInfo["quasselVersion"].toString()); - ui.labelCoreBuildDate->setText(_coreInfo["quasselBuildDate"].toString()); - ui.labelClientCount->setNum(_coreInfo["sessionConnectedClients"].toInt()); - updateUptime(); - startTimer(1000); + +void CoreInfoDlg::coreInfoAvailable() +{ + ui.labelCoreVersion->setText(_coreInfo["quasselVersion"].toString()); + ui.labelCoreBuildDate->setText(_coreInfo["quasselBuildDate"].toString()); + ui.labelClientCount->setNum(_coreInfo["sessionConnectedClients"].toInt()); + updateUptime(); + startTimer(1000); } -void CoreInfoDlg::updateUptime() { - QDateTime startTime = _coreInfo["startTime"].toDateTime(); - int uptime = startTime.secsTo(QDateTime::currentDateTime().toUTC()); - int updays = uptime / 86400; uptime %= 86400; - int uphours = uptime / 3600; uptime %= 3600; - int upmins = uptime / 60; uptime %= 60; +void CoreInfoDlg::updateUptime() +{ + QDateTime startTime = _coreInfo["startTime"].toDateTime(); + + int uptime = startTime.secsTo(QDateTime::currentDateTime().toUTC()); + int updays = uptime / 86400; uptime %= 86400; + int uphours = uptime / 3600; uptime %= 3600; + int upmins = uptime / 60; uptime %= 60; - QString uptimeText = tr("%n Day(s)", "", updays) - + tr(" %1:%2:%3 (since %4)").arg(uphours,2,10,QChar('0')).arg(upmins,2,10,QChar('0')).arg(uptime,2,10,QChar('0')).arg(startTime.toLocalTime().toString(Qt::TextDate)); - ui.labelUptime->setText(uptimeText); + QString uptimeText = tr("%n Day(s)", "", updays) + + tr(" %1:%2:%3 (since %4)").arg(uphours, 2, 10, QChar('0')).arg(upmins, 2, 10, QChar('0')).arg(uptime, 2, 10, QChar('0')).arg(startTime.toLocalTime().toString(Qt::TextDate)); + ui.labelUptime->setText(uptimeText); } diff --git a/src/qtui/coreinfodlg.h b/src/qtui/coreinfodlg.h index 05c9de09..5a111f2b 100644 --- a/src/qtui/coreinfodlg.h +++ b/src/qtui/coreinfodlg.h @@ -26,25 +26,27 @@ #include "clientcoreinfo.h" -class CoreInfoDlg : public QDialog { - Q_OBJECT +class CoreInfoDlg : public QDialog +{ + Q_OBJECT public: - CoreInfoDlg(QWidget *parent = 0); + CoreInfoDlg(QWidget *parent = 0); public slots: - void coreInfoAvailable(); + void coreInfoAvailable(); protected: - virtual void timerEvent(QTimerEvent *) { updateUptime(); } + virtual void timerEvent(QTimerEvent *) { updateUptime(); } private slots: - void on_closeButton_clicked() { reject(); } - void updateUptime(); + void on_closeButton_clicked() { reject(); } + void updateUptime(); private: - Ui::CoreInfoDlg ui; - ClientCoreInfo _coreInfo; + Ui::CoreInfoDlg ui; + ClientCoreInfo _coreInfo; }; + #endif //COREINFODLG_H diff --git a/src/qtui/debugbufferviewoverlay.cpp b/src/qtui/debugbufferviewoverlay.cpp index 1207c2a2..8311f2c8 100644 --- a/src/qtui/debugbufferviewoverlay.cpp +++ b/src/qtui/debugbufferviewoverlay.cpp @@ -31,75 +31,77 @@ #include "client.h" DebugBufferViewOverlay::DebugBufferViewOverlay(QWidget *parent) - : QWidget(parent) + : QWidget(parent) { - ui.setupUi(this); + ui.setupUi(this); - BufferViewOverlayFilter *filter = new BufferViewOverlayFilter(Client::bufferModel(), Client::bufferViewOverlay()); + BufferViewOverlayFilter *filter = new BufferViewOverlayFilter(Client::bufferModel(), Client::bufferViewOverlay()); - filter->setParent(ui.bufferView); + filter->setParent(ui.bufferView); - ui.bufferView->setModel(filter); - ui.bufferView->setColumnWidth(0, 250); - ui.bufferView->setColumnWidth(1, 250); - ui.bufferView->setColumnWidth(2, 80); - ui.bufferView->resize(610, 300); - ui.bufferView->show(); + ui.bufferView->setModel(filter); + ui.bufferView->setColumnWidth(0, 250); + ui.bufferView->setColumnWidth(1, 250); + ui.bufferView->setColumnWidth(2, 80); + ui.bufferView->resize(610, 300); + ui.bufferView->show(); - QFormLayout *layout = new QFormLayout(ui.overlayProperties); - layout->addRow(tr("BufferViews:"), _bufferViews = new QLineEdit(this)); - layout->addRow(tr("All Networks:"), _allNetworks = new QLabel(this)); - layout->addRow(tr("Networks:"), _networks = new QLineEdit(this)); - layout->addRow(tr("Buffers:"), _bufferIds = new QTextEdit(this)); - layout->addRow(tr("Removed buffers:"), _removedBufferIds = new QTextEdit(this)); - layout->addRow(tr("Temp. removed buffers:"), _tempRemovedBufferIds = new QTextEdit(this)); + QFormLayout *layout = new QFormLayout(ui.overlayProperties); + layout->addRow(tr("BufferViews:"), _bufferViews = new QLineEdit(this)); + layout->addRow(tr("All Networks:"), _allNetworks = new QLabel(this)); + layout->addRow(tr("Networks:"), _networks = new QLineEdit(this)); + layout->addRow(tr("Buffers:"), _bufferIds = new QTextEdit(this)); + layout->addRow(tr("Removed buffers:"), _removedBufferIds = new QTextEdit(this)); + layout->addRow(tr("Temp. removed buffers:"), _tempRemovedBufferIds = new QTextEdit(this)); - layout->addRow(tr("Allowed buffer types:"), _allowedBufferTypes = new QLabel(this)); - layout->addRow(tr("Minimum activity:"), _minimumActivity = new QLabel(this)); + layout->addRow(tr("Allowed buffer types:"), _allowedBufferTypes = new QLabel(this)); + layout->addRow(tr("Minimum activity:"), _minimumActivity = new QLabel(this)); - layout->addRow(tr("Is initialized:"), _isInitialized = new QLabel(this)); + layout->addRow(tr("Is initialized:"), _isInitialized = new QLabel(this)); - update(); - connect(Client::bufferViewOverlay(), SIGNAL(hasChanged()), this, SLOT(update())); + update(); + connect(Client::bufferViewOverlay(), SIGNAL(hasChanged()), this, SLOT(update())); } -void DebugBufferViewOverlay::update() { - BufferViewOverlay *overlay = Client::bufferViewOverlay(); - - _allNetworks->setText(overlay->allNetworks() ? "yes" : "no"); - - QStringList ids; - foreach(int bufferViewId, overlay->bufferViewIds()) { - ids << QString::number(bufferViewId); - } - _bufferViews->setText(ids.join(", ")); - - ids.clear(); - foreach(NetworkId networkId, overlay->networkIds()) { - ids << QString::number(networkId.toInt()); - } - _networks->setText(ids.join(", ")); - - ids.clear(); - foreach(BufferId bufferId, overlay->bufferIds()) { - ids << QString::number(bufferId.toInt()); - } - _bufferIds->setText(ids.join(", ")); - - ids.clear(); - foreach(BufferId bufferId, overlay->removedBufferIds()) { - ids << QString::number(bufferId.toInt()); - } - _removedBufferIds->setText(ids.join(", ")); - - ids.clear(); - foreach(BufferId bufferId, overlay->tempRemovedBufferIds()) { - ids << QString::number(bufferId.toInt()); - } - _tempRemovedBufferIds->setText(ids.join(", ")); - - _allowedBufferTypes->setText(QString::number(overlay->allowedBufferTypes())); - _minimumActivity->setText(QString::number(overlay->minimumActivity())); - - _isInitialized->setText(overlay->isInitialized() ? "yes" : "no"); + +void DebugBufferViewOverlay::update() +{ + BufferViewOverlay *overlay = Client::bufferViewOverlay(); + + _allNetworks->setText(overlay->allNetworks() ? "yes" : "no"); + + QStringList ids; + foreach(int bufferViewId, overlay->bufferViewIds()) { + ids << QString::number(bufferViewId); + } + _bufferViews->setText(ids.join(", ")); + + ids.clear(); + foreach(NetworkId networkId, overlay->networkIds()) { + ids << QString::number(networkId.toInt()); + } + _networks->setText(ids.join(", ")); + + ids.clear(); + foreach(BufferId bufferId, overlay->bufferIds()) { + ids << QString::number(bufferId.toInt()); + } + _bufferIds->setText(ids.join(", ")); + + ids.clear(); + foreach(BufferId bufferId, overlay->removedBufferIds()) { + ids << QString::number(bufferId.toInt()); + } + _removedBufferIds->setText(ids.join(", ")); + + ids.clear(); + foreach(BufferId bufferId, overlay->tempRemovedBufferIds()) { + ids << QString::number(bufferId.toInt()); + } + _tempRemovedBufferIds->setText(ids.join(", ")); + + _allowedBufferTypes->setText(QString::number(overlay->allowedBufferTypes())); + _minimumActivity->setText(QString::number(overlay->minimumActivity())); + + _isInitialized->setText(overlay->isInitialized() ? "yes" : "no"); } diff --git a/src/qtui/debugbufferviewoverlay.h b/src/qtui/debugbufferviewoverlay.h index 101ffa25..9d7908fc 100644 --- a/src/qtui/debugbufferviewoverlay.h +++ b/src/qtui/debugbufferviewoverlay.h @@ -27,28 +27,30 @@ class QLabel; class QLineEdit; class QTextEdit; -class DebugBufferViewOverlay : public QWidget { - Q_OBJECT +class DebugBufferViewOverlay : public QWidget +{ + Q_OBJECT public: - DebugBufferViewOverlay(QWidget *parent = 0); + DebugBufferViewOverlay(QWidget *parent = 0); private slots: - void update(); + void update(); private: - Ui::DebugBufferViewOverlay ui; - QLineEdit *_bufferViews; - QLabel *_allNetworks; - QLineEdit *_networks; - QTextEdit *_bufferIds; - QTextEdit *_removedBufferIds; - QTextEdit *_tempRemovedBufferIds; - QLabel *_addBuffersAutomatically; - QLabel *_hideInactiveBuffers; - QLabel *_allowedBufferTypes; - QLabel *_minimumActivity; - QLabel *_isInitialized; + Ui::DebugBufferViewOverlay ui; + QLineEdit *_bufferViews; + QLabel *_allNetworks; + QLineEdit *_networks; + QTextEdit *_bufferIds; + QTextEdit *_removedBufferIds; + QTextEdit *_tempRemovedBufferIds; + QLabel *_addBuffersAutomatically; + QLabel *_hideInactiveBuffers; + QLabel *_allowedBufferTypes; + QLabel *_minimumActivity; + QLabel *_isInitialized; }; + #endif //DEBUGBUFFERVIEWOVERLAY_H diff --git a/src/qtui/debugconsole.cpp b/src/qtui/debugconsole.cpp index 9bda37ed..60a57b5d 100644 --- a/src/qtui/debugconsole.cpp +++ b/src/qtui/debugconsole.cpp @@ -23,24 +23,29 @@ #include "signalproxy.h" DebugConsole::DebugConsole(QWidget *parent) - : QDialog(parent) + : QDialog(parent) { - ui.setupUi(this); - - Client::signalProxy()->attachSignal(this, SIGNAL(scriptRequest(QString))); - Client::signalProxy()->attachSlot(SIGNAL(scriptResult(QString)), this, SLOT(scriptResult(QString))); + ui.setupUi(this); + Client::signalProxy()->attachSignal(this, SIGNAL(scriptRequest(QString))); + Client::signalProxy()->attachSlot(SIGNAL(scriptResult(QString)), this, SLOT(scriptResult(QString))); } -DebugConsole::~DebugConsole() { + +DebugConsole::~DebugConsole() +{ } -void DebugConsole::on_evalButton_clicked() { - if(ui.selectCore->isChecked()) { - emit scriptRequest(ui.scriptEdit->toPlainText()); - } + +void DebugConsole::on_evalButton_clicked() +{ + if (ui.selectCore->isChecked()) { + emit scriptRequest(ui.scriptEdit->toPlainText()); + } } -void DebugConsole::scriptResult(QString result) { - ui.resultLabel->setText(result); + +void DebugConsole::scriptResult(QString result) +{ + ui.resultLabel->setText(result); } diff --git a/src/qtui/debugconsole.h b/src/qtui/debugconsole.h index 26f25e2e..754e655e 100644 --- a/src/qtui/debugconsole.h +++ b/src/qtui/debugconsole.h @@ -23,24 +23,26 @@ #include "ui_debugconsole.h" -class DebugConsole : public QDialog { - Q_OBJECT +class DebugConsole : public QDialog +{ + Q_OBJECT public: - DebugConsole(QWidget *parent = 0); - virtual ~DebugConsole(); + DebugConsole(QWidget *parent = 0); + virtual ~DebugConsole(); public slots: - void scriptResult(QString result); + void scriptResult(QString result); signals: - void scriptRequest(QString script); + void scriptRequest(QString script); private slots: - void on_evalButton_clicked(); - + void on_evalButton_clicked(); + private: - Ui::DebugConsole ui; + Ui::DebugConsole ui; }; + #endif diff --git a/src/qtui/debuglogwidget.cpp b/src/qtui/debuglogwidget.cpp index 31e636e4..af9b4289 100644 --- a/src/qtui/debuglogwidget.cpp +++ b/src/qtui/debuglogwidget.cpp @@ -23,18 +23,19 @@ #include "client.h" DebugLogWidget::DebugLogWidget(QWidget *parent) - : QWidget(parent) + : QWidget(parent) { - ui.setupUi(this); - setAttribute(Qt::WA_DeleteOnClose, true); - ui.textEdit->setPlainText(Client::debugLog()); - connect(Client::instance(), SIGNAL(logUpdated(const QString &)), this, SLOT(logUpdated(const QString &))); - ui.textEdit->setReadOnly(true); + ui.setupUi(this); + setAttribute(Qt::WA_DeleteOnClose, true); + ui.textEdit->setPlainText(Client::debugLog()); + connect(Client::instance(), SIGNAL(logUpdated(const QString &)), this, SLOT(logUpdated(const QString &))); + ui.textEdit->setReadOnly(true); } -void DebugLogWidget::logUpdated(const QString &msg) { - ui.textEdit->moveCursor(QTextCursor::End); - ui.textEdit->insertPlainText(msg); - ui.textEdit->moveCursor(QTextCursor::End); -} +void DebugLogWidget::logUpdated(const QString &msg) +{ + ui.textEdit->moveCursor(QTextCursor::End); + ui.textEdit->insertPlainText(msg); + ui.textEdit->moveCursor(QTextCursor::End); +} diff --git a/src/qtui/debuglogwidget.h b/src/qtui/debuglogwidget.h index 2e91d559..5aa1cc0e 100644 --- a/src/qtui/debuglogwidget.h +++ b/src/qtui/debuglogwidget.h @@ -23,17 +23,19 @@ #include "ui_debuglogwidget.h" -class DebugLogWidget : public QWidget { - Q_OBJECT +class DebugLogWidget : public QWidget +{ + Q_OBJECT public: - DebugLogWidget(QWidget *parent = 0); + DebugLogWidget(QWidget *parent = 0); private slots: - void logUpdated(const QString &msg); + void logUpdated(const QString &msg); private: - Ui::DebugLogWidget ui; + Ui::DebugLogWidget ui; }; + #endif //DEBUGLOGWIDGET_H diff --git a/src/qtui/debugmessagemodelfilter.cpp b/src/qtui/debugmessagemodelfilter.cpp index 664e2c56..179861ef 100644 --- a/src/qtui/debugmessagemodelfilter.cpp +++ b/src/qtui/debugmessagemodelfilter.cpp @@ -23,33 +23,37 @@ #include "messagemodel.h" DebugMessageModelFilter::DebugMessageModelFilter(QObject *parent) - : QSortFilterProxyModel(parent) + : QSortFilterProxyModel(parent) { } -QVariant DebugMessageModelFilter::headerData(int section, Qt::Orientation orientation, int role) const { - if(orientation != Qt::Horizontal || role != Qt::DisplayRole) - return QVariant(); - - switch(section) { - case 0: - return "MessageId"; - case 1: - return "Sender"; - case 2: - return "Message"; - default: - return QVariant(); - } + +QVariant DebugMessageModelFilter::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation != Qt::Horizontal || role != Qt::DisplayRole) + return QVariant(); + + switch (section) { + case 0: + return "MessageId"; + case 1: + return "Sender"; + case 2: + return "Message"; + default: + return QVariant(); + } } -QVariant DebugMessageModelFilter::data(const QModelIndex &index, int role) const { - if(index.column() != 0 || role != Qt::DisplayRole) - return QSortFilterProxyModel::data(index, role); - if(!sourceModel()) - return QVariant(); +QVariant DebugMessageModelFilter::data(const QModelIndex &index, int role) const +{ + if (index.column() != 0 || role != Qt::DisplayRole) + return QSortFilterProxyModel::data(index, role); + + if (!sourceModel()) + return QVariant(); - QModelIndex source_index = mapToSource(index); - return sourceModel()->data(source_index, MessageModel::MsgIdRole).value().toInt(); + QModelIndex source_index = mapToSource(index); + return sourceModel()->data(source_index, MessageModel::MsgIdRole).value().toInt(); } diff --git a/src/qtui/debugmessagemodelfilter.h b/src/qtui/debugmessagemodelfilter.h index ac06891d..bb6dd929 100644 --- a/src/qtui/debugmessagemodelfilter.h +++ b/src/qtui/debugmessagemodelfilter.h @@ -23,13 +23,15 @@ #include -class DebugMessageModelFilter : public QSortFilterProxyModel { - Q_OBJECT +class DebugMessageModelFilter : public QSortFilterProxyModel +{ + Q_OBJECT public: - DebugMessageModelFilter(QObject *parent = 0); - QVariant headerData(int section, Qt::Orientation orientation, int role) const; - virtual QVariant data(const QModelIndex &index, int role) const; + DebugMessageModelFilter(QObject *parent = 0); + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + virtual QVariant data(const QModelIndex &index, int role) const; }; + #endif //DEBUGMESSAGEMODELFILTER_H diff --git a/src/qtui/indicatornotificationbackend.cpp b/src/qtui/indicatornotificationbackend.cpp index 281fe98b..59c20b8d 100644 --- a/src/qtui/indicatornotificationbackend.cpp +++ b/src/qtui/indicatornotificationbackend.cpp @@ -33,162 +33,193 @@ #define STR(x) #x #define XSTR(x) STR(x) -class Indicator : public QIndicate::Indicator { +class Indicator : public QIndicate::Indicator +{ public: - uint lastNotificationId; + uint lastNotificationId; }; + IndicatorNotificationBackend::IndicatorNotificationBackend(QObject *parent) - : AbstractNotificationBackend(parent) + : AbstractNotificationBackend(parent) { - NotificationSettings notificationSettings; - _enabled = notificationSettings.value("Indicator/Enabled", false).toBool(); + NotificationSettings notificationSettings; + _enabled = notificationSettings.value("Indicator/Enabled", false).toBool(); - notificationSettings.notify("Indicator/Enabled", this, SLOT(enabledChanged(const QVariant &))); + notificationSettings.notify("Indicator/Enabled", this, SLOT(enabledChanged(const QVariant &))); - _server = QIndicate::Server::defaultInstance(); - _server->setType("message.irc"); - QString desktopFile = QString("%1/%2.desktop") - .arg(XSTR(XDG_APPS_INSTALL_DIR)) - .arg(QCoreApplication::applicationFilePath().section('/', -1)); - _server->setDesktopFile(desktopFile); - connect(_server, SIGNAL(serverDisplay()), SLOT(activateMainWidget())); + _server = QIndicate::Server::defaultInstance(); + _server->setType("message.irc"); + QString desktopFile = QString("%1/%2.desktop") + .arg(XSTR(XDG_APPS_INSTALL_DIR)) + .arg(QCoreApplication::applicationFilePath().section('/', -1)); + _server->setDesktopFile(desktopFile); + connect(_server, SIGNAL(serverDisplay()), SLOT(activateMainWidget())); - if (_enabled) { - _server->show(); - } + if (_enabled) { + _server->show(); + } } -IndicatorNotificationBackend::~IndicatorNotificationBackend() { - qDeleteAll(_indicatorHash); + +IndicatorNotificationBackend::~IndicatorNotificationBackend() +{ + qDeleteAll(_indicatorHash); } -void IndicatorNotificationBackend::activateMainWidget() { - GraphicalUi::activateMainWidget(); + +void IndicatorNotificationBackend::activateMainWidget() +{ + GraphicalUi::activateMainWidget(); } -void IndicatorNotificationBackend::notify(const Notification ¬ification) { - if(!_enabled) { - return; - } - if (notification.type != Highlight && notification.type != PrivMsg) { - return; - } - BufferId bufferId = notification.bufferId; - Indicator *indicator = _indicatorHash.value(bufferId); - if(!indicator) { - indicator = new Indicator; - _indicatorHash.insert(bufferId, indicator); - connect(indicator, SIGNAL(display(QIndicate::Indicator*)), - SLOT(indicatorDisplayed(QIndicate::Indicator*))); - } - indicator->lastNotificationId = notification.notificationId; - - BufferInfo::Type type = Client::networkModel()->bufferType(bufferId); - QString name; - if (type == BufferInfo::QueryBuffer) { - name = notification.sender; - } else { - name = QString("%1 (%2)") - .arg(Client::networkModel()->bufferName(bufferId)) - .arg(notification.sender); - } - indicator->setNameProperty(name); - - indicator->setTimeProperty(QDateTime::currentDateTime()); - - QModelIndex index = Client::networkModel()->bufferIndex(bufferId); - QVariant icon = QtUi::style()->bufferViewItemData(index, Qt::DecorationRole); - if (icon.canConvert()) { - QImage image = icon.value().toImage(); - indicator->setIconProperty(image); - } - - indicator->setDrawAttentionProperty(true); - indicator->show(); + +void IndicatorNotificationBackend::notify(const Notification ¬ification) +{ + if (!_enabled) { + return; + } + if (notification.type != Highlight && notification.type != PrivMsg) { + return; + } + BufferId bufferId = notification.bufferId; + Indicator *indicator = _indicatorHash.value(bufferId); + if (!indicator) { + indicator = new Indicator; + _indicatorHash.insert(bufferId, indicator); + connect(indicator, SIGNAL(display(QIndicate::Indicator *)), + SLOT(indicatorDisplayed(QIndicate::Indicator *))); + } + indicator->lastNotificationId = notification.notificationId; + + BufferInfo::Type type = Client::networkModel()->bufferType(bufferId); + QString name; + if (type == BufferInfo::QueryBuffer) { + name = notification.sender; + } + else { + name = QString("%1 (%2)") + .arg(Client::networkModel()->bufferName(bufferId)) + .arg(notification.sender); + } + indicator->setNameProperty(name); + + indicator->setTimeProperty(QDateTime::currentDateTime()); + + QModelIndex index = Client::networkModel()->bufferIndex(bufferId); + QVariant icon = QtUi::style()->bufferViewItemData(index, Qt::DecorationRole); + if (icon.canConvert()) { + QImage image = icon.value().toImage(); + indicator->setIconProperty(image); + } + + indicator->setDrawAttentionProperty(true); + indicator->show(); } -void IndicatorNotificationBackend::close(uint notificationId) { - // If we find an indicator whose lastNotificationId is notificationId, we - // delete it - IndicatorHash::Iterator - it = _indicatorHash.begin(), - end = _indicatorHash.end(); - for (; it != end; ++it) { - if (it.value()->lastNotificationId == notificationId) { - break; +void IndicatorNotificationBackend::close(uint notificationId) +{ + // If we find an indicator whose lastNotificationId is notificationId, we + // delete it + + IndicatorHash::Iterator + it = _indicatorHash.begin(), + end = _indicatorHash.end(); + for (; it != end; ++it) { + if (it.value()->lastNotificationId == notificationId) { + break; + } + } + if (it == end) { + // Not found, maybe there was no indicator for this notification or another + // notification happened after + return; } - } - if (it == end) { - // Not found, maybe there was no indicator for this notification or another - // notification happened after - return; - } - _indicatorHash.erase(it); - delete it.value(); + _indicatorHash.erase(it); + delete it.value(); } -void IndicatorNotificationBackend::enabledChanged(const QVariant &v) { - _enabled = v.toBool(); - if (_enabled) { - _server->show(); - // TODO: Create indicators for existing highlighted buffers? - } else { - _server->hide(); - qDeleteAll(_indicatorHash); - } + +void IndicatorNotificationBackend::enabledChanged(const QVariant &v) +{ + _enabled = v.toBool(); + if (_enabled) { + _server->show(); + // TODO: Create indicators for existing highlighted buffers? + } + else { + _server->hide(); + qDeleteAll(_indicatorHash); + } } -void IndicatorNotificationBackend::indicatorDisplayed(QIndicate::Indicator *_indicator) { - Indicator *indicator = static_cast(_indicator); - emit activated(indicator->lastNotificationId); + +void IndicatorNotificationBackend::indicatorDisplayed(QIndicate::Indicator *_indicator) +{ + Indicator *indicator = static_cast(_indicator); + emit activated(indicator->lastNotificationId); } -SettingsPage *IndicatorNotificationBackend::createConfigWidget() const { - return new ConfigWidget(); + +SettingsPage *IndicatorNotificationBackend::createConfigWidget() const +{ + return new ConfigWidget(); } + /***************************************************************************/ IndicatorNotificationBackend::ConfigWidget::ConfigWidget(QWidget *parent) -: SettingsPage("Internal", "IndicatorNotification", parent) + : SettingsPage("Internal", "IndicatorNotification", parent) { - ui.setupUi(this); - // FIXME find proper icon (this one is used by the plasmoid as well) - ui.enabled->setIcon(SmallIcon("mail-message-new")); + ui.setupUi(this); + // FIXME find proper icon (this one is used by the plasmoid as well) + ui.enabled->setIcon(SmallIcon("mail-message-new")); - connect(ui.enabled, SIGNAL(toggled(bool)), SLOT(widgetChanged())); + connect(ui.enabled, SIGNAL(toggled(bool)), SLOT(widgetChanged())); } -IndicatorNotificationBackend::ConfigWidget::~ConfigWidget() { + +IndicatorNotificationBackend::ConfigWidget::~ConfigWidget() +{ } -void IndicatorNotificationBackend::ConfigWidget::widgetChanged() { - bool changed = enabled != ui.enabled->isChecked(); - if(changed != hasChanged()) setChangedState(changed); +void IndicatorNotificationBackend::ConfigWidget::widgetChanged() +{ + bool changed = enabled != ui.enabled->isChecked(); + + if (changed != hasChanged()) setChangedState(changed); } -bool IndicatorNotificationBackend::ConfigWidget::hasDefaults() const { - return true; + +bool IndicatorNotificationBackend::ConfigWidget::hasDefaults() const +{ + return true; } -void IndicatorNotificationBackend::ConfigWidget::defaults() { - ui.enabled->setChecked(false); - widgetChanged(); + +void IndicatorNotificationBackend::ConfigWidget::defaults() +{ + ui.enabled->setChecked(false); + widgetChanged(); } -void IndicatorNotificationBackend::ConfigWidget::load() { - NotificationSettings s; - enabled = s.value("Indicator/Enabled", false).toBool(); - ui.enabled->setChecked(enabled); - setChangedState(false); +void IndicatorNotificationBackend::ConfigWidget::load() +{ + NotificationSettings s; + enabled = s.value("Indicator/Enabled", false).toBool(); + + ui.enabled->setChecked(enabled); + setChangedState(false); } -void IndicatorNotificationBackend::ConfigWidget::save() { - NotificationSettings s; - s.setValue("Indicator/Enabled", ui.enabled->isChecked()); - load(); + +void IndicatorNotificationBackend::ConfigWidget::save() +{ + NotificationSettings s; + s.setValue("Indicator/Enabled", ui.enabled->isChecked()); + load(); } diff --git a/src/qtui/indicatornotificationbackend.h b/src/qtui/indicatornotificationbackend.h index 4ccbe442..237af5a7 100644 --- a/src/qtui/indicatornotificationbackend.h +++ b/src/qtui/indicatornotificationbackend.h @@ -37,50 +37,54 @@ class Indicator; typedef QHash IndicatorHash; -class IndicatorNotificationBackend : public AbstractNotificationBackend { - Q_OBJECT +class IndicatorNotificationBackend : public AbstractNotificationBackend +{ + Q_OBJECT public: - IndicatorNotificationBackend(QObject *parent = 0); - ~IndicatorNotificationBackend(); + IndicatorNotificationBackend(QObject *parent = 0); + ~IndicatorNotificationBackend(); - void notify(const Notification &); - void close(uint notificationId); - virtual SettingsPage *createConfigWidget() const; + void notify(const Notification &); + void close(uint notificationId); + virtual SettingsPage *createConfigWidget() const; private slots: - void activateMainWidget(); - void enabledChanged(const QVariant &); - void indicatorDisplayed(QIndicate::Indicator *); + void activateMainWidget(); + void enabledChanged(const QVariant &); + void indicatorDisplayed(QIndicate::Indicator *); private: - class ConfigWidget; + class ConfigWidget; - bool _enabled; + bool _enabled; - QIndicate::Server *_server; - IndicatorHash _indicatorHash; + QIndicate::Server *_server; + IndicatorHash _indicatorHash; }; -class IndicatorNotificationBackend::ConfigWidget : public SettingsPage { - Q_OBJECT + +class IndicatorNotificationBackend::ConfigWidget : public SettingsPage +{ + Q_OBJECT public: - ConfigWidget(QWidget *parent = 0); - ~ConfigWidget(); + ConfigWidget(QWidget *parent = 0); + ~ConfigWidget(); - void save(); - void load(); - bool hasDefaults() const; - void defaults(); + void save(); + void load(); + bool hasDefaults() const; + void defaults(); private slots: - void widgetChanged(); + void widgetChanged(); private: - Ui::IndicatorNotificationConfigWidget ui; + Ui::IndicatorNotificationConfigWidget ui; - bool enabled; + bool enabled; }; + #endif diff --git a/src/qtui/inputwidget.cpp b/src/qtui/inputwidget.cpp index 33fe3a4e..3991b489 100644 --- a/src/qtui/inputwidget.cpp +++ b/src/qtui/inputwidget.cpp @@ -35,520 +35,596 @@ const int leftMargin = 3; InputWidget::InputWidget(QWidget *parent) - : AbstractItemView(parent), + : AbstractItemView(parent), _networkId(0) { - ui.setupUi(this); - connect(ui.ownNick, SIGNAL(activated(QString)), this, SLOT(changeNick(QString))); - - layout()->setAlignment(ui.ownNick, Qt::AlignBottom); - layout()->setAlignment(ui.inputEdit, Qt::AlignBottom); - layout()->setAlignment(ui.showStyleButton, Qt::AlignBottom); - layout()->setAlignment(ui.styleFrame, Qt::AlignBottom); + ui.setupUi(this); + connect(ui.ownNick, SIGNAL(activated(QString)), this, SLOT(changeNick(QString))); + + layout()->setAlignment(ui.ownNick, Qt::AlignBottom); + layout()->setAlignment(ui.inputEdit, Qt::AlignBottom); + layout()->setAlignment(ui.showStyleButton, Qt::AlignBottom); + layout()->setAlignment(ui.styleFrame, Qt::AlignBottom); + + ui.styleFrame->setVisible(false); + + setFocusProxy(ui.inputEdit); + ui.ownNick->setFocusProxy(ui.inputEdit); + + ui.ownNick->setSizeAdjustPolicy(QComboBox::AdjustToContents); + ui.ownNick->installEventFilter(new MouseWheelFilter(this)); + ui.inputEdit->installEventFilter(this); + + ui.inputEdit->setMinHeight(1); + ui.inputEdit->setMaxHeight(5); + ui.inputEdit->setMode(MultiLineEdit::MultiLine); + ui.inputEdit->setPasteProtectionEnabled(true); + + ui.boldButton->setIcon(SmallIcon("format-text-bold")); + ui.italicButton->setIcon(SmallIcon("format-text-italic")); + ui.underlineButton->setIcon(SmallIcon("format-text-underline")); + ui.textcolorButton->setIcon(SmallIcon("format-text-color")); + ui.highlightcolorButton->setIcon(SmallIcon("format-fill-color")); + + _colorMenu = new QMenu(); + _colorFillMenu = new QMenu(); + + QStringList names; + names << tr("White") << tr("Black") << tr("Dark blue") << tr("Dark green") << tr("Red") << tr("Dark red") << tr("Dark magenta") << tr("Orange") + << tr("Yellow") << tr("Green") << tr("Dark cyan") << tr("Cyan") << tr("Blue") << tr("Magenta") << tr("Dark gray") << tr("Light gray"); + + QPixmap pix(16, 16); + for (int i = 0; i < inputLine()->mircColorMap().count(); i++) { + pix.fill(inputLine()->mircColorMap().values()[i]); + _colorMenu->addAction(pix, names[i])->setData(inputLine()->mircColorMap().keys()[i]); + _colorFillMenu->addAction(pix, names[i])->setData(inputLine()->mircColorMap().keys()[i]); + } - ui.styleFrame->setVisible(false); + pix.fill(Qt::transparent); + _colorMenu->addAction(pix, tr("Clear Color"))->setData(""); + _colorFillMenu->addAction(pix, tr("Clear Color"))->setData(""); - setFocusProxy(ui.inputEdit); - ui.ownNick->setFocusProxy(ui.inputEdit); + ui.textcolorButton->setMenu(_colorMenu); + connect(_colorMenu, SIGNAL(triggered(QAction *)), this, SLOT(colorChosen(QAction *))); + ui.highlightcolorButton->setMenu(_colorFillMenu); + connect(_colorFillMenu, SIGNAL(triggered(QAction *)), this, SLOT(colorHighlightChosen(QAction *))); - ui.ownNick->setSizeAdjustPolicy(QComboBox::AdjustToContents); - ui.ownNick->installEventFilter(new MouseWheelFilter(this)); - ui.inputEdit->installEventFilter(this); + new TabCompleter(ui.inputEdit); - ui.inputEdit->setMinHeight(1); - ui.inputEdit->setMaxHeight(5); - ui.inputEdit->setMode(MultiLineEdit::MultiLine); - ui.inputEdit->setPasteProtectionEnabled(true); + UiStyleSettings fs("Fonts"); + fs.notify("UseCustomInputWidgetFont", this, SLOT(setUseCustomFont(QVariant))); + fs.notify("InputWidget", this, SLOT(setCustomFont(QVariant))); + if (fs.value("UseCustomInputWidgetFont", false).toBool()) + setCustomFont(fs.value("InputWidget", QFont())); - ui.boldButton->setIcon(SmallIcon("format-text-bold")); - ui.italicButton->setIcon(SmallIcon("format-text-italic")); - ui.underlineButton->setIcon(SmallIcon("format-text-underline")); - ui.textcolorButton->setIcon(SmallIcon("format-text-color")); - ui.highlightcolorButton->setIcon(SmallIcon("format-fill-color")); + UiSettings s("InputWidget"); - _colorMenu = new QMenu(); - _colorFillMenu = new QMenu(); +#ifdef HAVE_KDE + s.notify("EnableSpellCheck", this, SLOT(setEnableSpellCheck(QVariant))); + setEnableSpellCheck(s.value("EnableSpellCheck", false)); +#endif - QStringList names; - names << tr("White") << tr("Black") << tr("Dark blue") << tr("Dark green") << tr("Red") << tr("Dark red") << tr("Dark magenta") << tr("Orange") - << tr("Yellow") << tr("Green") << tr("Dark cyan") << tr("Cyan") << tr("Blue") << tr("Magenta") << tr("Dark gray") << tr("Light gray"); + s.notify("EnableEmacsMode", this, SLOT(setEnableEmacsMode(QVariant))); + setEnableEmacsMode(s.value("EnableEmacsMode", false)); - QPixmap pix(16, 16); - for (int i = 0; i < inputLine()->mircColorMap().count(); i++) { - pix.fill(inputLine()->mircColorMap().values()[i]); - _colorMenu->addAction(pix, names[i])->setData(inputLine()->mircColorMap().keys()[i]); - _colorFillMenu->addAction(pix, names[i])->setData(inputLine()->mircColorMap().keys()[i]); - } + s.notify("ShowNickSelector", this, SLOT(setShowNickSelector(QVariant))); + setShowNickSelector(s.value("ShowNickSelector", true)); - pix.fill(Qt::transparent); - _colorMenu->addAction(pix, tr("Clear Color"))->setData(""); - _colorFillMenu->addAction(pix, tr("Clear Color"))->setData(""); + s.notify("ShowStyleButtons", this, SLOT(setShowStyleButtons(QVariant))); + setShowStyleButtons(s.value("ShowStyleButtons", true)); - ui.textcolorButton->setMenu(_colorMenu); - connect(_colorMenu, SIGNAL(triggered(QAction*)), this, SLOT(colorChosen(QAction*))); - ui.highlightcolorButton->setMenu(_colorFillMenu); - connect(_colorFillMenu, SIGNAL(triggered(QAction*)), this, SLOT(colorHighlightChosen(QAction*))); + s.notify("EnablePerChatHistory", this, SLOT(setEnablePerChatHistory(QVariant))); + setEnablePerChatHistory(s.value("EnablePerChatHistory", false)); - new TabCompleter(ui.inputEdit); + s.notify("MaxNumLines", this, SLOT(setMaxLines(QVariant))); + setMaxLines(s.value("MaxNumLines", 5)); - UiStyleSettings fs("Fonts"); - fs.notify("UseCustomInputWidgetFont", this, SLOT(setUseCustomFont(QVariant))); - fs.notify("InputWidget", this, SLOT(setCustomFont(QVariant))); - if(fs.value("UseCustomInputWidgetFont", false).toBool()) - setCustomFont(fs.value("InputWidget", QFont())); + s.notify("EnableScrollBars", this, SLOT(setScrollBarsEnabled(QVariant))); + setScrollBarsEnabled(s.value("EnableScrollBars", true)); - UiSettings s("InputWidget"); + s.notify("EnableMultiLine", this, SLOT(setMultiLineEnabled(QVariant))); + setMultiLineEnabled(s.value("EnableMultiLine", true)); -#ifdef HAVE_KDE - s.notify("EnableSpellCheck", this, SLOT(setEnableSpellCheck(QVariant))); - setEnableSpellCheck(s.value("EnableSpellCheck", false)); -#endif + ActionCollection *coll = QtUi::actionCollection(); - s.notify("EnableEmacsMode", this, SLOT(setEnableEmacsMode(QVariant))); - setEnableEmacsMode(s.value("EnableEmacsMode", false)); + Action *activateInputline = coll->add("FocusInputLine"); + connect(activateInputline, SIGNAL(triggered()), SLOT(setFocus())); + activateInputline->setText(tr("Focus Input Line")); + activateInputline->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L)); - s.notify("ShowNickSelector", this, SLOT(setShowNickSelector(QVariant))); - setShowNickSelector(s.value("ShowNickSelector", true)); + connect(inputLine(), SIGNAL(textEntered(QString)), SLOT(onTextEntered(QString)), Qt::QueuedConnection); // make sure the line is already reset, bug #984 + connect(inputLine(), SIGNAL(currentCharFormatChanged(QTextCharFormat)), this, SLOT(currentCharFormatChanged(QTextCharFormat))); +} - s.notify("ShowStyleButtons", this, SLOT(setShowStyleButtons(QVariant))); - setShowStyleButtons(s.value("ShowStyleButtons", true)); - s.notify("EnablePerChatHistory", this, SLOT(setEnablePerChatHistory(QVariant))); - setEnablePerChatHistory(s.value("EnablePerChatHistory", false)); +InputWidget::~InputWidget() +{ +} - s.notify("MaxNumLines", this, SLOT(setMaxLines(QVariant))); - setMaxLines(s.value("MaxNumLines", 5)); - s.notify("EnableScrollBars", this, SLOT(setScrollBarsEnabled(QVariant))); - setScrollBarsEnabled(s.value("EnableScrollBars", true)); +void InputWidget::setUseCustomFont(const QVariant &v) +{ + if (v.toBool()) { + UiStyleSettings fs("Fonts"); + setCustomFont(fs.value("InputWidget")); + } + else + setCustomFont(QFont()); +} - s.notify("EnableMultiLine", this, SLOT(setMultiLineEnabled(QVariant))); - setMultiLineEnabled(s.value("EnableMultiLine", true)); - ActionCollection *coll = QtUi::actionCollection(); +void InputWidget::setCustomFont(const QVariant &v) +{ + QFont font = v.value(); + if (font.family().isEmpty()) + font = QApplication::font(); + // we don't want font styles as this conflics with mirc code richtext editing + font.setBold(false); + font.setItalic(false); + font.setUnderline(false); + font.setStrikeOut(false); + ui.inputEdit->setCustomFont(font); +} - Action *activateInputline = coll->add("FocusInputLine"); - connect(activateInputline, SIGNAL(triggered()), SLOT(setFocus())); - activateInputline->setText(tr("Focus Input Line")); - activateInputline->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L)); - connect(inputLine(), SIGNAL(textEntered(QString)), SLOT(onTextEntered(QString)), Qt::QueuedConnection); // make sure the line is already reset, bug #984 - connect(inputLine(), SIGNAL(currentCharFormatChanged(QTextCharFormat)), this, SLOT(currentCharFormatChanged(QTextCharFormat))); +void InputWidget::setEnableSpellCheck(const QVariant &v) +{ + ui.inputEdit->setSpellCheckEnabled(v.toBool()); } -InputWidget::~InputWidget() { -} -void InputWidget::setUseCustomFont(const QVariant &v) { - if(v.toBool()) { - UiStyleSettings fs("Fonts"); - setCustomFont(fs.value("InputWidget")); - } else - setCustomFont(QFont()); +void InputWidget::setEnableEmacsMode(const QVariant &v) +{ + ui.inputEdit->setEmacsMode(v.toBool()); } -void InputWidget::setCustomFont(const QVariant &v) { - QFont font = v.value(); - if(font.family().isEmpty()) - font = QApplication::font(); - // we don't want font styles as this conflics with mirc code richtext editing - font.setBold(false); - font.setItalic(false); - font.setUnderline(false); - font.setStrikeOut(false); - ui.inputEdit->setCustomFont(font); -} -void InputWidget::setEnableSpellCheck(const QVariant &v) { - ui.inputEdit->setSpellCheckEnabled(v.toBool()); +void InputWidget::setShowNickSelector(const QVariant &v) +{ + ui.ownNick->setVisible(v.toBool()); } -void InputWidget::setEnableEmacsMode(const QVariant &v) { - ui.inputEdit->setEmacsMode(v.toBool()); -} -void InputWidget::setShowNickSelector(const QVariant &v) { - ui.ownNick->setVisible(v.toBool()); +void InputWidget::setShowStyleButtons(const QVariant &v) +{ + ui.showStyleButton->setVisible(v.toBool()); } -void InputWidget::setShowStyleButtons(const QVariant &v) { - ui.showStyleButton->setVisible(v.toBool()); -} -void InputWidget::setEnablePerChatHistory(const QVariant &v) { - _perChatHistory = v.toBool(); +void InputWidget::setEnablePerChatHistory(const QVariant &v) +{ + _perChatHistory = v.toBool(); } -void InputWidget::setMaxLines(const QVariant &v) { - ui.inputEdit->setMaxHeight(v.toInt()); -} -void InputWidget::setScrollBarsEnabled(const QVariant &v) { - ui.inputEdit->setScrollBarsEnabled(v.toBool()); +void InputWidget::setMaxLines(const QVariant &v) +{ + ui.inputEdit->setMaxHeight(v.toInt()); } -void InputWidget::setMultiLineEnabled(const QVariant &v) { - ui.inputEdit->setMode(v.toBool()? MultiLineEdit::MultiLine : MultiLineEdit::SingleLine); + +void InputWidget::setScrollBarsEnabled(const QVariant &v) +{ + ui.inputEdit->setScrollBarsEnabled(v.toBool()); } -bool InputWidget::eventFilter(QObject *watched, QEvent *event) { - if(event->type() != QEvent::KeyPress) - return false; - QKeyEvent *keyEvent = static_cast(event); +void InputWidget::setMultiLineEnabled(const QVariant &v) +{ + ui.inputEdit->setMode(v.toBool() ? MultiLineEdit::MultiLine : MultiLineEdit::SingleLine); +} + - // keys from BufferView should be sent to (and focus) the input line - BufferView *view = qobject_cast(watched); - if(view) { - if(keyEvent->text().length() == 1 && !(keyEvent->modifiers() & (Qt::ControlModifier ^ Qt::AltModifier)) ) { // normal key press - QChar c = keyEvent->text().at(0); - if(c.isLetterOrNumber() || c.isSpace() || c.isPunct() || c.isSymbol()) { - setFocus(); - QCoreApplication::sendEvent(inputLine(), keyEvent); - return true; - } +bool InputWidget::eventFilter(QObject *watched, QEvent *event) +{ + if (event->type() != QEvent::KeyPress) + return false; + + QKeyEvent *keyEvent = static_cast(event); + + // keys from BufferView should be sent to (and focus) the input line + BufferView *view = qobject_cast(watched); + if (view) { + if (keyEvent->text().length() == 1 && !(keyEvent->modifiers() & (Qt::ControlModifier ^ Qt::AltModifier))) { // normal key press + QChar c = keyEvent->text().at(0); + if (c.isLetterOrNumber() || c.isSpace() || c.isPunct() || c.isSymbol()) { + setFocus(); + QCoreApplication::sendEvent(inputLine(), keyEvent); + return true; + } + } + return false; } - return false; - } else if(watched == ui.inputEdit) { - if(keyEvent->matches(QKeySequence::Find)) { - QAction *act = GraphicalUi::actionCollection()->action("ToggleSearchBar"); - if(act) { - act->toggle(); - return true; - } + else if (watched == ui.inputEdit) { + if (keyEvent->matches(QKeySequence::Find)) { + QAction *act = GraphicalUi::actionCollection()->action("ToggleSearchBar"); + if (act) { + act->toggle(); + return true; + } + } + return false; } return false; - } - return false; -} - -void InputWidget::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { - BufferId currentBufferId = current.data(NetworkModel::BufferIdRole).value(); - BufferId previousBufferId = previous.data(NetworkModel::BufferIdRole).value(); - - if (_perChatHistory) { - //backup - historyMap[previousBufferId].history = inputLine()->history(); - historyMap[previousBufferId].tempHistory = inputLine()->tempHistory(); - historyMap[previousBufferId].idx = inputLine()->idx(); - historyMap[previousBufferId].inputLine = inputLine()->html(); - - //restore - inputLine()->setHistory(historyMap[currentBufferId].history); - inputLine()->setTempHistory(historyMap[currentBufferId].tempHistory); - inputLine()->setIdx(historyMap[currentBufferId].idx); - inputLine()->setHtml(historyMap[currentBufferId].inputLine); - inputLine()->moveCursor(QTextCursor::End,QTextCursor::MoveAnchor); - - // FIXME this really should be in MultiLineEdit (and the const int on top removed) - QTextBlockFormat format = inputLine()->textCursor().blockFormat(); - format.setLeftMargin(leftMargin); // we want a little space between the frame and the contents - inputLine()->textCursor().setBlockFormat(format); - } - - NetworkId networkId = current.data(NetworkModel::NetworkIdRole).value(); - if(networkId == _networkId) - return; - - setNetwork(networkId); - updateNickSelector(); - updateEnabledState(); -} - -void InputWidget::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { - QItemSelectionRange changedArea(topLeft, bottomRight); - if(changedArea.contains(selectionModel()->currentIndex())) { +} + + +void InputWidget::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) +{ + BufferId currentBufferId = current.data(NetworkModel::BufferIdRole).value(); + BufferId previousBufferId = previous.data(NetworkModel::BufferIdRole).value(); + + if (_perChatHistory) { + //backup + historyMap[previousBufferId].history = inputLine()->history(); + historyMap[previousBufferId].tempHistory = inputLine()->tempHistory(); + historyMap[previousBufferId].idx = inputLine()->idx(); + historyMap[previousBufferId].inputLine = inputLine()->html(); + + //restore + inputLine()->setHistory(historyMap[currentBufferId].history); + inputLine()->setTempHistory(historyMap[currentBufferId].tempHistory); + inputLine()->setIdx(historyMap[currentBufferId].idx); + inputLine()->setHtml(historyMap[currentBufferId].inputLine); + inputLine()->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor); + + // FIXME this really should be in MultiLineEdit (and the const int on top removed) + QTextBlockFormat format = inputLine()->textCursor().blockFormat(); + format.setLeftMargin(leftMargin); // we want a little space between the frame and the contents + inputLine()->textCursor().setBlockFormat(format); + } + + NetworkId networkId = current.data(NetworkModel::NetworkIdRole).value(); + if (networkId == _networkId) + return; + + setNetwork(networkId); + updateNickSelector(); updateEnabledState(); - } +} + + +void InputWidget::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) +{ + QItemSelectionRange changedArea(topLeft, bottomRight); + if (changedArea.contains(selectionModel()->currentIndex())) { + updateEnabledState(); + } }; -void InputWidget::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { - NetworkId networkId; - QModelIndex child; - for(int row = start; row <= end; row++) { - child = model()->index(row, 0, parent); - if(NetworkModel::NetworkItemType != child.data(NetworkModel::ItemTypeRole).toInt()) - continue; - networkId = child.data(NetworkModel::NetworkIdRole).value(); - if(networkId == _networkId) { - setNetwork(0); - updateNickSelector(); - return; +void InputWidget::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) +{ + NetworkId networkId; + QModelIndex child; + for (int row = start; row <= end; row++) { + child = model()->index(row, 0, parent); + if (NetworkModel::NetworkItemType != child.data(NetworkModel::ItemTypeRole).toInt()) + continue; + networkId = child.data(NetworkModel::NetworkIdRole).value(); + if (networkId == _networkId) { + setNetwork(0); + updateNickSelector(); + return; + } } - } } -void InputWidget::updateEnabledState() { +void InputWidget::updateEnabledState() +{ // FIXME: Find a visualization for this that does not disable the widget! // Disabling kills global action shortcuts, plus users sometimes need/want to enter text // even in inactive channels. #if 0 - QModelIndex currentIndex = selectionModel()->currentIndex(); - - const Network *net = Client::networkModel()->networkByIndex(currentIndex); - bool enabled = false; - if(net) { - // disable inputline if it's a channelbuffer we parted from or... - enabled = (currentIndex.data(NetworkModel::ItemActiveRole).value() || (currentIndex.data(NetworkModel::BufferTypeRole).toInt() != BufferInfo::ChannelBuffer)); - // ... if we're not connected to the network at all - enabled &= net->isConnected(); - } - - ui.inputEdit->setEnabled(enabled); + QModelIndex currentIndex = selectionModel()->currentIndex(); + + const Network *net = Client::networkModel()->networkByIndex(currentIndex); + bool enabled = false; + if (net) { + // disable inputline if it's a channelbuffer we parted from or... + enabled = (currentIndex.data(NetworkModel::ItemActiveRole).value() || (currentIndex.data(NetworkModel::BufferTypeRole).toInt() != BufferInfo::ChannelBuffer)); + // ... if we're not connected to the network at all + enabled &= net->isConnected(); + } + + ui.inputEdit->setEnabled(enabled); #endif } -const Network *InputWidget::currentNetwork() const { - return Client::network(_networkId); + +const Network *InputWidget::currentNetwork() const +{ + return Client::network(_networkId); } -BufferInfo InputWidget::currentBufferInfo() const { - return selectionModel()->currentIndex().data(NetworkModel::BufferInfoRole).value(); + +BufferInfo InputWidget::currentBufferInfo() const +{ + return selectionModel()->currentIndex().data(NetworkModel::BufferInfoRole).value(); }; -void InputWidget::setNetwork(NetworkId networkId) { - if(_networkId == networkId) - return; - - const Network *previousNet = Client::network(_networkId); - if(previousNet) { - disconnect(previousNet, 0, this, 0); - if(previousNet->me()) - disconnect(previousNet->me(), 0, this, 0); - } - - _networkId = networkId; - - const Network *network = Client::network(networkId); - if(network) { - connect(network, SIGNAL(identitySet(IdentityId)), this, SLOT(setIdentity(IdentityId))); - connectMyIrcUser(); - setIdentity(network->identity()); - } else { - setIdentity(0); - _networkId = 0; - } -} - -void InputWidget::connectMyIrcUser() { - const Network *network = currentNetwork(); - if(network->me()) { - connect(network->me(), SIGNAL(nickSet(const QString &)), this, SLOT(updateNickSelector())); - connect(network->me(), SIGNAL(userModesSet(QString)), this, SLOT(updateNickSelector())); - connect(network->me(), SIGNAL(userModesAdded(QString)), this, SLOT(updateNickSelector())); - connect(network->me(), SIGNAL(userModesRemoved(QString)), this, SLOT(updateNickSelector())); - connect(network->me(), SIGNAL(awaySet(bool)), this, SLOT(updateNickSelector())); - disconnect(network, SIGNAL(myNickSet(const QString &)), this, SLOT(connectMyIrcUser())); - updateNickSelector(); - } else { - connect(network, SIGNAL(myNickSet(const QString &)), this, SLOT(connectMyIrcUser())); - } +void InputWidget::setNetwork(NetworkId networkId) +{ + if (_networkId == networkId) + return; + + const Network *previousNet = Client::network(_networkId); + if (previousNet) { + disconnect(previousNet, 0, this, 0); + if (previousNet->me()) + disconnect(previousNet->me(), 0, this, 0); + } + + _networkId = networkId; + + const Network *network = Client::network(networkId); + if (network) { + connect(network, SIGNAL(identitySet(IdentityId)), this, SLOT(setIdentity(IdentityId))); + connectMyIrcUser(); + setIdentity(network->identity()); + } + else { + setIdentity(0); + _networkId = 0; + } +} + + +void InputWidget::connectMyIrcUser() +{ + const Network *network = currentNetwork(); + if (network->me()) { + connect(network->me(), SIGNAL(nickSet(const QString &)), this, SLOT(updateNickSelector())); + connect(network->me(), SIGNAL(userModesSet(QString)), this, SLOT(updateNickSelector())); + connect(network->me(), SIGNAL(userModesAdded(QString)), this, SLOT(updateNickSelector())); + connect(network->me(), SIGNAL(userModesRemoved(QString)), this, SLOT(updateNickSelector())); + connect(network->me(), SIGNAL(awaySet(bool)), this, SLOT(updateNickSelector())); + disconnect(network, SIGNAL(myNickSet(const QString &)), this, SLOT(connectMyIrcUser())); + updateNickSelector(); + } + else { + connect(network, SIGNAL(myNickSet(const QString &)), this, SLOT(connectMyIrcUser())); + } } -void InputWidget::setIdentity(IdentityId identityId) { - if(_identityId == identityId) - return; - const Identity *previousIdentity = Client::identity(_identityId); - if(previousIdentity) - disconnect(previousIdentity, 0, this, 0); +void InputWidget::setIdentity(IdentityId identityId) +{ + if (_identityId == identityId) + return; + + const Identity *previousIdentity = Client::identity(_identityId); + if (previousIdentity) + disconnect(previousIdentity, 0, this, 0); - _identityId = identityId; + _identityId = identityId; - const Identity *identity = Client::identity(identityId); - if(identity) { - connect(identity, SIGNAL(nicksSet(QStringList)), this, SLOT(updateNickSelector())); - } else { - _identityId = 0; - } - updateNickSelector(); + const Identity *identity = Client::identity(identityId); + if (identity) { + connect(identity, SIGNAL(nicksSet(QStringList)), this, SLOT(updateNickSelector())); + } + else { + _identityId = 0; + } + updateNickSelector(); } -void InputWidget::updateNickSelector() const { - ui.ownNick->clear(); - const Network *net = currentNetwork(); - if(!net) - return; +void InputWidget::updateNickSelector() const +{ + ui.ownNick->clear(); + + const Network *net = currentNetwork(); + if (!net) + return; - const Identity *identity = Client::identity(net->identity()); - if(!identity) { - qWarning() << "InputWidget::updateNickSelector(): can't find Identity for Network" << net->networkId() << "IdentityId:" << net->identity(); - return; - } + const Identity *identity = Client::identity(net->identity()); + if (!identity) { + qWarning() << "InputWidget::updateNickSelector(): can't find Identity for Network" << net->networkId() << "IdentityId:" << net->identity(); + return; + } - int nickIdx; - QStringList nicks = identity->nicks(); - if((nickIdx = nicks.indexOf(net->myNick())) == -1) { - nicks.prepend(net->myNick()); - nickIdx = 0; - } + int nickIdx; + QStringList nicks = identity->nicks(); + if ((nickIdx = nicks.indexOf(net->myNick())) == -1) { + nicks.prepend(net->myNick()); + nickIdx = 0; + } - if(nicks.isEmpty()) - return; + if (nicks.isEmpty()) + return; - IrcUser *me = net->me(); - if(me) { - nicks[nickIdx] = net->myNick(); - if(!me->userModes().isEmpty()) - nicks[nickIdx] += QString(" (+%1)").arg(me->userModes()); - } + IrcUser *me = net->me(); + if (me) { + nicks[nickIdx] = net->myNick(); + if (!me->userModes().isEmpty()) + nicks[nickIdx] += QString(" (+%1)").arg(me->userModes()); + } - ui.ownNick->addItems(nicks); + ui.ownNick->addItems(nicks); - if(me && me->isAway()) - ui.ownNick->setItemData(nickIdx, SmallIcon("user-away"), Qt::DecorationRole); + if (me && me->isAway()) + ui.ownNick->setItemData(nickIdx, SmallIcon("user-away"), Qt::DecorationRole); - ui.ownNick->setCurrentIndex(nickIdx); + ui.ownNick->setCurrentIndex(nickIdx); } -void InputWidget::changeNick(const QString &newNick) const { - const Network *net = currentNetwork(); - if(!net || net->isMyNick(newNick)) - return; - // we reset the nick selecter as we have no confirmation yet, that this will succeed. - // if the action succeeds it will be properly updated anyways. - updateNickSelector(); - Client::userInput(BufferInfo::fakeStatusBuffer(net->networkId()), QString("/NICK %1").arg(newNick)); +void InputWidget::changeNick(const QString &newNick) const +{ + const Network *net = currentNetwork(); + if (!net || net->isMyNick(newNick)) + return; + + // we reset the nick selecter as we have no confirmation yet, that this will succeed. + // if the action succeeds it will be properly updated anyways. + updateNickSelector(); + Client::userInput(BufferInfo::fakeStatusBuffer(net->networkId()), QString("/NICK %1").arg(newNick)); } -void InputWidget::onTextEntered(const QString &text) { - Client::userInput(currentBufferInfo(), text); - ui.boldButton->setChecked(false); - ui.underlineButton->setChecked(false); - ui.italicButton->setChecked(false); - QTextCharFormat fmt; - fmt.setFontWeight(QFont::Normal); - fmt.setFontUnderline(false); - fmt.setFontItalic(false); - fmt.clearForeground(); - fmt.clearBackground(); - inputLine()->setCurrentCharFormat(fmt); +void InputWidget::onTextEntered(const QString &text) +{ + Client::userInput(currentBufferInfo(), text); + ui.boldButton->setChecked(false); + ui.underlineButton->setChecked(false); + ui.italicButton->setChecked(false); + + QTextCharFormat fmt; + fmt.setFontWeight(QFont::Normal); + fmt.setFontUnderline(false); + fmt.setFontItalic(false); + fmt.clearForeground(); + fmt.clearBackground(); + inputLine()->setCurrentCharFormat(fmt); #ifdef HAVE_KDE - // Set highlighter back to active in case it was deactivated by too many errors. - if(ui.inputEdit->highlighter()) - ui.inputEdit->highlighter()->setActive(true); + // Set highlighter back to active in case it was deactivated by too many errors. + if (ui.inputEdit->highlighter()) + ui.inputEdit->highlighter()->setActive(true); #endif } -void InputWidget::mergeFormatOnSelection(const QTextCharFormat &format) { - QTextCursor cursor = inputLine()->textCursor(); - cursor.mergeCharFormat(format); - inputLine()->mergeCurrentCharFormat(format); + +void InputWidget::mergeFormatOnSelection(const QTextCharFormat &format) +{ + QTextCursor cursor = inputLine()->textCursor(); + cursor.mergeCharFormat(format); + inputLine()->mergeCurrentCharFormat(format); } -void InputWidget::setFormatOnSelection(const QTextCharFormat &format) { - QTextCursor cursor = inputLine()->textCursor(); - cursor.setCharFormat(format); - inputLine()->setCurrentCharFormat(format); + +void InputWidget::setFormatOnSelection(const QTextCharFormat &format) +{ + QTextCursor cursor = inputLine()->textCursor(); + cursor.setCharFormat(format); + inputLine()->setCurrentCharFormat(format); } -QTextCharFormat InputWidget::getFormatOfWordOrSelection() { - QTextCursor cursor = inputLine()->textCursor(); - return cursor.charFormat(); + +QTextCharFormat InputWidget::getFormatOfWordOrSelection() +{ + QTextCursor cursor = inputLine()->textCursor(); + return cursor.charFormat(); } -void InputWidget::currentCharFormatChanged(const QTextCharFormat &format) { - fontChanged(format.font()); + +void InputWidget::currentCharFormatChanged(const QTextCharFormat &format) +{ + fontChanged(format.font()); } -void InputWidget::on_boldButton_clicked(bool checked) { - QTextCharFormat fmt; - fmt.setFontWeight(checked ? QFont::Bold : QFont::Normal); - mergeFormatOnSelection(fmt); + +void InputWidget::on_boldButton_clicked(bool checked) +{ + QTextCharFormat fmt; + fmt.setFontWeight(checked ? QFont::Bold : QFont::Normal); + mergeFormatOnSelection(fmt); } -void InputWidget::on_underlineButton_clicked(bool checked) { - QTextCharFormat fmt; - fmt.setFontUnderline(checked); - mergeFormatOnSelection(fmt); + +void InputWidget::on_underlineButton_clicked(bool checked) +{ + QTextCharFormat fmt; + fmt.setFontUnderline(checked); + mergeFormatOnSelection(fmt); } -void InputWidget::on_italicButton_clicked(bool checked) { - QTextCharFormat fmt; - fmt.setFontItalic(checked); - mergeFormatOnSelection(fmt); + +void InputWidget::on_italicButton_clicked(bool checked) +{ + QTextCharFormat fmt; + fmt.setFontItalic(checked); + mergeFormatOnSelection(fmt); } + void InputWidget::fontChanged(const QFont &f) { - ui.boldButton->setChecked(f.bold()); - ui.italicButton->setChecked(f.italic()); - ui.underlineButton->setChecked(f.underline()); + ui.boldButton->setChecked(f.bold()); + ui.italicButton->setChecked(f.italic()); + ui.underlineButton->setChecked(f.underline()); } -void InputWidget::colorChosen(QAction *action) { - QTextCharFormat fmt; - QColor color; - if (qVariantValue(action->data()) == "") { - color = Qt::transparent; - fmt = getFormatOfWordOrSelection(); - fmt.clearForeground(); - setFormatOnSelection(fmt); - } - else { - color = QColor(inputLine()->rgbColorFromMirc(qVariantValue(action->data()))); - fmt.setForeground(color); - mergeFormatOnSelection(fmt); - } - ui.textcolorButton->setDefaultAction(action); - ui.textcolorButton->setIcon(createColorToolButtonIcon(SmallIcon("format-text-color"), color)); + +void InputWidget::colorChosen(QAction *action) +{ + QTextCharFormat fmt; + QColor color; + if (qVariantValue(action->data()) == "") { + color = Qt::transparent; + fmt = getFormatOfWordOrSelection(); + fmt.clearForeground(); + setFormatOnSelection(fmt); + } + else { + color = QColor(inputLine()->rgbColorFromMirc(qVariantValue(action->data()))); + fmt.setForeground(color); + mergeFormatOnSelection(fmt); + } + ui.textcolorButton->setDefaultAction(action); + ui.textcolorButton->setIcon(createColorToolButtonIcon(SmallIcon("format-text-color"), color)); } -void InputWidget::colorHighlightChosen(QAction *action) { - QTextCharFormat fmt; - QColor color; - if (qVariantValue(action->data()) == "") { - color = Qt::transparent; - fmt = getFormatOfWordOrSelection(); - fmt.clearBackground(); - setFormatOnSelection(fmt); - } - else { - color = QColor(inputLine()->rgbColorFromMirc(qVariantValue(action->data()))); - fmt.setBackground(color); - mergeFormatOnSelection(fmt); - } - ui.highlightcolorButton->setDefaultAction(action); - ui.highlightcolorButton->setIcon(createColorToolButtonIcon(SmallIcon("format-fill-color"), color)); + +void InputWidget::colorHighlightChosen(QAction *action) +{ + QTextCharFormat fmt; + QColor color; + if (qVariantValue(action->data()) == "") { + color = Qt::transparent; + fmt = getFormatOfWordOrSelection(); + fmt.clearBackground(); + setFormatOnSelection(fmt); + } + else { + color = QColor(inputLine()->rgbColorFromMirc(qVariantValue(action->data()))); + fmt.setBackground(color); + mergeFormatOnSelection(fmt); + } + ui.highlightcolorButton->setDefaultAction(action); + ui.highlightcolorButton->setIcon(createColorToolButtonIcon(SmallIcon("format-fill-color"), color)); } -void InputWidget::on_showStyleButton_toggled(bool checked) { - ui.styleFrame->setVisible(checked); - if (checked) { - ui.showStyleButton->setArrowType(Qt::LeftArrow); - } - else { - ui.showStyleButton->setArrowType(Qt::RightArrow); - } + +void InputWidget::on_showStyleButton_toggled(bool checked) +{ + ui.styleFrame->setVisible(checked); + if (checked) { + ui.showStyleButton->setArrowType(Qt::LeftArrow); + } + else { + ui.showStyleButton->setArrowType(Qt::RightArrow); + } } -QIcon InputWidget::createColorToolButtonIcon(const QIcon &icon, const QColor &color) { - QPixmap pixmap(16, 16); - pixmap.fill(Qt::transparent); - QPainter painter(&pixmap); - QPixmap image = icon.pixmap(16,16); - QRect target(0, 0, 16, 14); - QRect source(0, 0, 16, 14); - painter.fillRect(QRect(0, 14, 16, 16), color); - painter.drawPixmap(target, image, source); - return QIcon(pixmap); +QIcon InputWidget::createColorToolButtonIcon(const QIcon &icon, const QColor &color) +{ + QPixmap pixmap(16, 16); + pixmap.fill(Qt::transparent); + QPainter painter(&pixmap); + QPixmap image = icon.pixmap(16, 16); + QRect target(0, 0, 16, 14); + QRect source(0, 0, 16, 14); + painter.fillRect(QRect(0, 14, 16, 16), color); + painter.drawPixmap(target, image, source); + + return QIcon(pixmap); } + // MOUSE WHEEL FILTER MouseWheelFilter::MouseWheelFilter(QObject *parent) - : QObject(parent) + : QObject(parent) { } -bool MouseWheelFilter::eventFilter(QObject *obj, QEvent *event) { - if(event->type() != QEvent::Wheel) - return QObject::eventFilter(obj, event); - else - return true; + +bool MouseWheelFilter::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() != QEvent::Wheel) + return QObject::eventFilter(obj, event); + else + return true; } diff --git a/src/qtui/inputwidget.h b/src/qtui/inputwidget.h index a0721d50..33aa46a9 100644 --- a/src/qtui/inputwidget.h +++ b/src/qtui/inputwidget.h @@ -32,87 +32,90 @@ class MultiLineEdit; -class InputWidget : public AbstractItemView { - Q_OBJECT +class InputWidget : public AbstractItemView +{ + Q_OBJECT public: - InputWidget(QWidget *parent = 0); - virtual ~InputWidget(); + InputWidget(QWidget *parent = 0); + virtual ~InputWidget(); - const Network *currentNetwork() const; + const Network *currentNetwork() const; - inline MultiLineEdit* inputLine() const { return ui.inputEdit; } + inline MultiLineEdit *inputLine() const { return ui.inputEdit; } protected: - virtual bool eventFilter(QObject *watched, QEvent *event); + virtual bool eventFilter(QObject *watched, QEvent *event); protected slots: - virtual void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); - virtual void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); - virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + virtual void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); + virtual void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); + virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); private slots: - void setCustomFont(const QVariant &font); - void setUseCustomFont(const QVariant &); - void setEnableSpellCheck(const QVariant &); - void setEnableEmacsMode(const QVariant &); - void setShowNickSelector(const QVariant &); - void setShowStyleButtons(const QVariant &); - void setEnablePerChatHistory(const QVariant &); - void setMaxLines(const QVariant &); - void setMultiLineEnabled(const QVariant &); - void setScrollBarsEnabled(const QVariant &); - void onTextEntered(const QString &text); - void changeNick(const QString &newNick) const; - - void setNetwork(NetworkId networkId); - void setIdentity(IdentityId identityId); - void connectMyIrcUser(); - void updateNickSelector() const; - void updateEnabledState(); - - BufferInfo currentBufferInfo() const; - - void currentCharFormatChanged(const QTextCharFormat &format); - void on_showStyleButton_toggled(bool checked); - void on_boldButton_clicked(bool checked); - void on_italicButton_clicked(bool checked); - void on_underlineButton_clicked(bool checked); - void colorChosen(QAction *action); - void colorHighlightChosen(QAction *action); + void setCustomFont(const QVariant &font); + void setUseCustomFont(const QVariant &); + void setEnableSpellCheck(const QVariant &); + void setEnableEmacsMode(const QVariant &); + void setShowNickSelector(const QVariant &); + void setShowStyleButtons(const QVariant &); + void setEnablePerChatHistory(const QVariant &); + void setMaxLines(const QVariant &); + void setMultiLineEnabled(const QVariant &); + void setScrollBarsEnabled(const QVariant &); + void onTextEntered(const QString &text); + void changeNick(const QString &newNick) const; + + void setNetwork(NetworkId networkId); + void setIdentity(IdentityId identityId); + void connectMyIrcUser(); + void updateNickSelector() const; + void updateEnabledState(); + + BufferInfo currentBufferInfo() const; + + void currentCharFormatChanged(const QTextCharFormat &format); + void on_showStyleButton_toggled(bool checked); + void on_boldButton_clicked(bool checked); + void on_italicButton_clicked(bool checked); + void on_underlineButton_clicked(bool checked); + void colorChosen(QAction *action); + void colorHighlightChosen(QAction *action); private: - Ui::InputWidget ui; - - NetworkId _networkId; - IdentityId _identityId; - QMenu *_colorMenu, *_colorFillMenu; - - void mergeFormatOnSelection(const QTextCharFormat &format); - void fontChanged(const QFont &f); - QIcon createColorToolButtonIcon(const QIcon &icon, const QColor &color); - QTextCharFormat getFormatOfWordOrSelection(); - void setFormatOnSelection(const QTextCharFormat &format); - - bool _perChatHistory; - struct HistoryState { - QStringList history; - QHash tempHistory; - qint32 idx; - QString inputLine; - inline HistoryState() : idx(0) {}; - }; - - QMap historyMap; + Ui::InputWidget ui; + + NetworkId _networkId; + IdentityId _identityId; + QMenu *_colorMenu, *_colorFillMenu; + + void mergeFormatOnSelection(const QTextCharFormat &format); + void fontChanged(const QFont &f); + QIcon createColorToolButtonIcon(const QIcon &icon, const QColor &color); + QTextCharFormat getFormatOfWordOrSelection(); + void setFormatOnSelection(const QTextCharFormat &format); + + bool _perChatHistory; + struct HistoryState { + QStringList history; + QHash tempHistory; + qint32 idx; + QString inputLine; + inline HistoryState() : idx(0) {}; + }; + + QMap historyMap; }; -class MouseWheelFilter : public QObject { - Q_OBJECT +class MouseWheelFilter : public QObject +{ + Q_OBJECT public: - MouseWheelFilter(QObject *parent = 0); - virtual bool eventFilter(QObject *obj, QEvent *event); + MouseWheelFilter(QObject *parent = 0); + virtual bool eventFilter(QObject *obj, QEvent *event); }; + #endif // INPUTWIDGET_H diff --git a/src/qtui/ircconnectionwizard.cpp b/src/qtui/ircconnectionwizard.cpp index e98460be..8f6b0c7a 100644 --- a/src/qtui/ircconnectionwizard.cpp +++ b/src/qtui/ircconnectionwizard.cpp @@ -27,137 +27,151 @@ #include IrcConnectionWizard::IrcConnectionWizard(QWidget *parent, Qt::WindowFlags flags) - : QWizard(parent, flags), + : QWizard(parent, flags), _introductionPage(0), _identityPage(0), _networkPage(0) { + _introductionPage = createIntroductionPage(this); + _identityPage = new IdentityPage(this); + _networkPage = new NetworkPage(this); - _introductionPage = createIntroductionPage(this); - _identityPage = new IdentityPage(this); - _networkPage = new NetworkPage(this); + addPage(_introductionPage); + addPage(_identityPage); + addPage(_networkPage); + setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); - addPage(_introductionPage); - addPage(_identityPage); - addPage(_networkPage); + setOptions(options() | (QWizard::WizardOptions)(QWizard::NoDefaultButton | QWizard::CancelButtonOnLeft)); + setOption(QWizard::NoCancelButton, false); - setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); - - setOptions(options() | (QWizard::WizardOptions)(QWizard::NoDefaultButton | QWizard::CancelButtonOnLeft)); - setOption(QWizard::NoCancelButton, false); - - connect(button(QWizard::FinishButton), SIGNAL(clicked()), this, SLOT(finishClicked())); - setButtonText(QWizard::FinishButton, tr("Save && Connect")); + connect(button(QWizard::FinishButton), SIGNAL(clicked()), this, SLOT(finishClicked())); + setButtonText(QWizard::FinishButton, tr("Save && Connect")); } -QWizardPage *IrcConnectionWizard::createIntroductionPage(QWidget *parent) { - QWizardPage *page = new QWizardPage(parent); - page->setTitle(QObject::tr("Welcome to Quassel IRC")); - QLabel *label = new QLabel(QObject::tr("This wizard will help you to set up your default identity and your IRC network connection.
" - "This only covers basic settings. You can cancel this wizard any time and use the settings dialog for more detailed changes."), page); - label->setWordWrap(true); +QWizardPage *IrcConnectionWizard::createIntroductionPage(QWidget *parent) +{ + QWizardPage *page = new QWizardPage(parent); + page->setTitle(QObject::tr("Welcome to Quassel IRC")); + + QLabel *label = new QLabel(QObject::tr("This wizard will help you to set up your default identity and your IRC network connection.
" + "This only covers basic settings. You can cancel this wizard any time and use the settings dialog for more detailed changes."), page); + label->setWordWrap(true); - QVBoxLayout *layout = new QVBoxLayout; - layout->addWidget(label); - page->setLayout(layout); - return page; + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(label); + page->setLayout(layout); + return page; } -void IrcConnectionWizard::finishClicked() { - CertIdentity *identity = static_cast(_identityPage)->identity(); - if(identity->id().isValid()) { - Client::updateIdentity(identity->id(), identity->toVariantMap()); - identityReady(identity->id()); - } else { - connect(Client::instance(), SIGNAL(identityCreated(IdentityId)), this, SLOT(identityReady(IdentityId))); - Client::createIdentity(*identity); - } + +void IrcConnectionWizard::finishClicked() +{ + CertIdentity *identity = static_cast(_identityPage)->identity(); + if (identity->id().isValid()) { + Client::updateIdentity(identity->id(), identity->toVariantMap()); + identityReady(identity->id()); + } + else { + connect(Client::instance(), SIGNAL(identityCreated(IdentityId)), this, SLOT(identityReady(IdentityId))); + Client::createIdentity(*identity); + } } -void IrcConnectionWizard::identityReady(IdentityId id) { - disconnect(Client::instance(), SIGNAL(identityCreated(IdentityId)), this, SLOT(identityReady(IdentityId))); - NetworkPage *networkPage = static_cast(_networkPage); - NetworkInfo networkInfo = networkPage->networkInfo(); - QStringList channels = networkPage->channelList(); - networkInfo.identity = id; - connect(Client::instance(), SIGNAL(networkCreated(NetworkId)), this, SLOT(networkReady(NetworkId))); - Client::createNetwork(networkInfo, channels); + +void IrcConnectionWizard::identityReady(IdentityId id) +{ + disconnect(Client::instance(), SIGNAL(identityCreated(IdentityId)), this, SLOT(identityReady(IdentityId))); + NetworkPage *networkPage = static_cast(_networkPage); + NetworkInfo networkInfo = networkPage->networkInfo(); + QStringList channels = networkPage->channelList(); + networkInfo.identity = id; + connect(Client::instance(), SIGNAL(networkCreated(NetworkId)), this, SLOT(networkReady(NetworkId))); + Client::createNetwork(networkInfo, channels); } -void IrcConnectionWizard::networkReady(NetworkId id) { - disconnect(Client::instance(), SIGNAL(networkCreated(NetworkId)), this, SLOT(networkReady(NetworkId))); - const Network *net = Client::network(id); - Q_ASSERT(net); - net->requestConnect(); - deleteLater(); + +void IrcConnectionWizard::networkReady(NetworkId id) +{ + disconnect(Client::instance(), SIGNAL(networkCreated(NetworkId)), this, SLOT(networkReady(NetworkId))); + const Network *net = Client::network(id); + Q_ASSERT(net); + net->requestConnect(); + deleteLater(); } + // ============================== // Wizard Pages // ============================== // Identity Page IdentityPage::IdentityPage(QWidget *parent) - : QWizardPage(parent), + : QWizardPage(parent), _identityEditWidget(new IdentityEditWidget(this)), _identity(0) { - setTitle(tr("Setup Identity")); - - if(Client::identityIds().isEmpty()) { - _identity = new CertIdentity(-1, this); - _identity->setToDefaults(); - _identity->setIdentityName(tr("Default Identity")); - } else { - _identity = new CertIdentity(*Client::identity(Client::identityIds().first()), this); - } - - _identityEditWidget->displayIdentity(_identity); - _identityEditWidget->showAdvanced(false); - QVBoxLayout *layout = new QVBoxLayout; - layout->addWidget(_identityEditWidget); - setLayout(layout); + setTitle(tr("Setup Identity")); + + if (Client::identityIds().isEmpty()) { + _identity = new CertIdentity(-1, this); + _identity->setToDefaults(); + _identity->setIdentityName(tr("Default Identity")); + } + else { + _identity = new CertIdentity(*Client::identity(Client::identityIds().first()), this); + } + + _identityEditWidget->displayIdentity(_identity); + _identityEditWidget->showAdvanced(false); + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(_identityEditWidget); + setLayout(layout); } -CertIdentity *IdentityPage::identity() { - _identityEditWidget->saveToIdentity(_identity); - return _identity; + +CertIdentity *IdentityPage::identity() +{ + _identityEditWidget->saveToIdentity(_identity); + return _identity; } // Network Page NetworkPage::NetworkPage(QWidget *parent) - : QWizardPage(parent), + : QWizardPage(parent), _networkEditor(new SimpleNetworkEditor(this)) { - - QStringList defaultNets = Network::presetNetworks(true); - if(!defaultNets.isEmpty()) { - NetworkInfo info = Network::networkInfoFromPreset(defaultNets[0]); - if(!info.networkName.isEmpty()) { - _networkInfo = info; - _channelList = Network::presetDefaultChannels(defaultNets[0]); + QStringList defaultNets = Network::presetNetworks(true); + if (!defaultNets.isEmpty()) { + NetworkInfo info = Network::networkInfoFromPreset(defaultNets[0]); + if (!info.networkName.isEmpty()) { + _networkInfo = info; + _channelList = Network::presetDefaultChannels(defaultNets[0]); + } } - } - _networkEditor->displayNetworkInfo(_networkInfo); - _networkEditor->setDefaultChannels(_channelList); + _networkEditor->displayNetworkInfo(_networkInfo); + _networkEditor->setDefaultChannels(_channelList); - setTitle(tr("Setup Network Connection")); + setTitle(tr("Setup Network Connection")); - QVBoxLayout *layout = new QVBoxLayout; - layout->addWidget(_networkEditor); - setLayout(layout); + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(_networkEditor); + setLayout(layout); } -NetworkInfo NetworkPage::networkInfo() { - _networkEditor->saveToNetworkInfo(_networkInfo); - return _networkInfo; + +NetworkInfo NetworkPage::networkInfo() +{ + _networkEditor->saveToNetworkInfo(_networkInfo); + return _networkInfo; } -QStringList NetworkPage::channelList() { - _channelList = _networkEditor->defaultChannels(); - return _channelList; + +QStringList NetworkPage::channelList() +{ + _channelList = _networkEditor->defaultChannels(); + return _channelList; } diff --git a/src/qtui/ircconnectionwizard.h b/src/qtui/ircconnectionwizard.h index aa65a039..b6272be3 100644 --- a/src/qtui/ircconnectionwizard.h +++ b/src/qtui/ircconnectionwizard.h @@ -25,23 +25,24 @@ #include "types.h" -class IrcConnectionWizard : public QWizard { - Q_OBJECT +class IrcConnectionWizard : public QWizard +{ + Q_OBJECT public: - IrcConnectionWizard(QWidget *parent = 0, Qt::WindowFlags flags = 0); + IrcConnectionWizard(QWidget *parent = 0, Qt::WindowFlags flags = 0); - static QWizardPage *createIntroductionPage(QWidget *parent = 0); + static QWizardPage *createIntroductionPage(QWidget *parent = 0); private slots: - void finishClicked(); - void identityReady(IdentityId id); - void networkReady(NetworkId id); + void finishClicked(); + void identityReady(IdentityId id); + void networkReady(NetworkId id); private: - QWizardPage *_introductionPage; - QWizardPage *_identityPage; - QWizardPage *_networkPage; + QWizardPage *_introductionPage; + QWizardPage *_identityPage; + QWizardPage *_networkPage; }; @@ -54,17 +55,18 @@ private: class IdentityEditWidget; -class IdentityPage : public QWizardPage { - Q_OBJECT +class IdentityPage : public QWizardPage +{ + Q_OBJECT public: - IdentityPage(QWidget *parent = 0); + IdentityPage(QWidget *parent = 0); - CertIdentity *identity(); + CertIdentity *identity(); private: - IdentityEditWidget *_identityEditWidget; - CertIdentity *_identity; + IdentityEditWidget *_identityEditWidget; + CertIdentity *_identity; }; @@ -73,19 +75,21 @@ private: class SimpleNetworkEditor; -class NetworkPage : public QWizardPage { - Q_OBJECT +class NetworkPage : public QWizardPage +{ + Q_OBJECT public: - NetworkPage(QWidget *parent = 0); + NetworkPage(QWidget *parent = 0); - NetworkInfo networkInfo(); - QStringList channelList(); + NetworkInfo networkInfo(); + QStringList channelList(); private: - SimpleNetworkEditor *_networkEditor; - NetworkInfo _networkInfo; - QStringList _channelList; + SimpleNetworkEditor *_networkEditor; + NetworkInfo _networkInfo; + QStringList _channelList; }; + #endif //IRCCONNECTIONWIZARD_H diff --git a/src/qtui/knotificationbackend.cpp b/src/qtui/knotificationbackend.cpp index db97e641..26f4be0f 100644 --- a/src/qtui/knotificationbackend.cpp +++ b/src/qtui/knotificationbackend.cpp @@ -33,113 +33,138 @@ #include "qtui.h" KNotificationBackend::KNotificationBackend(QObject *parent) -: AbstractNotificationBackend(parent) + : AbstractNotificationBackend(parent) { - connect(QtUi::mainWindow()->systemTray(), SIGNAL(activated(SystemTray::ActivationReason)), - SLOT(notificationActivated(SystemTray::ActivationReason))); + connect(QtUi::mainWindow()->systemTray(), SIGNAL(activated(SystemTray::ActivationReason)), + SLOT(notificationActivated(SystemTray::ActivationReason))); - updateToolTip(); + updateToolTip(); } -void KNotificationBackend::notify(const Notification &n) { - QString type; - switch(n.type) { + +void KNotificationBackend::notify(const Notification &n) +{ + QString type; + switch (n.type) { case Highlight: - type = "Highlight"; break; + type = "Highlight"; break; case HighlightFocused: - type = "HighlightFocused"; break; + type = "HighlightFocused"; break; case PrivMsg: - type = "PrivMsg"; break; + type = "PrivMsg"; break; case PrivMsgFocused: - type = "PrivMsgFocused"; break; - } - - QString message = QString("<%1> %2").arg(n.sender, Qt::escape(n.message)); - KNotification *notification = KNotification::event(type, message, DesktopIcon("dialog-information"), QtUi::mainWindow(), - KNotification::RaiseWidgetOnActivation - |KNotification::CloseWhenWidgetActivated - |KNotification::CloseOnTimeout); - connect(notification, SIGNAL(activated(uint)), SLOT(notificationActivated())); - notification->setActions(QStringList("View")); - notification->setProperty("notificationId", n.notificationId); - - _notifications.append(qMakePair(n.notificationId, QPointer(notification))); - - updateToolTip(); - QtUi::mainWindow()->systemTray()->setAlert(true); + type = "PrivMsgFocused"; break; + } + + QString message = QString("<%1> %2").arg(n.sender, Qt::escape(n.message)); + KNotification *notification = KNotification::event(type, message, DesktopIcon("dialog-information"), QtUi::mainWindow(), + KNotification::RaiseWidgetOnActivation + |KNotification::CloseWhenWidgetActivated + |KNotification::CloseOnTimeout); + connect(notification, SIGNAL(activated(uint)), SLOT(notificationActivated())); + notification->setActions(QStringList("View")); + notification->setProperty("notificationId", n.notificationId); + + _notifications.append(qMakePair(n.notificationId, QPointer(notification))); + + updateToolTip(); + QtUi::mainWindow()->systemTray()->setAlert(true); } -void KNotificationBackend::removeNotificationById(uint notificationId) { - QList > >::iterator i = _notifications.begin(); - while(i != _notifications.end()) { - if(i->first == notificationId) { - if(i->second) - i->second->close(); - i = _notifications.erase(i); - } else - ++i; - } - updateToolTip(); + +void KNotificationBackend::removeNotificationById(uint notificationId) +{ + QList > >::iterator i = _notifications.begin(); + while (i != _notifications.end()) { + if (i->first == notificationId) { + if (i->second) + i->second->close(); + i = _notifications.erase(i); + } + else + ++i; + } + updateToolTip(); } -void KNotificationBackend::close(uint notificationId) { - removeNotificationById(notificationId); - //if(!_notifications.count()) // FIXME make configurable + +void KNotificationBackend::close(uint notificationId) +{ + removeNotificationById(notificationId); + //if(!_notifications.count()) // FIXME make configurable QtUi::mainWindow()->systemTray()->setAlert(false); } -void KNotificationBackend::notificationActivated() { - uint id = 0; - KNotification *n = qobject_cast(sender()); - if(n) - id = n->property("notificationId").toUInt(); - notificationActivated(id); +void KNotificationBackend::notificationActivated() +{ + uint id = 0; + KNotification *n = qobject_cast(sender()); + if (n) + id = n->property("notificationId").toUInt(); + + notificationActivated(id); } -void KNotificationBackend::notificationActivated(SystemTray::ActivationReason reason) { - if(reason == SystemTray::Trigger) { - if( _notifications.count()) - notificationActivated(_notifications.first().first); // oldest one - else - GraphicalUi::toggleMainWidget(); - } + +void KNotificationBackend::notificationActivated(SystemTray::ActivationReason reason) +{ + if (reason == SystemTray::Trigger) { + if (_notifications.count()) + notificationActivated(_notifications.first().first); // oldest one + else + GraphicalUi::toggleMainWidget(); + } } -void KNotificationBackend::notificationActivated(uint notificationId) { - emit activated(notificationId); + +void KNotificationBackend::notificationActivated(uint notificationId) +{ + emit activated(notificationId); } -void KNotificationBackend::updateToolTip() { - QtUi::mainWindow()->systemTray()->setToolTip("Quassel IRC", - _notifications.count()? tr("%n pending highlight(s)", "", _notifications.count()) : QString()); + +void KNotificationBackend::updateToolTip() +{ + QtUi::mainWindow()->systemTray()->setToolTip("Quassel IRC", + _notifications.count() ? tr("%n pending highlight(s)", "", _notifications.count()) : QString()); } -SettingsPage *KNotificationBackend::createConfigWidget() const { - return new ConfigWidget(); + +SettingsPage *KNotificationBackend::createConfigWidget() const +{ + return new ConfigWidget(); } + /***************************************************************************/ -KNotificationBackend::ConfigWidget::ConfigWidget(QWidget *parent) : SettingsPage("Internal", "KNotification", parent) { - _widget = new KNotifyConfigWidget(this); - _widget->setApplication("quassel"); +KNotificationBackend::ConfigWidget::ConfigWidget(QWidget *parent) : SettingsPage("Internal", "KNotification", parent) +{ + _widget = new KNotifyConfigWidget(this); + _widget->setApplication("quassel"); - QVBoxLayout *layout = new QVBoxLayout(this); - layout->addWidget(_widget); + QVBoxLayout *layout = new QVBoxLayout(this); + layout->addWidget(_widget); - connect(_widget, SIGNAL(changed(bool)), SLOT(widgetChanged(bool))); + connect(_widget, SIGNAL(changed(bool)), SLOT(widgetChanged(bool))); } -void KNotificationBackend::ConfigWidget::widgetChanged(bool changed) { - setChangedState(changed); + +void KNotificationBackend::ConfigWidget::widgetChanged(bool changed) +{ + setChangedState(changed); } -void KNotificationBackend::ConfigWidget::load() { - setChangedState(false); + +void KNotificationBackend::ConfigWidget::load() +{ + setChangedState(false); } -void KNotificationBackend::ConfigWidget::save() { - _widget->save(); - load(); + +void KNotificationBackend::ConfigWidget::save() +{ + _widget->save(); + load(); } diff --git a/src/qtui/knotificationbackend.h b/src/qtui/knotificationbackend.h index eead0fa9..5ab10cf8 100644 --- a/src/qtui/knotificationbackend.h +++ b/src/qtui/knotificationbackend.h @@ -30,44 +30,48 @@ class KNotification; class KNotifyConfigWidget; -class KNotificationBackend : public AbstractNotificationBackend { - Q_OBJECT +class KNotificationBackend : public AbstractNotificationBackend +{ + Q_OBJECT public: - KNotificationBackend(QObject *parent = 0); + KNotificationBackend(QObject *parent = 0); - void notify(const Notification &); - void close(uint notificationId); - virtual SettingsPage *createConfigWidget() const; + void notify(const Notification &); + void close(uint notificationId); + virtual SettingsPage *createConfigWidget() const; private slots: - void notificationActivated(); - void notificationActivated(SystemTray::ActivationReason); - void notificationActivated(uint notificationId); + void notificationActivated(); + void notificationActivated(SystemTray::ActivationReason); + void notificationActivated(uint notificationId); private: - class ConfigWidget; + class ConfigWidget; - void removeNotificationById(uint id); - void updateToolTip(); + void removeNotificationById(uint id); + void updateToolTip(); - QList > > _notifications; + QList > > _notifications; }; -class KNotificationBackend::ConfigWidget : public SettingsPage { - Q_OBJECT + +class KNotificationBackend::ConfigWidget : public SettingsPage +{ + Q_OBJECT public: - ConfigWidget(QWidget *parent = 0); + ConfigWidget(QWidget *parent = 0); - void save(); - void load(); + void save(); + void load(); private slots: - void widgetChanged(bool); + void widgetChanged(bool); private: - KNotifyConfigWidget *_widget; + KNotifyConfigWidget *_widget; }; + #endif diff --git a/src/qtui/legacysystemtray.cpp b/src/qtui/legacysystemtray.cpp index 52bd15dc..27b99737 100644 --- a/src/qtui/legacysystemtray.cpp +++ b/src/qtui/legacysystemtray.cpp @@ -25,142 +25,168 @@ #include "qtui.h" LegacySystemTray::LegacySystemTray(QWidget *parent) - : SystemTray(parent), - _blinkState(false), - _lastMessageId(0) + : SystemTray(parent), + _blinkState(false), + _lastMessageId(0) { #ifndef HAVE_KDE - _trayIcon = new QSystemTrayIcon(associatedWidget()); + _trayIcon = new QSystemTrayIcon(associatedWidget()); #else - _trayIcon = new KSystemTrayIcon(associatedWidget()); - // We don't want to trigger a minimize if a highlight is pending, so we brutally remove the internal connection for that - disconnect(_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), - _trayIcon, SLOT(activateOrHide(QSystemTrayIcon::ActivationReason))); + _trayIcon = new KSystemTrayIcon(associatedWidget()); + // We don't want to trigger a minimize if a highlight is pending, so we brutally remove the internal connection for that + disconnect(_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), + _trayIcon, SLOT(activateOrHide(QSystemTrayIcon::ActivationReason))); #endif #ifndef Q_WS_MAC - connect(_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), - SLOT(on_activated(QSystemTrayIcon::ActivationReason))); + connect(_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), + SLOT(on_activated(QSystemTrayIcon::ActivationReason))); #endif - connect(_trayIcon, SIGNAL(messageClicked()), - SLOT(on_messageClicked())); + connect(_trayIcon, SIGNAL(messageClicked()), + SLOT(on_messageClicked())); - _blinkTimer.setInterval(500); - _blinkTimer.setSingleShot(false); - connect(&_blinkTimer, SIGNAL(timeout()), SLOT(on_blinkTimeout())); + _blinkTimer.setInterval(500); + _blinkTimer.setSingleShot(false); + connect(&_blinkTimer, SIGNAL(timeout()), SLOT(on_blinkTimeout())); - connect(this, SIGNAL(toolTipChanged(QString,QString)), SLOT(syncLegacyIcon())); + connect(this, SIGNAL(toolTipChanged(QString, QString)), SLOT(syncLegacyIcon())); } -void LegacySystemTray::init() { - if(mode() == Invalid) // derived class hasn't set a mode itself - setMode(Legacy); - SystemTray::init(); +void LegacySystemTray::init() +{ + if (mode() == Invalid) // derived class hasn't set a mode itself + setMode(Legacy); + + SystemTray::init(); - _trayIcon->setContextMenu(trayMenu()); + _trayIcon->setContextMenu(trayMenu()); } -void LegacySystemTray::syncLegacyIcon() { - _trayIcon->setIcon(stateIcon()); + +void LegacySystemTray::syncLegacyIcon() +{ + _trayIcon->setIcon(stateIcon()); #if defined Q_WS_MAC || defined Q_WS_WIN - QString tooltip = QString("%1").arg(toolTipTitle()); - if(!toolTipSubTitle().isEmpty()) - tooltip += QString("\n%1").arg(toolTipSubTitle()); + QString tooltip = QString("%1").arg(toolTipTitle()); + if (!toolTipSubTitle().isEmpty()) + tooltip += QString("\n%1").arg(toolTipSubTitle()); #else - QString tooltip = QString("%1").arg(toolTipTitle()); - if(!toolTipSubTitle().isEmpty()) - tooltip += QString("
%1").arg(toolTipSubTitle()); + QString tooltip = QString("%1").arg(toolTipTitle()); + if (!toolTipSubTitle().isEmpty()) + tooltip += QString("
%1").arg(toolTipSubTitle()); #endif - _trayIcon->setToolTip(tooltip); + _trayIcon->setToolTip(tooltip); } -void LegacySystemTray::setVisible(bool visible) { - SystemTray::setVisible(visible); - if(mode() == Legacy) { - if(shouldBeVisible()) - _trayIcon->show(); - else - _trayIcon->hide(); - } -} -bool LegacySystemTray::isVisible() const { - if(mode() == Legacy) { - return _trayIcon->isVisible(); - } - return SystemTray::isVisible(); +void LegacySystemTray::setVisible(bool visible) +{ + SystemTray::setVisible(visible); + if (mode() == Legacy) { + if (shouldBeVisible()) + _trayIcon->show(); + else + _trayIcon->hide(); + } } -void LegacySystemTray::setMode(Mode mode_) { - if(mode_ == mode()) - return; - - SystemTray::setMode(mode_); - - if(mode() == Legacy) { - syncLegacyIcon(); - if(shouldBeVisible()) - _trayIcon->show(); - else - _trayIcon->hide(); - if(state() == NeedsAttention) - _blinkTimer.start(); - } else { - _trayIcon->hide(); - _blinkTimer.stop(); - } + +bool LegacySystemTray::isVisible() const +{ + if (mode() == Legacy) { + return _trayIcon->isVisible(); + } + return SystemTray::isVisible(); } -void LegacySystemTray::setState(State state_) { - State oldstate = state(); - SystemTray::setState(state_); - if(oldstate != state()) { - if(state() == NeedsAttention && mode() == Legacy && animationEnabled()) - _blinkTimer.start(); + +void LegacySystemTray::setMode(Mode mode_) +{ + if (mode_ == mode()) + return; + + SystemTray::setMode(mode_); + + if (mode() == Legacy) { + syncLegacyIcon(); + if (shouldBeVisible()) + _trayIcon->show(); + else + _trayIcon->hide(); + if (state() == NeedsAttention) + _blinkTimer.start(); + } else { - _blinkTimer.stop(); - _blinkState = false; + _trayIcon->hide(); + _blinkTimer.stop(); } - } - if(mode() == Legacy) - _trayIcon->setIcon(stateIcon()); } -Icon LegacySystemTray::stateIcon() const { - if(mode() == Legacy && state() == NeedsAttention && !_blinkState) - return SystemTray::stateIcon(Active); - return SystemTray::stateIcon(); + +void LegacySystemTray::setState(State state_) +{ + State oldstate = state(); + SystemTray::setState(state_); + if (oldstate != state()) { + if (state() == NeedsAttention && mode() == Legacy && animationEnabled()) + _blinkTimer.start(); + else { + _blinkTimer.stop(); + _blinkState = false; + } + } + if (mode() == Legacy) + _trayIcon->setIcon(stateIcon()); +} + + +Icon LegacySystemTray::stateIcon() const +{ + if (mode() == Legacy && state() == NeedsAttention && !_blinkState) + return SystemTray::stateIcon(Active); + return SystemTray::stateIcon(); } -void LegacySystemTray::on_blinkTimeout() { - _blinkState = !_blinkState; - _trayIcon->setIcon(stateIcon()); + +void LegacySystemTray::on_blinkTimeout() +{ + _blinkState = !_blinkState; + _trayIcon->setIcon(stateIcon()); } -void LegacySystemTray::on_activated(QSystemTrayIcon::ActivationReason reason) { - activate((SystemTray::ActivationReason)reason); + +void LegacySystemTray::on_activated(QSystemTrayIcon::ActivationReason reason) +{ + activate((SystemTray::ActivationReason)reason); } -void LegacySystemTray::on_messageClicked() { - emit messageClicked(_lastMessageId); + +void LegacySystemTray::on_messageClicked() +{ + emit messageClicked(_lastMessageId); } -void LegacySystemTray::showMessage(const QString &title, const QString &message, SystemTray::MessageIcon icon, int msTimeout, uint id) { - // fancy stuff later: show messages in order - // for now, we just show the last message - _lastMessageId = id; - _trayIcon->showMessage(title, message, (QSystemTrayIcon::MessageIcon)icon, msTimeout); + +void LegacySystemTray::showMessage(const QString &title, const QString &message, SystemTray::MessageIcon icon, int msTimeout, uint id) +{ + // fancy stuff later: show messages in order + // for now, we just show the last message + _lastMessageId = id; + _trayIcon->showMessage(title, message, (QSystemTrayIcon::MessageIcon)icon, msTimeout); } -void LegacySystemTray::closeMessage(uint notificationId) { - Q_UNUSED(notificationId) - // there really seems to be no sane way to close the bubble... :( +void LegacySystemTray::closeMessage(uint notificationId) +{ + Q_UNUSED(notificationId) + + // there really seems to be no sane way to close the bubble... :( #ifdef Q_WS_X11 - showMessage("", "", NoIcon, 1); + showMessage("", "", NoIcon, 1); #endif } + #endif /* QT_NO_SYSTEMTRAYICON */ diff --git a/src/qtui/legacysystemtray.h b/src/qtui/legacysystemtray.h index 7a7ba09d..8bc3b467 100644 --- a/src/qtui/legacysystemtray.h +++ b/src/qtui/legacysystemtray.h @@ -33,56 +33,59 @@ #include "systemtray.h" -class LegacySystemTray : public SystemTray { - Q_OBJECT +class LegacySystemTray : public SystemTray +{ + Q_OBJECT public: - explicit LegacySystemTray(QWidget *parent); - virtual ~LegacySystemTray() {} - virtual void init(); + explicit LegacySystemTray(QWidget *parent); + virtual ~LegacySystemTray() {} + virtual void init(); - virtual bool isVisible() const; - virtual inline bool isSystemTrayAvailable() const; - virtual Icon stateIcon() const; // overriden to care about blinkState + virtual bool isVisible() const; + virtual inline bool isSystemTrayAvailable() const; + virtual Icon stateIcon() const; // overriden to care about blinkState public slots: - virtual void setState(State state); - virtual void setVisible(bool visible = true); - virtual void showMessage(const QString &title, const QString &message, MessageIcon icon = Information, int msTimeout = 10000, uint notificationId = 0); - virtual void closeMessage(uint notificationId); + virtual void setState(State state); + virtual void setVisible(bool visible = true); + virtual void showMessage(const QString &title, const QString &message, MessageIcon icon = Information, int msTimeout = 10000, uint notificationId = 0); + virtual void closeMessage(uint notificationId); protected slots: protected: - virtual void setMode(Mode mode); + virtual void setMode(Mode mode); private slots: - void on_blinkTimeout(); - void on_activated(QSystemTrayIcon::ActivationReason); - void on_messageClicked(); + void on_blinkTimeout(); + void on_activated(QSystemTrayIcon::ActivationReason); + void on_messageClicked(); - void syncLegacyIcon(); + void syncLegacyIcon(); private: - QTimer _blinkTimer; - bool _blinkState; - uint _lastMessageId; + QTimer _blinkTimer; + bool _blinkState; + uint _lastMessageId; #ifdef HAVE_KDE - KSystemTrayIcon *_trayIcon; + KSystemTrayIcon *_trayIcon; #else - QSystemTrayIcon *_trayIcon; + QSystemTrayIcon *_trayIcon; #endif - }; + // inlines -bool LegacySystemTray::isSystemTrayAvailable() const { - return mode() == Legacy ? QSystemTrayIcon::isSystemTrayAvailable() - : SystemTray::isSystemTrayAvailable(); +bool LegacySystemTray::isSystemTrayAvailable() const +{ + return mode() == Legacy ? QSystemTrayIcon::isSystemTrayAvailable() + : SystemTray::isSystemTrayAvailable(); } + #endif /* QT_NO_SYSTEMTRAYICON */ #endif /* LEGACYSYSTEMTRAY_H_ */ diff --git a/src/qtui/mainpage.cpp b/src/qtui/mainpage.cpp index 24653315..61b13bca 100644 --- a/src/qtui/mainpage.cpp +++ b/src/qtui/mainpage.cpp @@ -23,23 +23,23 @@ #include "mainpage.h" -MainPage::MainPage(QWidget *parent) : QWidget(parent) { - - +MainPage::MainPage(QWidget *parent) : QWidget(parent) +{ } -void MainPage::paintEvent(QPaintEvent *event) { - Q_UNUSED(event); - QPainter painter(this); - QImage img(":/pics/quassel-logo.png"); // FIXME load externally +void MainPage::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); - if(img.height() > height() || img.width() > width()) - img = img.scaled(width(), height(), Qt::KeepAspectRatio, Qt::SmoothTransformation); + QPainter painter(this); + QImage img(":/pics/quassel-logo.png"); // FIXME load externally - int xmargin = (width() - img.width()) / 2; - int ymargin = (height() - img.height()) / 2; + if (img.height() > height() || img.width() > width()) + img = img.scaled(width(), height(), Qt::KeepAspectRatio, Qt::SmoothTransformation); - painter.drawImage(xmargin, ymargin, img); + int xmargin = (width() - img.width()) / 2; + int ymargin = (height() - img.height()) / 2; + painter.drawImage(xmargin, ymargin, img); } diff --git a/src/qtui/mainpage.h b/src/qtui/mainpage.h index 1d1e35d1..f0905046 100644 --- a/src/qtui/mainpage.h +++ b/src/qtui/mainpage.h @@ -23,16 +23,16 @@ #include -class MainPage : public QWidget { - Q_OBJECT +class MainPage : public QWidget +{ + Q_OBJECT public: - MainPage(QWidget *parent = 0); + MainPage(QWidget *parent = 0); protected: - void paintEvent(QPaintEvent *event); - - + void paintEvent(QPaintEvent *event); }; + #endif diff --git a/src/qtui/mainwin.cpp b/src/qtui/mainwin.cpp index 14329168..cc667caa 100644 --- a/src/qtui/mainwin.cpp +++ b/src/qtui/mainwin.cpp @@ -131,10 +131,10 @@ MainWin::MainWin(QWidget *parent) #ifdef HAVE_KDE - : KMainWindow(parent), - _kHelpMenu(new KHelpMenu(this, KGlobal::mainComponent().aboutData())), + : KMainWindow(parent), + _kHelpMenu(new KHelpMenu(this, KGlobal::mainComponent().aboutData())), #else - : QMainWindow(parent), + : QMainWindow(parent), #endif _msgProcessorStatusWidget(new MsgProcessorStatusWidget(this)), _coreConnectionStatusWidget(new CoreConnectionStatusWidget(Client::coreConnection(), this)), @@ -143,1326 +143,1486 @@ MainWin::MainWin(QWidget *parent) _layoutLoaded(false), _activeBufferViewIndex(-1) { - setAttribute(Qt::WA_DeleteOnClose, false); // we delete the mainwin manually + setAttribute(Qt::WA_DeleteOnClose, false); // we delete the mainwin manually - QtUiSettings uiSettings; - QString style = uiSettings.value("Style", QString()).toString(); - if(!style.isEmpty()) { - QApplication::setStyle(style); - } + QtUiSettings uiSettings; + QString style = uiSettings.value("Style", QString()).toString(); + if (!style.isEmpty()) { + QApplication::setStyle(style); + } - QApplication::setQuitOnLastWindowClosed(false); + QApplication::setQuitOnLastWindowClosed(false); - setWindowTitle("Quassel IRC"); - setWindowIconText("Quassel IRC"); - updateIcon(); + setWindowTitle("Quassel IRC"); + setWindowIconText("Quassel IRC"); + updateIcon(); } -void MainWin::init() { - connect(Client::instance(), SIGNAL(networkCreated(NetworkId)), SLOT(clientNetworkCreated(NetworkId))); - connect(Client::instance(), SIGNAL(networkRemoved(NetworkId)), SLOT(clientNetworkRemoved(NetworkId))); - connect(Client::messageModel(), SIGNAL(rowsInserted(const QModelIndex &, int, int)), - SLOT(messagesInserted(const QModelIndex &, int, int))); - connect(GraphicalUi::contextMenuActionProvider(), SIGNAL(showChannelList(NetworkId)), SLOT(showChannelList(NetworkId))); - connect(GraphicalUi::contextMenuActionProvider(), SIGNAL(showIgnoreList(QString)), SLOT(showIgnoreList(QString))); - connect(Client::coreConnection(), SIGNAL(startCoreSetup(QVariantList)), SLOT(showCoreConfigWizard(QVariantList))); - connect(Client::coreConnection(), SIGNAL(connectionErrorPopup(QString)), SLOT(handleCoreConnectionError(QString))); - connect(Client::coreConnection(), SIGNAL(userAuthenticationRequired(CoreAccount *, bool *, QString)), SLOT(userAuthenticationRequired(CoreAccount *, bool *, QString))); - connect(Client::coreConnection(), SIGNAL(handleNoSslInClient(bool*)), SLOT(handleNoSslInClient(bool *))); - connect(Client::coreConnection(), SIGNAL(handleNoSslInCore(bool*)), SLOT(handleNoSslInCore(bool *))); +void MainWin::init() +{ + connect(Client::instance(), SIGNAL(networkCreated(NetworkId)), SLOT(clientNetworkCreated(NetworkId))); + connect(Client::instance(), SIGNAL(networkRemoved(NetworkId)), SLOT(clientNetworkRemoved(NetworkId))); + connect(Client::messageModel(), SIGNAL(rowsInserted(const QModelIndex &, int, int)), + SLOT(messagesInserted(const QModelIndex &, int, int))); + connect(GraphicalUi::contextMenuActionProvider(), SIGNAL(showChannelList(NetworkId)), SLOT(showChannelList(NetworkId))); + connect(GraphicalUi::contextMenuActionProvider(), SIGNAL(showIgnoreList(QString)), SLOT(showIgnoreList(QString))); + + connect(Client::coreConnection(), SIGNAL(startCoreSetup(QVariantList)), SLOT(showCoreConfigWizard(QVariantList))); + connect(Client::coreConnection(), SIGNAL(connectionErrorPopup(QString)), SLOT(handleCoreConnectionError(QString))); + connect(Client::coreConnection(), SIGNAL(userAuthenticationRequired(CoreAccount *, bool *, QString)), SLOT(userAuthenticationRequired(CoreAccount *, bool *, QString))); + connect(Client::coreConnection(), SIGNAL(handleNoSslInClient(bool *)), SLOT(handleNoSslInClient(bool *))); + connect(Client::coreConnection(), SIGNAL(handleNoSslInCore(bool *)), SLOT(handleNoSslInCore(bool *))); #ifdef HAVE_SSL - connect(Client::coreConnection(), SIGNAL(handleSslErrors(const QSslSocket *, bool *, bool *)), SLOT(handleSslErrors(const QSslSocket *, bool *, bool *))); + connect(Client::coreConnection(), SIGNAL(handleSslErrors(const QSslSocket *, bool *, bool *)), SLOT(handleSslErrors(const QSslSocket *, bool *, bool *))); #endif - // Setup Dock Areas - setDockNestingEnabled(true); - setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); - setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); - setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea); - setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); - - // Order is sometimes important - setupActions(); - setupBufferWidget(); - setupMenus(); - setupTopicWidget(); - setupNickWidget(); - setupInputWidget(); - setupChatMonitor(); - setupViewMenuTail(); - setupStatusBar(); - setupToolBars(); - setupSystray(); - setupTitleSetter(); - setupHotList(); + // Setup Dock Areas + setDockNestingEnabled(true); + setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); + setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); + setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea); + setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); + + // Order is sometimes important + setupActions(); + setupBufferWidget(); + setupMenus(); + setupTopicWidget(); + setupNickWidget(); + setupInputWidget(); + setupChatMonitor(); + setupViewMenuTail(); + setupStatusBar(); + setupToolBars(); + setupSystray(); + setupTitleSetter(); + setupHotList(); #ifndef HAVE_KDE # ifdef HAVE_PHONON - QtUi::registerNotificationBackend(new PhononNotificationBackend(this)); + QtUi::registerNotificationBackend(new PhononNotificationBackend(this)); # endif # ifndef QT_NO_SYSTEMTRAYICON - QtUi::registerNotificationBackend(new SystrayNotificationBackend(this)); + QtUi::registerNotificationBackend(new SystrayNotificationBackend(this)); # endif - QtUi::registerNotificationBackend(new TaskbarNotificationBackend(this)); + QtUi::registerNotificationBackend(new TaskbarNotificationBackend(this)); #else /* HAVE_KDE */ - QtUi::registerNotificationBackend(new KNotificationBackend(this)); + QtUi::registerNotificationBackend(new KNotificationBackend(this)); #endif /* HAVE_KDE */ #ifdef HAVE_INDICATEQT - QtUi::registerNotificationBackend(new IndicatorNotificationBackend(this)); + QtUi::registerNotificationBackend(new IndicatorNotificationBackend(this)); #endif - // we assume that at this point, all configurable actions are defined! - QtUi::loadShortcuts(); + // we assume that at this point, all configurable actions are defined! + QtUi::loadShortcuts(); - connect(bufferWidget(), SIGNAL(currentChanged(BufferId)), SLOT(currentBufferChanged(BufferId))); + connect(bufferWidget(), SIGNAL(currentChanged(BufferId)), SLOT(currentBufferChanged(BufferId))); - setDisconnectedState(); // Disable menus and stuff + setDisconnectedState(); // Disable menus and stuff #ifdef HAVE_KDE - setAutoSaveSettings(); + setAutoSaveSettings(); #endif - // restore mainwin state - QtUiSettings s; - restoreStateFromSettings(s); + // restore mainwin state + QtUiSettings s; + restoreStateFromSettings(s); - // restore locked state of docks - QtUi::actionCollection("General")->action("LockLayout")->setChecked(s.value("LockLayout", false).toBool()); + // restore locked state of docks + QtUi::actionCollection("General")->action("LockLayout")->setChecked(s.value("LockLayout", false).toBool()); - CoreConnection *conn = Client::coreConnection(); - if(!conn->connectToCore()) { - // No autoconnect selected (or no accounts) - showCoreConnectionDlg(); - } + CoreConnection *conn = Client::coreConnection(); + if (!conn->connectToCore()) { + // No autoconnect selected (or no accounts) + showCoreConnectionDlg(); + } } -MainWin::~MainWin() { +MainWin::~MainWin() +{ } -void MainWin::quit() { - QtUiSettings s; - saveStateToSettings(s); - saveLayout(); - QApplication::quit(); + +void MainWin::quit() +{ + QtUiSettings s; + saveStateToSettings(s); + saveLayout(); + QApplication::quit(); } -void MainWin::saveStateToSettings(UiSettings &s) { - s.setValue("MainWinSize", _normalSize); - s.setValue("MainWinPos", _normalPos); - s.setValue("MainWinState", saveState()); - s.setValue("MainWinGeometry", saveGeometry()); - s.setValue("MainWinMinimized", isMinimized()); - s.setValue("MainWinMaximized", isMaximized()); - s.setValue("MainWinHidden", !isVisible()); - BufferId lastBufId = Client::bufferModel()->currentBuffer(); - if(lastBufId.isValid()) - s.setValue("LastUsedBufferId", lastBufId.toInt()); + +void MainWin::saveStateToSettings(UiSettings &s) +{ + s.setValue("MainWinSize", _normalSize); + s.setValue("MainWinPos", _normalPos); + s.setValue("MainWinState", saveState()); + s.setValue("MainWinGeometry", saveGeometry()); + s.setValue("MainWinMinimized", isMinimized()); + s.setValue("MainWinMaximized", isMaximized()); + s.setValue("MainWinHidden", !isVisible()); + BufferId lastBufId = Client::bufferModel()->currentBuffer(); + if (lastBufId.isValid()) + s.setValue("LastUsedBufferId", lastBufId.toInt()); #ifdef HAVE_KDE - saveAutoSaveSettings(); + saveAutoSaveSettings(); #endif } -void MainWin::restoreStateFromSettings(UiSettings &s) { - _normalSize = s.value("MainWinSize", size()).toSize(); - _normalPos = s.value("MainWinPos", pos()).toPoint(); - bool maximized = s.value("MainWinMaximized", false).toBool(); + +void MainWin::restoreStateFromSettings(UiSettings &s) +{ + _normalSize = s.value("MainWinSize", size()).toSize(); + _normalPos = s.value("MainWinPos", pos()).toPoint(); + bool maximized = s.value("MainWinMaximized", false).toBool(); #ifndef HAVE_KDE - restoreGeometry(s.value("MainWinGeometry").toByteArray()); + restoreGeometry(s.value("MainWinGeometry").toByteArray()); - if(maximized) { - // restoreGeometry() fails if the windows was maximized, so we resize and position explicitly - resize(_normalSize); - move(_normalPos); - } + if (maximized) { + // restoreGeometry() fails if the windows was maximized, so we resize and position explicitly + resize(_normalSize); + move(_normalPos); + } - restoreState(s.value("MainWinState").toByteArray()); + restoreState(s.value("MainWinState").toByteArray()); #else - move(_normalPos); + move(_normalPos); #endif - if(s.value("MainWinHidden").toBool() && QtUi::haveSystemTray()) - QtUi::hideMainWidget(); - else if(s.value("MainWinMinimized").toBool()) - showMinimized(); - else if(maximized) - showMaximized(); - else - show(); + if (s.value("MainWinHidden").toBool() && QtUi::haveSystemTray()) + QtUi::hideMainWidget(); + else if (s.value("MainWinMinimized").toBool()) + showMinimized(); + else if (maximized) + showMaximized(); + else + show(); } -void MainWin::updateIcon() { + +void MainWin::updateIcon() +{ #ifdef Q_WS_MAC - const int size = 128; + const int size = 128; #else - const int size = 48; + const int size = 48; #endif - QPixmap icon; - if(Client::isConnected()) - icon = DesktopIcon("quassel", size); - else - icon = DesktopIcon("quassel-inactive", size); - setWindowIcon(icon); - qApp->setWindowIcon(icon); -} - -void MainWin::setupActions() { - ActionCollection *coll = QtUi::actionCollection("General", tr("General")); - // File - coll->addAction("ConnectCore", new Action(SmallIcon("network-connect"), tr("&Connect to Core..."), coll, - this, SLOT(showCoreConnectionDlg()))); - coll->addAction("DisconnectCore", new Action(SmallIcon("network-disconnect"), tr("&Disconnect from Core"), coll, - Client::instance(), SLOT(disconnectFromCore()))); - coll->addAction("CoreInfo", new Action(SmallIcon("help-about"), tr("Core &Info..."), coll, - this, SLOT(showCoreInfoDlg()))); - coll->addAction("ConfigureNetworks", new Action(SmallIcon("configure"), tr("Configure &Networks..."), coll, - this, SLOT(on_actionConfigureNetworks_triggered()))); - // FIXME: use QKeySequence::Quit once we depend on Qt 4.6 - coll->addAction("Quit", new Action(SmallIcon("application-exit"), tr("&Quit"), coll, - this, SLOT(quit()), Qt::CTRL + Qt::Key_Q)); - - // View - coll->addAction("ConfigureBufferViews", new Action(tr("&Configure Chat Lists..."), coll, - this, SLOT(on_actionConfigureViews_triggered()))); - - QAction *lockAct = coll->addAction("LockLayout", new Action(tr("&Lock Layout"), coll)); - lockAct->setCheckable(true); - connect(lockAct, SIGNAL(toggled(bool)), SLOT(on_actionLockLayout_toggled(bool))); - - coll->addAction("ToggleSearchBar", new Action(SmallIcon("edit-find"), tr("Show &Search Bar"), coll, - 0, 0, QKeySequence::Find))->setCheckable(true); - coll->addAction("ShowAwayLog", new Action(tr("Show Away Log"), coll, - this, SLOT(showAwayLog()))); - coll->addAction("ToggleMenuBar", new Action(SmallIcon("show-menu"), tr("Show &Menubar"), coll, - 0, 0, QKeySequence(Qt::CTRL + Qt::Key_M)))->setCheckable(true); - - coll->addAction("ToggleStatusBar", new Action(tr("Show Status &Bar"), coll, - 0, 0))->setCheckable(true); + QPixmap icon; + if (Client::isConnected()) + icon = DesktopIcon("quassel", size); + else + icon = DesktopIcon("quassel-inactive", size); + setWindowIcon(icon); + qApp->setWindowIcon(icon); +} + + +void MainWin::setupActions() +{ + ActionCollection *coll = QtUi::actionCollection("General", tr("General")); + // File + coll->addAction("ConnectCore", new Action(SmallIcon("network-connect"), tr("&Connect to Core..."), coll, + this, SLOT(showCoreConnectionDlg()))); + coll->addAction("DisconnectCore", new Action(SmallIcon("network-disconnect"), tr("&Disconnect from Core"), coll, + Client::instance(), SLOT(disconnectFromCore()))); + coll->addAction("CoreInfo", new Action(SmallIcon("help-about"), tr("Core &Info..."), coll, + this, SLOT(showCoreInfoDlg()))); + coll->addAction("ConfigureNetworks", new Action(SmallIcon("configure"), tr("Configure &Networks..."), coll, + this, SLOT(on_actionConfigureNetworks_triggered()))); + // FIXME: use QKeySequence::Quit once we depend on Qt 4.6 + coll->addAction("Quit", new Action(SmallIcon("application-exit"), tr("&Quit"), coll, + this, SLOT(quit()), Qt::CTRL + Qt::Key_Q)); + + // View + coll->addAction("ConfigureBufferViews", new Action(tr("&Configure Chat Lists..."), coll, + this, SLOT(on_actionConfigureViews_triggered()))); + + QAction *lockAct = coll->addAction("LockLayout", new Action(tr("&Lock Layout"), coll)); + lockAct->setCheckable(true); + connect(lockAct, SIGNAL(toggled(bool)), SLOT(on_actionLockLayout_toggled(bool))); + + coll->addAction("ToggleSearchBar", new Action(SmallIcon("edit-find"), tr("Show &Search Bar"), coll, + 0, 0, QKeySequence::Find))->setCheckable(true); + coll->addAction("ShowAwayLog", new Action(tr("Show Away Log"), coll, + this, SLOT(showAwayLog()))); + coll->addAction("ToggleMenuBar", new Action(SmallIcon("show-menu"), tr("Show &Menubar"), coll, + 0, 0, QKeySequence(Qt::CTRL + Qt::Key_M)))->setCheckable(true); + + coll->addAction("ToggleStatusBar", new Action(tr("Show Status &Bar"), coll, + 0, 0))->setCheckable(true); #ifdef HAVE_KDE - QAction *fullScreenAct = KStandardAction::fullScreen(this, SLOT(toggleFullscreen()), this, coll); + QAction *fullScreenAct = KStandardAction::fullScreen(this, SLOT(toggleFullscreen()), this, coll); #else - QAction *fullScreenAct = new Action(SmallIcon("view-fullscreen"), tr("&Full Screen Mode"), coll, - this, SLOT(toggleFullscreen()), QKeySequence(Qt::Key_F11)); - fullScreenAct->setCheckable(true); + QAction *fullScreenAct = new Action(SmallIcon("view-fullscreen"), tr("&Full Screen Mode"), coll, + this, SLOT(toggleFullscreen()), QKeySequence(Qt::Key_F11)); + fullScreenAct->setCheckable(true); #endif - coll->addAction("ToggleFullscreen", fullScreenAct); + coll->addAction("ToggleFullscreen", fullScreenAct); - // Settings - QAction *configureShortcutsAct = new Action(SmallIcon("configure-shortcuts"), tr("Configure &Shortcuts..."), coll, - this, SLOT(showShortcutsDlg())); - configureShortcutsAct->setMenuRole(QAction::NoRole); - coll->addAction("ConfigureShortcuts", configureShortcutsAct); + // Settings + QAction *configureShortcutsAct = new Action(SmallIcon("configure-shortcuts"), tr("Configure &Shortcuts..."), coll, + this, SLOT(showShortcutsDlg())); + configureShortcutsAct->setMenuRole(QAction::NoRole); + coll->addAction("ConfigureShortcuts", configureShortcutsAct); #ifdef Q_WS_MAC - QAction *configureQuasselAct = new Action(SmallIcon("configure"), tr("&Configure Quassel..."), coll, - this, SLOT(showSettingsDlg())); - configureQuasselAct->setMenuRole(QAction::PreferencesRole); + QAction *configureQuasselAct = new Action(SmallIcon("configure"), tr("&Configure Quassel..."), coll, + this, SLOT(showSettingsDlg())); + configureQuasselAct->setMenuRole(QAction::PreferencesRole); #else - QAction *configureQuasselAct = new Action(SmallIcon("configure"), tr("&Configure Quassel..."), coll, - this, SLOT(showSettingsDlg()), QKeySequence(Qt::Key_F7)); + QAction *configureQuasselAct = new Action(SmallIcon("configure"), tr("&Configure Quassel..."), coll, + this, SLOT(showSettingsDlg()), QKeySequence(Qt::Key_F7)); #endif - coll->addAction("ConfigureQuassel", configureQuasselAct); - - // Help - QAction *aboutQuasselAct = new Action(SmallIcon("quassel"), tr("&About Quassel"), coll, - this, SLOT(showAboutDlg())); - aboutQuasselAct->setMenuRole(QAction::AboutRole); - coll->addAction("AboutQuassel", aboutQuasselAct); - - QAction *aboutQtAct = new Action(QIcon(":/pics/qt-logo.png"), tr("About &Qt"), coll, - qApp, SLOT(aboutQt())); - aboutQtAct->setMenuRole(QAction::AboutQtRole); - coll->addAction("AboutQt", aboutQtAct); - coll->addAction("DebugNetworkModel", new Action(SmallIcon("tools-report-bug"), tr("Debug &NetworkModel"), coll, - this, SLOT(on_actionDebugNetworkModel_triggered()))); - coll->addAction("DebugBufferViewOverlay", new Action(SmallIcon("tools-report-bug"), tr("Debug &BufferViewOverlay"), coll, - this, SLOT(on_actionDebugBufferViewOverlay_triggered()))); - coll->addAction("DebugMessageModel", new Action(SmallIcon("tools-report-bug"), tr("Debug &MessageModel"), coll, - this, SLOT(on_actionDebugMessageModel_triggered()))); - coll->addAction("DebugHotList", new Action(SmallIcon("tools-report-bug"), tr("Debug &HotList"), coll, - this, SLOT(on_actionDebugHotList_triggered()))); - coll->addAction("DebugLog", new Action(SmallIcon("tools-report-bug"), tr("Debug &Log"), coll, - this, SLOT(on_actionDebugLog_triggered()))); - coll->addAction("ReloadStyle", new Action(SmallIcon("view-refresh"), tr("Reload Stylesheet"), coll, - QtUi::style(), SLOT(reload()), QKeySequence::Refresh)); - - coll->addAction("HideCurrentBuffer", new Action(tr("Hide Current Buffer"), coll, - this, SLOT(hideCurrentBuffer()), QKeySequence::Close)); - - // Navigation - coll = QtUi::actionCollection("Navigation", tr("Navigation")); - - coll->addAction("JumpHotBuffer", new Action(tr("Jump to hot chat"), coll, - this, SLOT(on_jumpHotBuffer_triggered()), QKeySequence(Qt::META + Qt::Key_A))); - - // Jump keys + coll->addAction("ConfigureQuassel", configureQuasselAct); + + // Help + QAction *aboutQuasselAct = new Action(SmallIcon("quassel"), tr("&About Quassel"), coll, + this, SLOT(showAboutDlg())); + aboutQuasselAct->setMenuRole(QAction::AboutRole); + coll->addAction("AboutQuassel", aboutQuasselAct); + + QAction *aboutQtAct = new Action(QIcon(":/pics/qt-logo.png"), tr("About &Qt"), coll, + qApp, SLOT(aboutQt())); + aboutQtAct->setMenuRole(QAction::AboutQtRole); + coll->addAction("AboutQt", aboutQtAct); + coll->addAction("DebugNetworkModel", new Action(SmallIcon("tools-report-bug"), tr("Debug &NetworkModel"), coll, + this, SLOT(on_actionDebugNetworkModel_triggered()))); + coll->addAction("DebugBufferViewOverlay", new Action(SmallIcon("tools-report-bug"), tr("Debug &BufferViewOverlay"), coll, + this, SLOT(on_actionDebugBufferViewOverlay_triggered()))); + coll->addAction("DebugMessageModel", new Action(SmallIcon("tools-report-bug"), tr("Debug &MessageModel"), coll, + this, SLOT(on_actionDebugMessageModel_triggered()))); + coll->addAction("DebugHotList", new Action(SmallIcon("tools-report-bug"), tr("Debug &HotList"), coll, + this, SLOT(on_actionDebugHotList_triggered()))); + coll->addAction("DebugLog", new Action(SmallIcon("tools-report-bug"), tr("Debug &Log"), coll, + this, SLOT(on_actionDebugLog_triggered()))); + coll->addAction("ReloadStyle", new Action(SmallIcon("view-refresh"), tr("Reload Stylesheet"), coll, + QtUi::style(), SLOT(reload()), QKeySequence::Refresh)); + + coll->addAction("HideCurrentBuffer", new Action(tr("Hide Current Buffer"), coll, + this, SLOT(hideCurrentBuffer()), QKeySequence::Close)); + + // Navigation + coll = QtUi::actionCollection("Navigation", tr("Navigation")); + + coll->addAction("JumpHotBuffer", new Action(tr("Jump to hot chat"), coll, + this, SLOT(on_jumpHotBuffer_triggered()), QKeySequence(Qt::META + Qt::Key_A))); + + // Jump keys #ifdef Q_WS_MAC - const int bindModifier = Qt::ControlModifier | Qt::AltModifier; - const int jumpModifier = Qt::ControlModifier; + const int bindModifier = Qt::ControlModifier | Qt::AltModifier; + const int jumpModifier = Qt::ControlModifier; #else - const int bindModifier = Qt::ControlModifier; - const int jumpModifier = Qt::AltModifier; + const int bindModifier = Qt::ControlModifier; + const int jumpModifier = Qt::AltModifier; #endif - coll->addAction("BindJumpKey0", new Action(tr("Set Quick Access #0"), coll, this, SLOT(bindJumpKey()), - QKeySequence(bindModifier + Qt::Key_0)))->setProperty("Index", 0); - coll->addAction("BindJumpKey1", new Action(tr("Set Quick Access #1"), coll, this, SLOT(bindJumpKey()), - QKeySequence(bindModifier + Qt::Key_1)))->setProperty("Index", 1); - coll->addAction("BindJumpKey2", new Action(tr("Set Quick Access #2"), coll, this, SLOT(bindJumpKey()), - QKeySequence(bindModifier + Qt::Key_2)))->setProperty("Index", 2); - coll->addAction("BindJumpKey3", new Action(tr("Set Quick Access #3"), coll, this, SLOT(bindJumpKey()), - QKeySequence(bindModifier + Qt::Key_3)))->setProperty("Index", 3); - coll->addAction("BindJumpKey4", new Action(tr("Set Quick Access #4"), coll, this, SLOT(bindJumpKey()), - QKeySequence(bindModifier + Qt::Key_4)))->setProperty("Index", 4); - coll->addAction("BindJumpKey5", new Action(tr("Set Quick Access #5"), coll, this, SLOT(bindJumpKey()), - QKeySequence(bindModifier + Qt::Key_5)))->setProperty("Index", 5); - coll->addAction("BindJumpKey6", new Action(tr("Set Quick Access #6"), coll, this, SLOT(bindJumpKey()), - QKeySequence(bindModifier + Qt::Key_6)))->setProperty("Index", 6); - coll->addAction("BindJumpKey7", new Action(tr("Set Quick Access #7"), coll, this, SLOT(bindJumpKey()), - QKeySequence(bindModifier + Qt::Key_7)))->setProperty("Index", 7); - coll->addAction("BindJumpKey8", new Action(tr("Set Quick Access #8"), coll, this, SLOT(bindJumpKey()), - QKeySequence(bindModifier + Qt::Key_8)))->setProperty("Index", 8); - coll->addAction("BindJumpKey9", new Action(tr("Set Quick Access #9"), coll, this, SLOT(bindJumpKey()), - QKeySequence(bindModifier + Qt::Key_9)))->setProperty("Index", 9); - - coll->addAction("JumpKey0", new Action(tr("Quick Access #0"), coll, this, SLOT(onJumpKey()), - QKeySequence(jumpModifier + Qt::Key_0)))->setProperty("Index", 0); - coll->addAction("JumpKey1", new Action(tr("Quick Access #1"), coll, this, SLOT(onJumpKey()), - QKeySequence(jumpModifier + Qt::Key_1)))->setProperty("Index", 1); - coll->addAction("JumpKey2", new Action(tr("Quick Access #2"), coll, this, SLOT(onJumpKey()), - QKeySequence(jumpModifier + Qt::Key_2)))->setProperty("Index", 2); - coll->addAction("JumpKey3", new Action(tr("Quick Access #3"), coll, this, SLOT(onJumpKey()), - QKeySequence(jumpModifier + Qt::Key_3)))->setProperty("Index", 3); - coll->addAction("JumpKey4", new Action(tr("Quick Access #4"), coll, this, SLOT(onJumpKey()), - QKeySequence(jumpModifier + Qt::Key_4)))->setProperty("Index", 4); - coll->addAction("JumpKey5", new Action(tr("Quick Access #5"), coll, this, SLOT(onJumpKey()), - QKeySequence(jumpModifier + Qt::Key_5)))->setProperty("Index", 5); - coll->addAction("JumpKey6", new Action(tr("Quick Access #6"), coll, this, SLOT(onJumpKey()), - QKeySequence(jumpModifier + Qt::Key_6)))->setProperty("Index", 6); - coll->addAction("JumpKey7", new Action(tr("Quick Access #7"), coll, this, SLOT(onJumpKey()), - QKeySequence(jumpModifier + Qt::Key_7)))->setProperty("Index", 7); - coll->addAction("JumpKey8", new Action(tr("Quick Access #8"), coll, this, SLOT(onJumpKey()), - QKeySequence(jumpModifier + Qt::Key_8)))->setProperty("Index", 8); - coll->addAction("JumpKey9", new Action(tr("Quick Access #9"), coll, this, SLOT(onJumpKey()), - QKeySequence(jumpModifier + Qt::Key_9)))->setProperty("Index", 9); - - // Buffer navigation - coll->addAction("NextBufferView", new Action(SmallIcon("go-next-view"), tr("Activate Next Chat List"), coll, - this, SLOT(nextBufferView()), QKeySequence(QKeySequence::Forward))); - coll->addAction("PreviousBufferView", new Action(SmallIcon("go-previous-view"), tr("Activate Previous Chat List"), coll, - this, SLOT(previousBufferView()), QKeySequence::Back)); - coll->addAction("NextBuffer", new Action(SmallIcon("go-down"), tr("Go to Next Chat"), coll, - this, SLOT(nextBuffer()), QKeySequence(Qt::ALT + Qt::Key_Down))); - coll->addAction("PreviousBuffer", new Action(SmallIcon("go-up"), tr("Go to Previous Chat"), coll, - this, SLOT(previousBuffer()), QKeySequence(Qt::ALT + Qt::Key_Up))); -} - -void MainWin::setupMenus() { - ActionCollection *coll = QtUi::actionCollection("General"); - - _fileMenu = menuBar()->addMenu(tr("&File")); - - static const QStringList coreActions = QStringList() - << "ConnectCore" << "DisconnectCore" << "CoreInfo"; - - QAction *coreAction; - foreach(QString actionName, coreActions) { - coreAction = coll->action(actionName); - _fileMenu->addAction(coreAction); - flagRemoteCoreOnly(coreAction); - } - flagRemoteCoreOnly(_fileMenu->addSeparator()); + coll->addAction("BindJumpKey0", new Action(tr("Set Quick Access #0"), coll, this, SLOT(bindJumpKey()), + QKeySequence(bindModifier + Qt::Key_0)))->setProperty("Index", 0); + coll->addAction("BindJumpKey1", new Action(tr("Set Quick Access #1"), coll, this, SLOT(bindJumpKey()), + QKeySequence(bindModifier + Qt::Key_1)))->setProperty("Index", 1); + coll->addAction("BindJumpKey2", new Action(tr("Set Quick Access #2"), coll, this, SLOT(bindJumpKey()), + QKeySequence(bindModifier + Qt::Key_2)))->setProperty("Index", 2); + coll->addAction("BindJumpKey3", new Action(tr("Set Quick Access #3"), coll, this, SLOT(bindJumpKey()), + QKeySequence(bindModifier + Qt::Key_3)))->setProperty("Index", 3); + coll->addAction("BindJumpKey4", new Action(tr("Set Quick Access #4"), coll, this, SLOT(bindJumpKey()), + QKeySequence(bindModifier + Qt::Key_4)))->setProperty("Index", 4); + coll->addAction("BindJumpKey5", new Action(tr("Set Quick Access #5"), coll, this, SLOT(bindJumpKey()), + QKeySequence(bindModifier + Qt::Key_5)))->setProperty("Index", 5); + coll->addAction("BindJumpKey6", new Action(tr("Set Quick Access #6"), coll, this, SLOT(bindJumpKey()), + QKeySequence(bindModifier + Qt::Key_6)))->setProperty("Index", 6); + coll->addAction("BindJumpKey7", new Action(tr("Set Quick Access #7"), coll, this, SLOT(bindJumpKey()), + QKeySequence(bindModifier + Qt::Key_7)))->setProperty("Index", 7); + coll->addAction("BindJumpKey8", new Action(tr("Set Quick Access #8"), coll, this, SLOT(bindJumpKey()), + QKeySequence(bindModifier + Qt::Key_8)))->setProperty("Index", 8); + coll->addAction("BindJumpKey9", new Action(tr("Set Quick Access #9"), coll, this, SLOT(bindJumpKey()), + QKeySequence(bindModifier + Qt::Key_9)))->setProperty("Index", 9); + + coll->addAction("JumpKey0", new Action(tr("Quick Access #0"), coll, this, SLOT(onJumpKey()), + QKeySequence(jumpModifier + Qt::Key_0)))->setProperty("Index", 0); + coll->addAction("JumpKey1", new Action(tr("Quick Access #1"), coll, this, SLOT(onJumpKey()), + QKeySequence(jumpModifier + Qt::Key_1)))->setProperty("Index", 1); + coll->addAction("JumpKey2", new Action(tr("Quick Access #2"), coll, this, SLOT(onJumpKey()), + QKeySequence(jumpModifier + Qt::Key_2)))->setProperty("Index", 2); + coll->addAction("JumpKey3", new Action(tr("Quick Access #3"), coll, this, SLOT(onJumpKey()), + QKeySequence(jumpModifier + Qt::Key_3)))->setProperty("Index", 3); + coll->addAction("JumpKey4", new Action(tr("Quick Access #4"), coll, this, SLOT(onJumpKey()), + QKeySequence(jumpModifier + Qt::Key_4)))->setProperty("Index", 4); + coll->addAction("JumpKey5", new Action(tr("Quick Access #5"), coll, this, SLOT(onJumpKey()), + QKeySequence(jumpModifier + Qt::Key_5)))->setProperty("Index", 5); + coll->addAction("JumpKey6", new Action(tr("Quick Access #6"), coll, this, SLOT(onJumpKey()), + QKeySequence(jumpModifier + Qt::Key_6)))->setProperty("Index", 6); + coll->addAction("JumpKey7", new Action(tr("Quick Access #7"), coll, this, SLOT(onJumpKey()), + QKeySequence(jumpModifier + Qt::Key_7)))->setProperty("Index", 7); + coll->addAction("JumpKey8", new Action(tr("Quick Access #8"), coll, this, SLOT(onJumpKey()), + QKeySequence(jumpModifier + Qt::Key_8)))->setProperty("Index", 8); + coll->addAction("JumpKey9", new Action(tr("Quick Access #9"), coll, this, SLOT(onJumpKey()), + QKeySequence(jumpModifier + Qt::Key_9)))->setProperty("Index", 9); + + // Buffer navigation + coll->addAction("NextBufferView", new Action(SmallIcon("go-next-view"), tr("Activate Next Chat List"), coll, + this, SLOT(nextBufferView()), QKeySequence(QKeySequence::Forward))); + coll->addAction("PreviousBufferView", new Action(SmallIcon("go-previous-view"), tr("Activate Previous Chat List"), coll, + this, SLOT(previousBufferView()), QKeySequence::Back)); + coll->addAction("NextBuffer", new Action(SmallIcon("go-down"), tr("Go to Next Chat"), coll, + this, SLOT(nextBuffer()), QKeySequence(Qt::ALT + Qt::Key_Down))); + coll->addAction("PreviousBuffer", new Action(SmallIcon("go-up"), tr("Go to Previous Chat"), coll, + this, SLOT(previousBuffer()), QKeySequence(Qt::ALT + Qt::Key_Up))); +} + + +void MainWin::setupMenus() +{ + ActionCollection *coll = QtUi::actionCollection("General"); + + _fileMenu = menuBar()->addMenu(tr("&File")); + + static const QStringList coreActions = QStringList() + << "ConnectCore" << "DisconnectCore" << "CoreInfo"; + + QAction *coreAction; + foreach(QString actionName, coreActions) { + coreAction = coll->action(actionName); + _fileMenu->addAction(coreAction); + flagRemoteCoreOnly(coreAction); + } + flagRemoteCoreOnly(_fileMenu->addSeparator()); - _networksMenu = _fileMenu->addMenu(tr("&Networks")); - _networksMenu->addAction(coll->action("ConfigureNetworks")); - _networksMenu->addSeparator(); - _fileMenu->addSeparator(); - _fileMenu->addAction(coll->action("Quit")); + _networksMenu = _fileMenu->addMenu(tr("&Networks")); + _networksMenu->addAction(coll->action("ConfigureNetworks")); + _networksMenu->addSeparator(); + _fileMenu->addSeparator(); + _fileMenu->addAction(coll->action("Quit")); - _viewMenu = menuBar()->addMenu(tr("&View")); - _bufferViewsMenu = _viewMenu->addMenu(tr("&Chat Lists")); - _bufferViewsMenu->addAction(coll->action("ConfigureBufferViews")); - _toolbarMenu = _viewMenu->addMenu(tr("&Toolbars")); - _viewMenu->addSeparator(); + _viewMenu = menuBar()->addMenu(tr("&View")); + _bufferViewsMenu = _viewMenu->addMenu(tr("&Chat Lists")); + _bufferViewsMenu->addAction(coll->action("ConfigureBufferViews")); + _toolbarMenu = _viewMenu->addMenu(tr("&Toolbars")); + _viewMenu->addSeparator(); - _viewMenu->addAction(coll->action("ToggleMenuBar")); - _viewMenu->addAction(coll->action("ToggleStatusBar")); - _viewMenu->addAction(coll->action("ToggleSearchBar")); + _viewMenu->addAction(coll->action("ToggleMenuBar")); + _viewMenu->addAction(coll->action("ToggleStatusBar")); + _viewMenu->addAction(coll->action("ToggleSearchBar")); - coreAction = coll->action("ShowAwayLog"); - flagRemoteCoreOnly(coreAction); - _viewMenu->addAction(coreAction); + coreAction = coll->action("ShowAwayLog"); + flagRemoteCoreOnly(coreAction); + _viewMenu->addAction(coreAction); - _viewMenu->addSeparator(); - _viewMenu->addAction(coll->action("LockLayout")); + _viewMenu->addSeparator(); + _viewMenu->addAction(coll->action("LockLayout")); - _settingsMenu = menuBar()->addMenu(tr("&Settings")); + _settingsMenu = menuBar()->addMenu(tr("&Settings")); #ifdef HAVE_KDE - _settingsMenu->addAction(KStandardAction::configureNotifications(this, SLOT(showNotificationsDlg()), this)); - _settingsMenu->addAction(KStandardAction::keyBindings(this, SLOT(showShortcutsDlg()), this)); + _settingsMenu->addAction(KStandardAction::configureNotifications(this, SLOT(showNotificationsDlg()), this)); + _settingsMenu->addAction(KStandardAction::keyBindings(this, SLOT(showShortcutsDlg()), this)); #else - _settingsMenu->addAction(coll->action("ConfigureShortcuts")); + _settingsMenu->addAction(coll->action("ConfigureShortcuts")); #endif - _settingsMenu->addAction(coll->action("ConfigureQuassel")); + _settingsMenu->addAction(coll->action("ConfigureQuassel")); - _helpMenu = menuBar()->addMenu(tr("&Help")); - _helpMenu->addAction(coll->action("AboutQuassel")); + _helpMenu = menuBar()->addMenu(tr("&Help")); + _helpMenu->addAction(coll->action("AboutQuassel")); #ifndef HAVE_KDE - _helpMenu->addAction(coll->action("AboutQt")); + _helpMenu->addAction(coll->action("AboutQt")); #else - _helpMenu->addAction(KStandardAction::aboutKDE(_kHelpMenu, SLOT(aboutKDE()), this)); + _helpMenu->addAction(KStandardAction::aboutKDE(_kHelpMenu, SLOT(aboutKDE()), this)); #endif - _helpMenu->addSeparator(); - _helpDebugMenu = _helpMenu->addMenu(SmallIcon("tools-report-bug"), tr("Debug")); - _helpDebugMenu->addAction(coll->action("DebugNetworkModel")); - _helpDebugMenu->addAction(coll->action("DebugBufferViewOverlay")); - _helpDebugMenu->addAction(coll->action("DebugMessageModel")); - _helpDebugMenu->addAction(coll->action("DebugHotList")); - _helpDebugMenu->addAction(coll->action("DebugLog")); - _helpDebugMenu->addSeparator(); - _helpDebugMenu->addAction(coll->action("ReloadStyle")); + _helpMenu->addSeparator(); + _helpDebugMenu = _helpMenu->addMenu(SmallIcon("tools-report-bug"), tr("Debug")); + _helpDebugMenu->addAction(coll->action("DebugNetworkModel")); + _helpDebugMenu->addAction(coll->action("DebugBufferViewOverlay")); + _helpDebugMenu->addAction(coll->action("DebugMessageModel")); + _helpDebugMenu->addAction(coll->action("DebugHotList")); + _helpDebugMenu->addAction(coll->action("DebugLog")); + _helpDebugMenu->addSeparator(); + _helpDebugMenu->addAction(coll->action("ReloadStyle")); - // Toggle visibility - QAction *showMenuBar = QtUi::actionCollection("General")->action("ToggleMenuBar"); + // Toggle visibility + QAction *showMenuBar = QtUi::actionCollection("General")->action("ToggleMenuBar"); - QtUiSettings uiSettings; - bool enabled = uiSettings.value("ShowMenuBar", QVariant(true)).toBool(); - showMenuBar->setChecked(enabled); - enabled ? menuBar()->show() : menuBar()->hide(); + QtUiSettings uiSettings; + bool enabled = uiSettings.value("ShowMenuBar", QVariant(true)).toBool(); + showMenuBar->setChecked(enabled); + enabled ? menuBar()->show() : menuBar()->hide(); - connect(showMenuBar, SIGNAL(toggled(bool)), menuBar(), SLOT(setVisible(bool))); - connect(showMenuBar, SIGNAL(toggled(bool)), this, SLOT(saveMenuBarStatus(bool))); + connect(showMenuBar, SIGNAL(toggled(bool)), menuBar(), SLOT(setVisible(bool))); + connect(showMenuBar, SIGNAL(toggled(bool)), this, SLOT(saveMenuBarStatus(bool))); } -void MainWin::setupBufferWidget() { - _bufferWidget = new BufferWidget(this); - _bufferWidget->setModel(Client::bufferModel()); - _bufferWidget->setSelectionModel(Client::bufferModel()->standardSelectionModel()); - setCentralWidget(_bufferWidget); -} -void MainWin::addBufferView(int bufferViewConfigId) { - addBufferView(Client::bufferViewManager()->clientBufferViewConfig(bufferViewConfigId)); +void MainWin::setupBufferWidget() +{ + _bufferWidget = new BufferWidget(this); + _bufferWidget->setModel(Client::bufferModel()); + _bufferWidget->setSelectionModel(Client::bufferModel()->standardSelectionModel()); + setCentralWidget(_bufferWidget); } -void MainWin::addBufferView(ClientBufferViewConfig *config) { - if(!config) - return; - config->setLocked(QtUiSettings().value("LockLayout", false).toBool()); - BufferViewDock *dock = new BufferViewDock(config, this); +void MainWin::addBufferView(int bufferViewConfigId) +{ + addBufferView(Client::bufferViewManager()->clientBufferViewConfig(bufferViewConfigId)); +} - //create the view and initialize it's filter - BufferView *view = new BufferView(dock); - view->setFilteredModel(Client::bufferModel(), config); - view->installEventFilter(_inputWidget); // for key presses - Client::bufferModel()->synchronizeView(view); +void MainWin::addBufferView(ClientBufferViewConfig *config) +{ + if (!config) + return; - dock->setWidget(view); - dock->setVisible(_layoutLoaded); // don't show before state has been restored + config->setLocked(QtUiSettings().value("LockLayout", false).toBool()); + BufferViewDock *dock = new BufferViewDock(config, this); - addDockWidget(Qt::LeftDockWidgetArea, dock); - _bufferViewsMenu->addAction(dock->toggleViewAction()); + //create the view and initialize it's filter + BufferView *view = new BufferView(dock); + view->setFilteredModel(Client::bufferModel(), config); + view->installEventFilter(_inputWidget); // for key presses - connect(dock->toggleViewAction(), SIGNAL(toggled(bool)), this, SLOT(bufferViewToggled(bool))); - connect(dock, SIGNAL(visibilityChanged(bool)), SLOT(bufferViewVisibilityChanged(bool))); - _bufferViews.append(dock); + Client::bufferModel()->synchronizeView(view); - if(!activeBufferView()) - nextBufferView(); -} + dock->setWidget(view); + dock->setVisible(_layoutLoaded); // don't show before state has been restored -void MainWin::removeBufferView(int bufferViewConfigId) { - QVariant actionData; - BufferViewDock *dock; - foreach(QAction *action, _bufferViewsMenu->actions()) { - actionData = action->data(); - if(!actionData.isValid()) - continue; + addDockWidget(Qt::LeftDockWidgetArea, dock); + _bufferViewsMenu->addAction(dock->toggleViewAction()); - dock = qobject_cast(action->parent()); - if(dock && actionData.toInt() == bufferViewConfigId) { - removeAction(action); - Client::bufferViewOverlay()->removeView(dock->bufferViewId()); - _bufferViews.removeAll(dock); + connect(dock->toggleViewAction(), SIGNAL(toggled(bool)), this, SLOT(bufferViewToggled(bool))); + connect(dock, SIGNAL(visibilityChanged(bool)), SLOT(bufferViewVisibilityChanged(bool))); + _bufferViews.append(dock); - if(dock->isActive()) { - dock->setActive(false); - _activeBufferViewIndex = -1; + if (!activeBufferView()) nextBufferView(); - } +} - dock->deleteLater(); + +void MainWin::removeBufferView(int bufferViewConfigId) +{ + QVariant actionData; + BufferViewDock *dock; + foreach(QAction *action, _bufferViewsMenu->actions()) { + actionData = action->data(); + if (!actionData.isValid()) + continue; + + dock = qobject_cast(action->parent()); + if (dock && actionData.toInt() == bufferViewConfigId) { + removeAction(action); + Client::bufferViewOverlay()->removeView(dock->bufferViewId()); + _bufferViews.removeAll(dock); + + if (dock->isActive()) { + dock->setActive(false); + _activeBufferViewIndex = -1; + nextBufferView(); + } + + dock->deleteLater(); + } } - } } -void MainWin::bufferViewToggled(bool enabled) { - if(!enabled && !isVisible()) { - // hiding the mainwindow triggers a toggle of the bufferview (which pretty much sucks big time) - // since this isn't our fault and we can't do anything about it, we suppress the resulting calls - return; - } - QAction *action = qobject_cast(sender()); - Q_ASSERT(action); - BufferViewDock *dock = qobject_cast(action->parent()); - Q_ASSERT(dock); - // Make sure we don't toggle backlog fetch for a view we've already removed - if(!_bufferViews.contains(dock)) - return; +void MainWin::bufferViewToggled(bool enabled) +{ + if (!enabled && !isVisible()) { + // hiding the mainwindow triggers a toggle of the bufferview (which pretty much sucks big time) + // since this isn't our fault and we can't do anything about it, we suppress the resulting calls + return; + } + QAction *action = qobject_cast(sender()); + Q_ASSERT(action); + BufferViewDock *dock = qobject_cast(action->parent()); + Q_ASSERT(dock); - if(enabled) - Client::bufferViewOverlay()->addView(dock->bufferViewId()); - else - Client::bufferViewOverlay()->removeView(dock->bufferViewId()); -} + // Make sure we don't toggle backlog fetch for a view we've already removed + if (!_bufferViews.contains(dock)) + return; -void MainWin::bufferViewVisibilityChanged(bool visible) { - Q_UNUSED(visible); - BufferViewDock *dock = qobject_cast(sender()); - Q_ASSERT(dock); - if((!dock->isHidden() && !activeBufferView()) || (dock->isHidden() && dock->isActive())) - nextBufferView(); + if (enabled) + Client::bufferViewOverlay()->addView(dock->bufferViewId()); + else + Client::bufferViewOverlay()->removeView(dock->bufferViewId()); } -BufferView *MainWin::allBuffersView() const { - // "All Buffers" is always the first dock created - if(_bufferViews.count() > 0) - return _bufferViews[0]->bufferView(); - return 0; + +void MainWin::bufferViewVisibilityChanged(bool visible) +{ + Q_UNUSED(visible); + BufferViewDock *dock = qobject_cast(sender()); + Q_ASSERT(dock); + if ((!dock->isHidden() && !activeBufferView()) || (dock->isHidden() && dock->isActive())) + nextBufferView(); } -BufferView *MainWin::activeBufferView() const { - if(_activeBufferViewIndex < 0 || _activeBufferViewIndex >= _bufferViews.count()) + +BufferView *MainWin::allBuffersView() const +{ + // "All Buffers" is always the first dock created + if (_bufferViews.count() > 0) + return _bufferViews[0]->bufferView(); return 0; - BufferViewDock *dock = _bufferViews.at(_activeBufferViewIndex); - return dock->isActive() ? qobject_cast(dock->widget()) : 0; } -void MainWin::changeActiveBufferView(int bufferViewId) { - if(bufferViewId < 0) - return; - BufferView *current = activeBufferView(); - if(current) { - qobject_cast(current->parent())->setActive(false); - _activeBufferViewIndex = -1; - } - - for(int i = 0; i < _bufferViews.count(); i++) { - BufferViewDock *dock = _bufferViews.at(i); - if(dock->bufferViewId() == bufferViewId && !dock->isHidden()) { - _activeBufferViewIndex = i; - dock->setActive(true); - return; - } - } - - nextBufferView(); // fallback +BufferView *MainWin::activeBufferView() const +{ + if (_activeBufferViewIndex < 0 || _activeBufferViewIndex >= _bufferViews.count()) + return 0; + BufferViewDock *dock = _bufferViews.at(_activeBufferViewIndex); + return dock->isActive() ? qobject_cast(dock->widget()) : 0; } -void MainWin::changeActiveBufferView(bool backwards) { - BufferView *current = activeBufferView(); - if(current) - qobject_cast(current->parent())->setActive(false); - if(!_bufferViews.count()) - return; +void MainWin::changeActiveBufferView(int bufferViewId) +{ + if (bufferViewId < 0) + return; + + BufferView *current = activeBufferView(); + if (current) { + qobject_cast(current->parent())->setActive(false); + _activeBufferViewIndex = -1; + } - int c = _bufferViews.count(); - while(c--) { // yes, this will reactivate the current active one if all others fail - if(backwards) { - if(--_activeBufferViewIndex < 0) - _activeBufferViewIndex = _bufferViews.count()-1; - } else { - if(++_activeBufferViewIndex >= _bufferViews.count()) - _activeBufferViewIndex = 0; + for (int i = 0; i < _bufferViews.count(); i++) { + BufferViewDock *dock = _bufferViews.at(i); + if (dock->bufferViewId() == bufferViewId && !dock->isHidden()) { + _activeBufferViewIndex = i; + dock->setActive(true); + return; + } } - BufferViewDock *dock = _bufferViews.at(_activeBufferViewIndex); - if(dock->isHidden()) - continue; + nextBufferView(); // fallback +} + - dock->setActive(true); - return; - } +void MainWin::changeActiveBufferView(bool backwards) +{ + BufferView *current = activeBufferView(); + if (current) + qobject_cast(current->parent())->setActive(false); + + if (!_bufferViews.count()) + return; + + int c = _bufferViews.count(); + while (c--) { // yes, this will reactivate the current active one if all others fail + if (backwards) { + if (--_activeBufferViewIndex < 0) + _activeBufferViewIndex = _bufferViews.count()-1; + } + else { + if (++_activeBufferViewIndex >= _bufferViews.count()) + _activeBufferViewIndex = 0; + } + + BufferViewDock *dock = _bufferViews.at(_activeBufferViewIndex); + if (dock->isHidden()) + continue; + + dock->setActive(true); + return; + } - _activeBufferViewIndex = -1; + _activeBufferViewIndex = -1; } -void MainWin::nextBufferView() { - changeActiveBufferView(false); + +void MainWin::nextBufferView() +{ + changeActiveBufferView(false); } -void MainWin::previousBufferView() { - changeActiveBufferView(true); + +void MainWin::previousBufferView() +{ + changeActiveBufferView(true); } -void MainWin::nextBuffer() { - BufferView *view = activeBufferView(); - if(view) - view->nextBuffer(); + +void MainWin::nextBuffer() +{ + BufferView *view = activeBufferView(); + if (view) + view->nextBuffer(); } -void MainWin::previousBuffer() { - BufferView *view = activeBufferView(); - if(view) - view->previousBuffer(); + +void MainWin::previousBuffer() +{ + BufferView *view = activeBufferView(); + if (view) + view->previousBuffer(); } -void MainWin::hideCurrentBuffer() { - BufferView *view = activeBufferView(); - if(view) - view->hideCurrentBuffer(); + +void MainWin::hideCurrentBuffer() +{ + BufferView *view = activeBufferView(); + if (view) + view->hideCurrentBuffer(); } -void MainWin::showNotificationsDlg() { - SettingsPageDlg dlg(new NotificationsSettingsPage(this), this); - dlg.exec(); + +void MainWin::showNotificationsDlg() +{ + SettingsPageDlg dlg(new NotificationsSettingsPage(this), this); + dlg.exec(); } -void MainWin::on_actionConfigureNetworks_triggered() { - SettingsPageDlg dlg(new NetworksSettingsPage(this), this); - dlg.exec(); + +void MainWin::on_actionConfigureNetworks_triggered() +{ + SettingsPageDlg dlg(new NetworksSettingsPage(this), this); + dlg.exec(); } -void MainWin::on_actionConfigureViews_triggered() { - SettingsPageDlg dlg(new BufferViewSettingsPage(this), this); - dlg.exec(); + +void MainWin::on_actionConfigureViews_triggered() +{ + SettingsPageDlg dlg(new BufferViewSettingsPage(this), this); + dlg.exec(); } -void MainWin::on_actionLockLayout_toggled(bool lock) { - QList docks = findChildren(); - foreach(VerticalDock *dock, docks) { - dock->showTitle(!lock); - } - if(Client::bufferViewManager()) { - foreach(ClientBufferViewConfig *config, Client::bufferViewManager()->clientBufferViewConfigs()) { - config->setLocked(lock); + +void MainWin::on_actionLockLayout_toggled(bool lock) +{ + QList docks = findChildren(); + foreach(VerticalDock *dock, docks) { + dock->showTitle(!lock); + } + if (Client::bufferViewManager()) { + foreach(ClientBufferViewConfig *config, Client::bufferViewManager()->clientBufferViewConfigs()) { + config->setLocked(lock); + } } - } - QtUiSettings().setValue("LockLayout", lock); + QtUiSettings().setValue("LockLayout", lock); } -void MainWin::setupNickWidget() { - // create nick dock - NickListDock *nickDock = new NickListDock(tr("Nicks"), this); - nickDock->setObjectName("NickDock"); - nickDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); - _nickListWidget = new NickListWidget(nickDock); - nickDock->setWidget(_nickListWidget); +void MainWin::setupNickWidget() +{ + // create nick dock + NickListDock *nickDock = new NickListDock(tr("Nicks"), this); + nickDock->setObjectName("NickDock"); + nickDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + + _nickListWidget = new NickListWidget(nickDock); + nickDock->setWidget(_nickListWidget); - addDockWidget(Qt::RightDockWidgetArea, nickDock); - _viewMenu->addAction(nickDock->toggleViewAction()); - nickDock->toggleViewAction()->setText(tr("Show Nick List")); + addDockWidget(Qt::RightDockWidgetArea, nickDock); + _viewMenu->addAction(nickDock->toggleViewAction()); + nickDock->toggleViewAction()->setText(tr("Show Nick List")); - // See NickListDock::NickListDock(); - // connect(nickDock->toggleViewAction(), SIGNAL(triggered(bool)), nickListWidget, SLOT(showWidget(bool))); + // See NickListDock::NickListDock(); + // connect(nickDock->toggleViewAction(), SIGNAL(triggered(bool)), nickListWidget, SLOT(showWidget(bool))); - // attach the NickListWidget to the BufferModel and the default selection - _nickListWidget->setModel(Client::bufferModel()); - _nickListWidget->setSelectionModel(Client::bufferModel()->standardSelectionModel()); + // attach the NickListWidget to the BufferModel and the default selection + _nickListWidget->setModel(Client::bufferModel()); + _nickListWidget->setSelectionModel(Client::bufferModel()->standardSelectionModel()); } -void MainWin::setupChatMonitor() { - VerticalDock *dock = new VerticalDock(tr("Chat Monitor"), this); - dock->setObjectName("ChatMonitorDock"); - ChatMonitorFilter *filter = new ChatMonitorFilter(Client::messageModel(), this); - _chatMonitorView = new ChatMonitorView(filter, this); - _chatMonitorView->setFocusProxy(_inputWidget); - _chatMonitorView->show(); - dock->setWidget(_chatMonitorView); - dock->hide(); +void MainWin::setupChatMonitor() +{ + VerticalDock *dock = new VerticalDock(tr("Chat Monitor"), this); + dock->setObjectName("ChatMonitorDock"); + + ChatMonitorFilter *filter = new ChatMonitorFilter(Client::messageModel(), this); + _chatMonitorView = new ChatMonitorView(filter, this); + _chatMonitorView->setFocusProxy(_inputWidget); + _chatMonitorView->show(); + dock->setWidget(_chatMonitorView); + dock->hide(); - addDockWidget(Qt::TopDockWidgetArea, dock, Qt::Vertical); - _viewMenu->addAction(dock->toggleViewAction()); - dock->toggleViewAction()->setText(tr("Show Chat Monitor")); + addDockWidget(Qt::TopDockWidgetArea, dock, Qt::Vertical); + _viewMenu->addAction(dock->toggleViewAction()); + dock->toggleViewAction()->setText(tr("Show Chat Monitor")); } -void MainWin::setupInputWidget() { - VerticalDock *dock = new VerticalDock(tr("Inputline"), this); - dock->setObjectName("InputDock"); - _inputWidget = new InputWidget(dock); - dock->setWidget(_inputWidget); +void MainWin::setupInputWidget() +{ + VerticalDock *dock = new VerticalDock(tr("Inputline"), this); + dock->setObjectName("InputDock"); + + _inputWidget = new InputWidget(dock); + dock->setWidget(_inputWidget); - addDockWidget(Qt::BottomDockWidgetArea, dock); + addDockWidget(Qt::BottomDockWidgetArea, dock); - _viewMenu->addAction(dock->toggleViewAction()); - dock->toggleViewAction()->setText(tr("Show Input Line")); + _viewMenu->addAction(dock->toggleViewAction()); + dock->toggleViewAction()->setText(tr("Show Input Line")); - _inputWidget->setModel(Client::bufferModel()); - _inputWidget->setSelectionModel(Client::bufferModel()->standardSelectionModel()); + _inputWidget->setModel(Client::bufferModel()); + _inputWidget->setSelectionModel(Client::bufferModel()->standardSelectionModel()); - _bufferWidget->setFocusProxy(_inputWidget); + _bufferWidget->setFocusProxy(_inputWidget); - _inputWidget->inputLine()->installEventFilter(_bufferWidget); + _inputWidget->inputLine()->installEventFilter(_bufferWidget); - connect(_topicWidget, SIGNAL(switchedPlain()), _bufferWidget, SLOT(setFocus())); + connect(_topicWidget, SIGNAL(switchedPlain()), _bufferWidget, SLOT(setFocus())); } -void MainWin::setupTopicWidget() { - VerticalDock *dock = new VerticalDock(tr("Topic"), this); - dock->setObjectName("TopicDock"); - _topicWidget = new TopicWidget(dock); - dock->setWidget(_topicWidget); +void MainWin::setupTopicWidget() +{ + VerticalDock *dock = new VerticalDock(tr("Topic"), this); + dock->setObjectName("TopicDock"); + _topicWidget = new TopicWidget(dock); - _topicWidget->setModel(Client::bufferModel()); - _topicWidget->setSelectionModel(Client::bufferModel()->standardSelectionModel()); + dock->setWidget(_topicWidget); - addDockWidget(Qt::TopDockWidgetArea, dock, Qt::Vertical); + _topicWidget->setModel(Client::bufferModel()); + _topicWidget->setSelectionModel(Client::bufferModel()->standardSelectionModel()); - _viewMenu->addAction(dock->toggleViewAction()); - dock->toggleViewAction()->setText(tr("Show Topic Line")); + addDockWidget(Qt::TopDockWidgetArea, dock, Qt::Vertical); + + _viewMenu->addAction(dock->toggleViewAction()); + dock->toggleViewAction()->setText(tr("Show Topic Line")); } -void MainWin::setupViewMenuTail() { - _viewMenu->addSeparator(); - _viewMenu->addAction(QtUi::actionCollection("General")->action("ToggleFullscreen")); + +void MainWin::setupViewMenuTail() +{ + _viewMenu->addSeparator(); + _viewMenu->addAction(QtUi::actionCollection("General")->action("ToggleFullscreen")); } -void MainWin::setupTitleSetter() { - _titleSetter.setModel(Client::bufferModel()); - _titleSetter.setSelectionModel(Client::bufferModel()->standardSelectionModel()); + +void MainWin::setupTitleSetter() +{ + _titleSetter.setModel(Client::bufferModel()); + _titleSetter.setSelectionModel(Client::bufferModel()->standardSelectionModel()); } -void MainWin::setupStatusBar() { - // MessageProcessor progress - statusBar()->addPermanentWidget(_msgProcessorStatusWidget); - // Connection state - _coreConnectionStatusWidget->update(); - statusBar()->addPermanentWidget(_coreConnectionStatusWidget); +void MainWin::setupStatusBar() +{ + // MessageProcessor progress + statusBar()->addPermanentWidget(_msgProcessorStatusWidget); + + // Connection state + _coreConnectionStatusWidget->update(); + statusBar()->addPermanentWidget(_coreConnectionStatusWidget); - QAction *showStatusbar = QtUi::actionCollection("General")->action("ToggleStatusBar"); + QAction *showStatusbar = QtUi::actionCollection("General")->action("ToggleStatusBar"); - QtUiSettings uiSettings; + QtUiSettings uiSettings; - bool enabled = uiSettings.value("ShowStatusBar", QVariant(true)).toBool(); - showStatusbar->setChecked(enabled); - enabled ? statusBar()->show() : statusBar()->hide(); + bool enabled = uiSettings.value("ShowStatusBar", QVariant(true)).toBool(); + showStatusbar->setChecked(enabled); + enabled ? statusBar()->show() : statusBar()->hide(); - connect(showStatusbar, SIGNAL(toggled(bool)), statusBar(), SLOT(setVisible(bool))); - connect(showStatusbar, SIGNAL(toggled(bool)), this, SLOT(saveStatusBarStatus(bool))); + connect(showStatusbar, SIGNAL(toggled(bool)), statusBar(), SLOT(setVisible(bool))); + connect(showStatusbar, SIGNAL(toggled(bool)), this, SLOT(saveStatusBarStatus(bool))); - connect(Client::coreConnection(), SIGNAL(connectionMsg(QString)), statusBar(), SLOT(showMessage(QString))); + connect(Client::coreConnection(), SIGNAL(connectionMsg(QString)), statusBar(), SLOT(showMessage(QString))); } -void MainWin::setupHotList() { - FlatProxyModel *flatProxy = new FlatProxyModel(this); - flatProxy->setSourceModel(Client::bufferModel()); - _bufferHotList = new BufferHotListFilter(flatProxy); + +void MainWin::setupHotList() +{ + FlatProxyModel *flatProxy = new FlatProxyModel(this); + flatProxy->setSourceModel(Client::bufferModel()); + _bufferHotList = new BufferHotListFilter(flatProxy); } -void MainWin::saveMenuBarStatus(bool enabled) { - QtUiSettings uiSettings; - uiSettings.setValue("ShowMenuBar", enabled); + +void MainWin::saveMenuBarStatus(bool enabled) +{ + QtUiSettings uiSettings; + uiSettings.setValue("ShowMenuBar", enabled); } -void MainWin::saveStatusBarStatus(bool enabled) { - QtUiSettings uiSettings; - uiSettings.setValue("ShowStatusBar", enabled); + +void MainWin::saveStatusBarStatus(bool enabled) +{ + QtUiSettings uiSettings; + uiSettings.setValue("ShowStatusBar", enabled); } -void MainWin::setupSystray() { + +void MainWin::setupSystray() +{ #ifdef HAVE_DBUS - _systemTray = new StatusNotifierItem(this); + _systemTray = new StatusNotifierItem(this); #elif !defined QT_NO_SYSTEMTRAYICON - _systemTray = new LegacySystemTray(this); + _systemTray = new LegacySystemTray(this); #else - _systemTray = new SystemTray(this); // dummy + _systemTray = new SystemTray(this); // dummy #endif - _systemTray->init(); + _systemTray->init(); } -void MainWin::setupToolBars() { - connect(_bufferWidget, SIGNAL(currentChanged(QModelIndex)), - QtUi::toolBarActionProvider(), SLOT(currentBufferChanged(QModelIndex))); - connect(_nickListWidget, SIGNAL(nickSelectionChanged(QModelIndexList)), - QtUi::toolBarActionProvider(), SLOT(nickSelectionChanged(QModelIndexList))); + +void MainWin::setupToolBars() +{ + connect(_bufferWidget, SIGNAL(currentChanged(QModelIndex)), + QtUi::toolBarActionProvider(), SLOT(currentBufferChanged(QModelIndex))); + connect(_nickListWidget, SIGNAL(nickSelectionChanged(QModelIndexList)), + QtUi::toolBarActionProvider(), SLOT(nickSelectionChanged(QModelIndexList))); #ifdef Q_WS_MAC - setUnifiedTitleAndToolBarOnMac(true); + setUnifiedTitleAndToolBarOnMac(true); #endif #ifdef HAVE_KDE - _mainToolBar = new KToolBar("MainToolBar", this, Qt::TopToolBarArea, false, true, true); + _mainToolBar = new KToolBar("MainToolBar", this, Qt::TopToolBarArea, false, true, true); #else - _mainToolBar = new QToolBar(this); - _mainToolBar->setObjectName("MainToolBar"); + _mainToolBar = new QToolBar(this); + _mainToolBar->setObjectName("MainToolBar"); #endif - _mainToolBar->setWindowTitle(tr("Main Toolbar")); - addToolBar(_mainToolBar); + _mainToolBar->setWindowTitle(tr("Main Toolbar")); + addToolBar(_mainToolBar); - QtUi::toolBarActionProvider()->addActions(_mainToolBar, ToolBarActionProvider::MainToolBar); - _toolbarMenu->addAction(_mainToolBar->toggleViewAction()); + QtUi::toolBarActionProvider()->addActions(_mainToolBar, ToolBarActionProvider::MainToolBar); + _toolbarMenu->addAction(_mainToolBar->toggleViewAction()); } -void MainWin::connectedToCore() { - Q_CHECK_PTR(Client::bufferViewManager()); - connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigAdded(int)), this, SLOT(addBufferView(int))); - connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigDeleted(int)), this, SLOT(removeBufferView(int))); - connect(Client::bufferViewManager(), SIGNAL(initDone()), this, SLOT(loadLayout())); - setConnectedState(); +void MainWin::connectedToCore() +{ + Q_CHECK_PTR(Client::bufferViewManager()); + connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigAdded(int)), this, SLOT(addBufferView(int))); + connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigDeleted(int)), this, SLOT(removeBufferView(int))); + connect(Client::bufferViewManager(), SIGNAL(initDone()), this, SLOT(loadLayout())); + + setConnectedState(); } -void MainWin::setConnectedState() { - ActionCollection *coll = QtUi::actionCollection("General"); - coll->action("ConnectCore")->setEnabled(false); - coll->action("DisconnectCore")->setEnabled(true); - coll->action("CoreInfo")->setEnabled(true); +void MainWin::setConnectedState() +{ + ActionCollection *coll = QtUi::actionCollection("General"); - foreach(QAction *action, _fileMenu->actions()) { - if(isRemoteCoreOnly(action)) - action->setVisible(!Client::internalCore()); - } + coll->action("ConnectCore")->setEnabled(false); + coll->action("DisconnectCore")->setEnabled(true); + coll->action("CoreInfo")->setEnabled(true); - disconnect(Client::backlogManager(), SIGNAL(updateProgress(int, int)), _msgProcessorStatusWidget, SLOT(setProgress(int, int))); - disconnect(Client::backlogManager(), SIGNAL(messagesRequested(const QString &)), this, SLOT(showStatusBarMessage(const QString &))); - disconnect(Client::backlogManager(), SIGNAL(messagesProcessed(const QString &)), this, SLOT(showStatusBarMessage(const QString &))); - if(!Client::internalCore()) { - connect(Client::backlogManager(), SIGNAL(updateProgress(int, int)), _msgProcessorStatusWidget, SLOT(setProgress(int, int))); - connect(Client::backlogManager(), SIGNAL(messagesRequested(const QString &)), this, SLOT(showStatusBarMessage(const QString &))); - connect(Client::backlogManager(), SIGNAL(messagesProcessed(const QString &)), this, SLOT(showStatusBarMessage(const QString &))); - } + foreach(QAction *action, _fileMenu->actions()) { + if (isRemoteCoreOnly(action)) + action->setVisible(!Client::internalCore()); + } + + disconnect(Client::backlogManager(), SIGNAL(updateProgress(int, int)), _msgProcessorStatusWidget, SLOT(setProgress(int, int))); + disconnect(Client::backlogManager(), SIGNAL(messagesRequested(const QString &)), this, SLOT(showStatusBarMessage(const QString &))); + disconnect(Client::backlogManager(), SIGNAL(messagesProcessed(const QString &)), this, SLOT(showStatusBarMessage(const QString &))); + if (!Client::internalCore()) { + connect(Client::backlogManager(), SIGNAL(updateProgress(int, int)), _msgProcessorStatusWidget, SLOT(setProgress(int, int))); + connect(Client::backlogManager(), SIGNAL(messagesRequested(const QString &)), this, SLOT(showStatusBarMessage(const QString &))); + connect(Client::backlogManager(), SIGNAL(messagesProcessed(const QString &)), this, SLOT(showStatusBarMessage(const QString &))); + } - // _viewMenu->setEnabled(true); - if(!Client::internalCore()) - statusBar()->showMessage(tr("Connected to core.")); - else - statusBar()->clearMessage(); + // _viewMenu->setEnabled(true); + if (!Client::internalCore()) + statusBar()->showMessage(tr("Connected to core.")); + else + statusBar()->clearMessage(); - _coreConnectionStatusWidget->setVisible(!Client::internalCore()); - updateIcon(); - systemTray()->setState(SystemTray::Active); + _coreConnectionStatusWidget->setVisible(!Client::internalCore()); + updateIcon(); + systemTray()->setState(SystemTray::Active); - if(Client::networkIds().isEmpty()) { - IrcConnectionWizard *wizard = new IrcConnectionWizard(this, Qt::Sheet); - wizard->show(); - } - else { - // Monolithic always preselects last used buffer - Client only if the connection died - if(Client::coreConnection()->wasReconnect() || Quassel::runMode() == Quassel::Monolithic) { - QtUiSettings s; - BufferId lastUsedBufferId(s.value("LastUsedBufferId").toInt()); - if(lastUsedBufferId.isValid()) - Client::bufferModel()->switchToBuffer(lastUsedBufferId); + if (Client::networkIds().isEmpty()) { + IrcConnectionWizard *wizard = new IrcConnectionWizard(this, Qt::Sheet); + wizard->show(); + } + else { + // Monolithic always preselects last used buffer - Client only if the connection died + if (Client::coreConnection()->wasReconnect() || Quassel::runMode() == Quassel::Monolithic) { + QtUiSettings s; + BufferId lastUsedBufferId(s.value("LastUsedBufferId").toInt()); + if (lastUsedBufferId.isValid()) + Client::bufferModel()->switchToBuffer(lastUsedBufferId); + } } - } } -void MainWin::loadLayout() { - QtUiSettings s; - int accountId = Client::currentCoreAccount().accountId().toInt(); - QByteArray state = s.value(QString("MainWinState-%1").arg(accountId)).toByteArray(); - if(state.isEmpty()) { - foreach(BufferViewDock *view, _bufferViews) - view->show(); + +void MainWin::loadLayout() +{ + QtUiSettings s; + int accountId = Client::currentCoreAccount().accountId().toInt(); + QByteArray state = s.value(QString("MainWinState-%1").arg(accountId)).toByteArray(); + if (state.isEmpty()) { + foreach(BufferViewDock *view, _bufferViews) + view->show(); + _layoutLoaded = true; + return; + } + + restoreState(state, accountId); + int bufferViewId = s.value(QString("ActiveBufferView-%1").arg(accountId), -1).toInt(); + if (bufferViewId >= 0) + changeActiveBufferView(bufferViewId); + _layoutLoaded = true; - return; - } +} - restoreState(state, accountId); - int bufferViewId = s.value(QString("ActiveBufferView-%1").arg(accountId), -1).toInt(); - if(bufferViewId >= 0) - changeActiveBufferView(bufferViewId); - _layoutLoaded = true; +void MainWin::saveLayout() +{ + QtUiSettings s; + int accountId = _bufferViews.count() ? Client::currentCoreAccount().accountId().toInt() : 0; // only save if we still have a layout! + if (accountId > 0) { + s.setValue(QString("MainWinState-%1").arg(accountId), saveState(accountId)); + BufferView *view = activeBufferView(); + s.setValue(QString("ActiveBufferView-%1").arg(accountId), view ? view->config()->bufferViewId() : -1); + } } -void MainWin::saveLayout() { - QtUiSettings s; - int accountId = _bufferViews.count()? Client::currentCoreAccount().accountId().toInt() : 0; // only save if we still have a layout! - if(accountId > 0) { - s.setValue(QString("MainWinState-%1").arg(accountId) , saveState(accountId)); - BufferView *view = activeBufferView(); - s.setValue(QString("ActiveBufferView-%1").arg(accountId), view ? view->config()->bufferViewId() : -1); - } -} - -void MainWin::disconnectedFromCore() { - // save core specific layout and remove bufferviews; - saveLayout(); - _layoutLoaded = false; - - QVariant actionData; - BufferViewDock *dock; - foreach(QAction *action, _bufferViewsMenu->actions()) { - actionData = action->data(); - if(!actionData.isValid()) - continue; - - dock = qobject_cast(action->parent()); - if(dock && actionData.toInt() != -1) { - removeAction(action); - _bufferViews.removeAll(dock); - dock->deleteLater(); + +void MainWin::disconnectedFromCore() +{ + // save core specific layout and remove bufferviews; + saveLayout(); + _layoutLoaded = false; + + QVariant actionData; + BufferViewDock *dock; + foreach(QAction *action, _bufferViewsMenu->actions()) { + actionData = action->data(); + if (!actionData.isValid()) + continue; + + dock = qobject_cast(action->parent()); + if (dock && actionData.toInt() != -1) { + removeAction(action); + _bufferViews.removeAll(dock); + dock->deleteLater(); + } } - } - // store last active buffer - QtUiSettings s; - BufferId lastBufId = _bufferWidget->currentBuffer(); - if(lastBufId.isValid()) { - s.setValue("LastUsedBufferId", lastBufId.toInt()); - // clear the current selection - Client::bufferModel()->standardSelectionModel()->clearSelection(); - } - restoreState(s.value("MainWinState").toByteArray()); - setDisconnectedState(); + // store last active buffer + QtUiSettings s; + BufferId lastBufId = _bufferWidget->currentBuffer(); + if (lastBufId.isValid()) { + s.setValue("LastUsedBufferId", lastBufId.toInt()); + // clear the current selection + Client::bufferModel()->standardSelectionModel()->clearSelection(); + } + restoreState(s.value("MainWinState").toByteArray()); + setDisconnectedState(); } -void MainWin::setDisconnectedState() { - ActionCollection *coll = QtUi::actionCollection("General"); - //ui.menuCore->setEnabled(false); - coll->action("ConnectCore")->setEnabled(true); - coll->action("DisconnectCore")->setEnabled(false); - coll->action("CoreInfo")->setEnabled(false); - //_viewMenu->setEnabled(false); - statusBar()->showMessage(tr("Not connected to core.")); - if(_msgProcessorStatusWidget) - _msgProcessorStatusWidget->setProgress(0, 0); - updateIcon(); - systemTray()->setState(SystemTray::Passive); + +void MainWin::setDisconnectedState() +{ + ActionCollection *coll = QtUi::actionCollection("General"); + //ui.menuCore->setEnabled(false); + coll->action("ConnectCore")->setEnabled(true); + coll->action("DisconnectCore")->setEnabled(false); + coll->action("CoreInfo")->setEnabled(false); + //_viewMenu->setEnabled(false); + statusBar()->showMessage(tr("Not connected to core.")); + if (_msgProcessorStatusWidget) + _msgProcessorStatusWidget->setProgress(0, 0); + updateIcon(); + systemTray()->setState(SystemTray::Passive); } -void MainWin::userAuthenticationRequired(CoreAccount *account, bool *valid, const QString &errorMessage) { - Q_UNUSED(errorMessage) - CoreConnectAuthDlg dlg(account, this); - *valid = (dlg.exec() == QDialog::Accepted); + +void MainWin::userAuthenticationRequired(CoreAccount *account, bool *valid, const QString &errorMessage) +{ + Q_UNUSED(errorMessage) + CoreConnectAuthDlg dlg(account, this); + *valid = (dlg.exec() == QDialog::Accepted); } -void MainWin::handleNoSslInClient(bool *accepted) { - QMessageBox box(QMessageBox::Warning, tr("Unencrypted Connection"), tr("Your client does not support SSL encryption"), - QMessageBox::Ignore|QMessageBox::Cancel, this); - box.setInformativeText(tr("Sensitive data, like passwords, will be transmitted unencrypted to your Quassel core.")); - box.setDefaultButton(QMessageBox::Ignore); - *accepted = box.exec() == QMessageBox::Ignore; + +void MainWin::handleNoSslInClient(bool *accepted) +{ + QMessageBox box(QMessageBox::Warning, tr("Unencrypted Connection"), tr("Your client does not support SSL encryption"), + QMessageBox::Ignore|QMessageBox::Cancel, this); + box.setInformativeText(tr("Sensitive data, like passwords, will be transmitted unencrypted to your Quassel core.")); + box.setDefaultButton(QMessageBox::Ignore); + *accepted = box.exec() == QMessageBox::Ignore; } -void MainWin::handleNoSslInCore(bool *accepted) { - QMessageBox box(QMessageBox::Warning, tr("Unencrypted Connection"), tr("Your core does not support SSL encryption"), - QMessageBox::Ignore|QMessageBox::Cancel, this); - box.setInformativeText(tr("Sensitive data, like passwords, will be transmitted unencrypted to your Quassel core.")); - box.setDefaultButton(QMessageBox::Ignore); - *accepted = box.exec() == QMessageBox::Ignore; +void MainWin::handleNoSslInCore(bool *accepted) +{ + QMessageBox box(QMessageBox::Warning, tr("Unencrypted Connection"), tr("Your core does not support SSL encryption"), + QMessageBox::Ignore|QMessageBox::Cancel, this); + box.setInformativeText(tr("Sensitive data, like passwords, will be transmitted unencrypted to your Quassel core.")); + box.setDefaultButton(QMessageBox::Ignore); + *accepted = box.exec() == QMessageBox::Ignore; } + #ifdef HAVE_SSL -void MainWin::handleSslErrors(const QSslSocket *socket, bool *accepted, bool *permanently) { - QString errorString = "
    "; - foreach(const QSslError error, socket->sslErrors()) +void MainWin::handleSslErrors(const QSslSocket *socket, bool *accepted, bool *permanently) +{ + QString errorString = "
      "; + foreach(const QSslError error, socket->sslErrors()) errorString += QString("
    • %1
    • ").arg(error.errorString()); - errorString += "
    "; - - QMessageBox box(QMessageBox::Warning, - tr("Untrusted Security Certificate"), - tr("The SSL certificate provided by the core at %1 is untrusted for the following reasons:").arg(socket->peerName()), - QMessageBox::Cancel, this); - box.setInformativeText(errorString); - box.addButton(tr("Continue"), QMessageBox::AcceptRole); - box.setDefaultButton(box.addButton(tr("Show Certificate"), QMessageBox::HelpRole)); - - QMessageBox::ButtonRole role; - do { - box.exec(); - role = box.buttonRole(box.clickedButton()); - if(role == QMessageBox::HelpRole) { - SslInfoDlg dlg(socket, this); - dlg.exec(); + errorString += "
"; + + QMessageBox box(QMessageBox::Warning, + tr("Untrusted Security Certificate"), + tr("The SSL certificate provided by the core at %1 is untrusted for the following reasons:").arg(socket->peerName()), + QMessageBox::Cancel, this); + box.setInformativeText(errorString); + box.addButton(tr("Continue"), QMessageBox::AcceptRole); + box.setDefaultButton(box.addButton(tr("Show Certificate"), QMessageBox::HelpRole)); + + QMessageBox::ButtonRole role; + do { + box.exec(); + role = box.buttonRole(box.clickedButton()); + if (role == QMessageBox::HelpRole) { + SslInfoDlg dlg(socket, this); + dlg.exec(); + } + } + while (role == QMessageBox::HelpRole); + + *accepted = role == QMessageBox::AcceptRole; + if (*accepted) { + QMessageBox box2(QMessageBox::Warning, + tr("Untrusted Security Certificate"), + tr("Would you like to accept this certificate forever without being prompted?"), + 0, this); + box2.setDefaultButton(box2.addButton(tr("Current Session Only"), QMessageBox::NoRole)); + box2.addButton(tr("Forever"), QMessageBox::YesRole); + box2.exec(); + *permanently = box2.buttonRole(box2.clickedButton()) == QMessageBox::YesRole; } - } while(role == QMessageBox::HelpRole); - - *accepted = role == QMessageBox::AcceptRole; - if(*accepted) { - QMessageBox box2(QMessageBox::Warning, - tr("Untrusted Security Certificate"), - tr("Would you like to accept this certificate forever without being prompted?"), - 0, this); - box2.setDefaultButton(box2.addButton(tr("Current Session Only"), QMessageBox::NoRole)); - box2.addButton(tr("Forever"), QMessageBox::YesRole); - box2.exec(); - *permanently = box2.buttonRole(box2.clickedButton()) == QMessageBox::YesRole; - } } + #endif /* HAVE_SSL */ -void MainWin::handleCoreConnectionError(const QString &error) { - QMessageBox::critical(this, tr("Core Connection Error"), error, QMessageBox::Ok); +void MainWin::handleCoreConnectionError(const QString &error) +{ + QMessageBox::critical(this, tr("Core Connection Error"), error, QMessageBox::Ok); } -void MainWin::showCoreConnectionDlg() { - CoreConnectDlg dlg(this); - if(dlg.exec() == QDialog::Accepted) { - AccountId accId = dlg.selectedAccount(); - if(accId.isValid()) - Client::coreConnection()->connectToCore(accId); - } + +void MainWin::showCoreConnectionDlg() +{ + CoreConnectDlg dlg(this); + if (dlg.exec() == QDialog::Accepted) { + AccountId accId = dlg.selectedAccount(); + if (accId.isValid()) + Client::coreConnection()->connectToCore(accId); + } } -void MainWin::showCoreConfigWizard(const QVariantList &backends) { - CoreConfigWizard *wizard = new CoreConfigWizard(Client::coreConnection(), backends, this); - wizard->show(); +void MainWin::showCoreConfigWizard(const QVariantList &backends) +{ + CoreConfigWizard *wizard = new CoreConfigWizard(Client::coreConnection(), backends, this); + + wizard->show(); } -void MainWin::showChannelList(NetworkId netId) { - ChannelListDlg *channelListDlg = new ChannelListDlg(); - if(!netId.isValid()) { - QAction *action = qobject_cast(sender()); - if(action) - netId = action->data().value(); - } +void MainWin::showChannelList(NetworkId netId) +{ + ChannelListDlg *channelListDlg = new ChannelListDlg(); - channelListDlg->setAttribute(Qt::WA_DeleteOnClose); - channelListDlg->setNetwork(netId); - channelListDlg->show(); -} + if (!netId.isValid()) { + QAction *action = qobject_cast(sender()); + if (action) + netId = action->data().value(); + } -void MainWin::showIgnoreList(QString newRule) { - SettingsPageDlg dlg(new IgnoreListSettingsPage(this), this); - // prepare config dialog for new rule - if(!newRule.isEmpty()) - qobject_cast(dlg.currentPage())->editIgnoreRule(newRule); - dlg.exec(); + channelListDlg->setAttribute(Qt::WA_DeleteOnClose); + channelListDlg->setNetwork(netId); + channelListDlg->show(); } -void MainWin::showCoreInfoDlg() { - CoreInfoDlg(this).exec(); + +void MainWin::showIgnoreList(QString newRule) +{ + SettingsPageDlg dlg(new IgnoreListSettingsPage(this), this); + // prepare config dialog for new rule + if (!newRule.isEmpty()) + qobject_cast(dlg.currentPage())->editIgnoreRule(newRule); + dlg.exec(); } -void MainWin::showAwayLog() { - if(_awayLog) - return; - AwayLogFilter *filter = new AwayLogFilter(Client::messageModel()); - _awayLog = new AwayLogView(filter, 0); - filter->setParent(_awayLog); - connect(_awayLog, SIGNAL(destroyed()), this, SLOT(awayLogDestroyed())); - _awayLog->setAttribute(Qt::WA_DeleteOnClose); - _awayLog->show(); + +void MainWin::showCoreInfoDlg() +{ + CoreInfoDlg(this).exec(); } -void MainWin::awayLogDestroyed() { - _awayLog = 0; + +void MainWin::showAwayLog() +{ + if (_awayLog) + return; + AwayLogFilter *filter = new AwayLogFilter(Client::messageModel()); + _awayLog = new AwayLogView(filter, 0); + filter->setParent(_awayLog); + connect(_awayLog, SIGNAL(destroyed()), this, SLOT(awayLogDestroyed())); + _awayLog->setAttribute(Qt::WA_DeleteOnClose); + _awayLog->show(); } -void MainWin::showSettingsDlg() { - SettingsDlg *dlg = new SettingsDlg(); - //Category: Interface - dlg->registerSettingsPage(new AppearanceSettingsPage(dlg)); - dlg->registerSettingsPage(new ChatViewSettingsPage(dlg)); - dlg->registerSettingsPage(new ChatMonitorSettingsPage(dlg)); - dlg->registerSettingsPage(new ItemViewSettingsPage(dlg)); - dlg->registerSettingsPage(new BufferViewSettingsPage(dlg)); - dlg->registerSettingsPage(new InputWidgetSettingsPage(dlg)); - dlg->registerSettingsPage(new TopicWidgetSettingsPage(dlg)); - dlg->registerSettingsPage(new HighlightSettingsPage(dlg)); - dlg->registerSettingsPage(new NotificationsSettingsPage(dlg)); - dlg->registerSettingsPage(new BacklogSettingsPage(dlg)); +void MainWin::awayLogDestroyed() +{ + _awayLog = 0; +} - //Category: IRC - dlg->registerSettingsPage(new ConnectionSettingsPage(dlg)); - dlg->registerSettingsPage(new IdentitiesSettingsPage(dlg)); - dlg->registerSettingsPage(new NetworksSettingsPage(dlg)); - dlg->registerSettingsPage(new AliasesSettingsPage(dlg)); - dlg->registerSettingsPage(new IgnoreListSettingsPage(dlg)); - // Category: Remote Cores - if(Quassel::runMode() != Quassel::Monolithic) { - dlg->registerSettingsPage(new CoreAccountSettingsPage(dlg)); - dlg->registerSettingsPage(new CoreConnectionSettingsPage(dlg)); - } +void MainWin::showSettingsDlg() +{ + SettingsDlg *dlg = new SettingsDlg(); + + //Category: Interface + dlg->registerSettingsPage(new AppearanceSettingsPage(dlg)); + dlg->registerSettingsPage(new ChatViewSettingsPage(dlg)); + dlg->registerSettingsPage(new ChatMonitorSettingsPage(dlg)); + dlg->registerSettingsPage(new ItemViewSettingsPage(dlg)); + dlg->registerSettingsPage(new BufferViewSettingsPage(dlg)); + dlg->registerSettingsPage(new InputWidgetSettingsPage(dlg)); + dlg->registerSettingsPage(new TopicWidgetSettingsPage(dlg)); + dlg->registerSettingsPage(new HighlightSettingsPage(dlg)); + dlg->registerSettingsPage(new NotificationsSettingsPage(dlg)); + dlg->registerSettingsPage(new BacklogSettingsPage(dlg)); + + //Category: IRC + dlg->registerSettingsPage(new ConnectionSettingsPage(dlg)); + dlg->registerSettingsPage(new IdentitiesSettingsPage(dlg)); + dlg->registerSettingsPage(new NetworksSettingsPage(dlg)); + dlg->registerSettingsPage(new AliasesSettingsPage(dlg)); + dlg->registerSettingsPage(new IgnoreListSettingsPage(dlg)); + + // Category: Remote Cores + if (Quassel::runMode() != Quassel::Monolithic) { + dlg->registerSettingsPage(new CoreAccountSettingsPage(dlg)); + dlg->registerSettingsPage(new CoreConnectionSettingsPage(dlg)); + } - dlg->show(); + dlg->show(); } -void MainWin::showAboutDlg() { - AboutDlg(this).exec(); + +void MainWin::showAboutDlg() +{ + AboutDlg(this).exec(); } -void MainWin::showShortcutsDlg() { + +void MainWin::showShortcutsDlg() +{ #ifdef HAVE_KDE - KShortcutsDialog dlg(KShortcutsEditor::AllActions, KShortcutsEditor::LetterShortcutsDisallowed, this); - foreach(KActionCollection *coll, QtUi::actionCollections()) + KShortcutsDialog dlg(KShortcutsEditor::AllActions, KShortcutsEditor::LetterShortcutsDisallowed, this); + foreach(KActionCollection *coll, QtUi::actionCollections()) dlg.addCollection(coll, coll->property("Category").toString()); - dlg.exec(); + dlg.exec(); #else - SettingsPageDlg dlg(new ShortcutsSettingsPage(QtUi::actionCollections(), this), this); - dlg.exec(); + SettingsPageDlg dlg(new ShortcutsSettingsPage(QtUi::actionCollections(), this), this); + dlg.exec(); #endif } -void MainWin::toggleFullscreen() { - if(isFullScreen()) - showNormal(); - else - showFullScreen(); + +void MainWin::toggleFullscreen() +{ + if (isFullScreen()) + showNormal(); + else + showFullScreen(); } + /********************************************************************************************************/ -bool MainWin::event(QEvent *event) { - if(event->type() == QEvent::WindowActivate) { - BufferId buffer = Client::bufferModel()->currentBuffer(); - if(buffer.isValid()) - Client::instance()->markBufferAsRead(buffer); - } - return QMainWindow::event(event); +bool MainWin::event(QEvent *event) +{ + if (event->type() == QEvent::WindowActivate) { + BufferId buffer = Client::bufferModel()->currentBuffer(); + if (buffer.isValid()) + Client::instance()->markBufferAsRead(buffer); + } + return QMainWindow::event(event); } -void MainWin::moveEvent(QMoveEvent *event) { - if(!(windowState() & Qt::WindowMaximized)) - _normalPos = event->pos(); - QMainWindow::moveEvent(event); +void MainWin::moveEvent(QMoveEvent *event) +{ + if (!(windowState() & Qt::WindowMaximized)) + _normalPos = event->pos(); + + QMainWindow::moveEvent(event); } -void MainWin::resizeEvent(QResizeEvent *event) { - if(!(windowState() & Qt::WindowMaximized)) - _normalSize = event->size(); - QMainWindow::resizeEvent(event); -} +void MainWin::resizeEvent(QResizeEvent *event) +{ + if (!(windowState() & Qt::WindowMaximized)) + _normalSize = event->size(); -void MainWin::closeEvent(QCloseEvent *event) { - QtUiSettings s; - QtUiApplication* app = qobject_cast qApp; - Q_ASSERT(app); - if(!app->isAboutToQuit() && QtUi::haveSystemTray() && s.value("MinimizeOnClose").toBool()) { - QtUi::hideMainWidget(); - event->ignore(); - } else { - event->accept(); - quit(); - } + QMainWindow::resizeEvent(event); } -void MainWin::messagesInserted(const QModelIndex &parent, int start, int end) { - Q_UNUSED(parent); - - bool hasFocus = QApplication::activeWindow() != 0; - for(int i = start; i <= end; i++) { - QModelIndex idx = Client::messageModel()->index(i, ChatLineModel::ContentsColumn); - if(!idx.isValid()) { - qDebug() << "MainWin::messagesInserted(): Invalid model index!"; - continue; +void MainWin::closeEvent(QCloseEvent *event) +{ + QtUiSettings s; + QtUiApplication *app = qobject_cast qApp; + Q_ASSERT(app); + if (!app->isAboutToQuit() && QtUi::haveSystemTray() && s.value("MinimizeOnClose").toBool()) { + QtUi::hideMainWidget(); + event->ignore(); } - Message::Flags flags = (Message::Flags)idx.data(ChatLineModel::FlagsRole).toInt(); - if(flags.testFlag(Message::Backlog) || flags.testFlag(Message::Self)) - continue; - - BufferId bufId = idx.data(ChatLineModel::BufferIdRole).value(); - BufferInfo::Type bufType = Client::networkModel()->bufferType(bufId); - - // check if bufferId belongs to the shown chatlists - if(!(Client::bufferViewOverlay()->bufferIds().contains(bufId) || - Client::bufferViewOverlay()->tempRemovedBufferIds().contains(bufId))) - continue; - - // check if it's the buffer currently displayed - if(hasFocus && bufId == Client::bufferModel()->currentBuffer()) - continue; - - // only show notifications for higlights or queries - if(bufType != BufferInfo::QueryBuffer && !(flags & Message::Highlight)) - continue; - - // and of course: don't notify for ignored messages - if(Client::ignoreListManager() && Client::ignoreListManager()->match(idx.data(MessageModel::MessageRole).value(), Client::networkModel()->networkName(bufId))) - continue; - - // seems like we have a legit notification candidate! - QModelIndex senderIdx = Client::messageModel()->index(i, ChatLineModel::SenderColumn); - QString sender = senderIdx.data(ChatLineModel::EditRole).toString(); - QString contents = idx.data(ChatLineModel::DisplayRole).toString(); - AbstractNotificationBackend::NotificationType type; - - if(bufType == BufferInfo::QueryBuffer && !hasFocus) - type = AbstractNotificationBackend::PrivMsg; - else if(bufType == BufferInfo::QueryBuffer && hasFocus) - type = AbstractNotificationBackend::PrivMsgFocused; - else if(flags & Message::Highlight && !hasFocus) - type = AbstractNotificationBackend::Highlight; - else - type = AbstractNotificationBackend::HighlightFocused; + else { + event->accept(); + quit(); + } +} + - QtUi::instance()->invokeNotification(bufId, type, sender, contents); - } +void MainWin::messagesInserted(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent); + + bool hasFocus = QApplication::activeWindow() != 0; + + for (int i = start; i <= end; i++) { + QModelIndex idx = Client::messageModel()->index(i, ChatLineModel::ContentsColumn); + if (!idx.isValid()) { + qDebug() << "MainWin::messagesInserted(): Invalid model index!"; + continue; + } + Message::Flags flags = (Message::Flags)idx.data(ChatLineModel::FlagsRole).toInt(); + if (flags.testFlag(Message::Backlog) || flags.testFlag(Message::Self)) + continue; + + BufferId bufId = idx.data(ChatLineModel::BufferIdRole).value(); + BufferInfo::Type bufType = Client::networkModel()->bufferType(bufId); + + // check if bufferId belongs to the shown chatlists + if (!(Client::bufferViewOverlay()->bufferIds().contains(bufId) || + Client::bufferViewOverlay()->tempRemovedBufferIds().contains(bufId))) + continue; + + // check if it's the buffer currently displayed + if (hasFocus && bufId == Client::bufferModel()->currentBuffer()) + continue; + + // only show notifications for higlights or queries + if (bufType != BufferInfo::QueryBuffer && !(flags & Message::Highlight)) + continue; + + // and of course: don't notify for ignored messages + if (Client::ignoreListManager() && Client::ignoreListManager()->match(idx.data(MessageModel::MessageRole).value(), Client::networkModel()->networkName(bufId))) + continue; + + // seems like we have a legit notification candidate! + QModelIndex senderIdx = Client::messageModel()->index(i, ChatLineModel::SenderColumn); + QString sender = senderIdx.data(ChatLineModel::EditRole).toString(); + QString contents = idx.data(ChatLineModel::DisplayRole).toString(); + AbstractNotificationBackend::NotificationType type; + + if (bufType == BufferInfo::QueryBuffer && !hasFocus) + type = AbstractNotificationBackend::PrivMsg; + else if (bufType == BufferInfo::QueryBuffer && hasFocus) + type = AbstractNotificationBackend::PrivMsgFocused; + else if (flags & Message::Highlight && !hasFocus) + type = AbstractNotificationBackend::Highlight; + else + type = AbstractNotificationBackend::HighlightFocused; + + QtUi::instance()->invokeNotification(bufId, type, sender, contents); + } } -void MainWin::currentBufferChanged(BufferId buffer) { - if(buffer.isValid()) - Client::instance()->markBufferAsRead(buffer); + +void MainWin::currentBufferChanged(BufferId buffer) +{ + if (buffer.isValid()) + Client::instance()->markBufferAsRead(buffer); } -void MainWin::clientNetworkCreated(NetworkId id) { - const Network *net = Client::network(id); - QAction *act = new QAction(net->networkName(), this); - act->setObjectName(QString("NetworkAction-%1").arg(id.toInt())); - act->setData(QVariant::fromValue(id)); - connect(net, SIGNAL(updatedRemotely()), this, SLOT(clientNetworkUpdated())); - connect(act, SIGNAL(triggered()), this, SLOT(connectOrDisconnectFromNet())); - QAction *beforeAction = 0; - foreach(QAction *action, _networksMenu->actions()) { - if(!action->data().isValid()) // ignore stock actions - continue; - if(net->networkName().localeAwareCompare(action->text()) < 0) { - beforeAction = action; - break; +void MainWin::clientNetworkCreated(NetworkId id) +{ + const Network *net = Client::network(id); + QAction *act = new QAction(net->networkName(), this); + act->setObjectName(QString("NetworkAction-%1").arg(id.toInt())); + act->setData(QVariant::fromValue(id)); + connect(net, SIGNAL(updatedRemotely()), this, SLOT(clientNetworkUpdated())); + connect(act, SIGNAL(triggered()), this, SLOT(connectOrDisconnectFromNet())); + + QAction *beforeAction = 0; + foreach(QAction *action, _networksMenu->actions()) { + if (!action->data().isValid()) // ignore stock actions + continue; + if (net->networkName().localeAwareCompare(action->text()) < 0) { + beforeAction = action; + break; + } } - } - _networksMenu->insertAction(beforeAction, act); -} - -void MainWin::clientNetworkUpdated() { - const Network *net = qobject_cast(sender()); - if(!net) - return; - - QAction *action = findChild(QString("NetworkAction-%1").arg(net->networkId().toInt())); - if(!action) - return; - - action->setText(net->networkName()); - - switch(net->connectionState()) { - case Network::Initialized: - action->setIcon(SmallIcon("network-connect")); - // if we have no currently selected buffer, jump to the first connecting statusbuffer - if(!bufferWidget()->currentBuffer().isValid()) { - QModelIndex idx = Client::networkModel()->networkIndex(net->networkId()); - if(idx.isValid()) { - BufferId statusBufferId = idx.data(NetworkModel::BufferIdRole).value(); - Client::bufferModel()->switchToBuffer(statusBufferId); - } + _networksMenu->insertAction(beforeAction, act); +} + + +void MainWin::clientNetworkUpdated() +{ + const Network *net = qobject_cast(sender()); + if (!net) + return; + + QAction *action = findChild(QString("NetworkAction-%1").arg(net->networkId().toInt())); + if (!action) + return; + + action->setText(net->networkName()); + + switch (net->connectionState()) { + case Network::Initialized: + action->setIcon(SmallIcon("network-connect")); + // if we have no currently selected buffer, jump to the first connecting statusbuffer + if (!bufferWidget()->currentBuffer().isValid()) { + QModelIndex idx = Client::networkModel()->networkIndex(net->networkId()); + if (idx.isValid()) { + BufferId statusBufferId = idx.data(NetworkModel::BufferIdRole).value(); + Client::bufferModel()->switchToBuffer(statusBufferId); + } + } + break; + case Network::Disconnected: + action->setIcon(SmallIcon("network-disconnect")); + break; + default: + action->setIcon(SmallIcon("network-wired")); } - break; - case Network::Disconnected: - action->setIcon(SmallIcon("network-disconnect")); - break; - default: - action->setIcon(SmallIcon("network-wired")); - } } -void MainWin::clientNetworkRemoved(NetworkId id) { - QAction *action = findChild(QString("NetworkAction-%1").arg(id.toInt())); - if(!action) - return; - action->deleteLater(); +void MainWin::clientNetworkRemoved(NetworkId id) +{ + QAction *action = findChild(QString("NetworkAction-%1").arg(id.toInt())); + if (!action) + return; + + action->deleteLater(); } -void MainWin::connectOrDisconnectFromNet() { - QAction *act = qobject_cast(sender()); - if(!act) return; - const Network *net = Client::network(act->data().value()); - if(!net) return; - if(net->connectionState() == Network::Disconnected) net->requestConnect(); - else net->requestDisconnect(); + +void MainWin::connectOrDisconnectFromNet() +{ + QAction *act = qobject_cast(sender()); + if (!act) return; + const Network *net = Client::network(act->data().value()); + if (!net) return; + if (net->connectionState() == Network::Disconnected) net->requestConnect(); + else net->requestDisconnect(); } -void MainWin::on_jumpHotBuffer_triggered() { - if(!_bufferHotList->rowCount()) - return; - QModelIndex topIndex = _bufferHotList->index(0, 0); - BufferId bufferId = _bufferHotList->data(topIndex, NetworkModel::BufferIdRole).value(); - Client::bufferModel()->switchToBuffer(bufferId); +void MainWin::on_jumpHotBuffer_triggered() +{ + if (!_bufferHotList->rowCount()) + return; + + QModelIndex topIndex = _bufferHotList->index(0, 0); + BufferId bufferId = _bufferHotList->data(topIndex, NetworkModel::BufferIdRole).value(); + Client::bufferModel()->switchToBuffer(bufferId); } -void MainWin::onJumpKey() { - QAction *action = qobject_cast(sender()); - if(!action || !Client::bufferModel()) - return; - int idx = action->property("Index").toInt(); - if(_jumpKeyMap.isEmpty()) - _jumpKeyMap = CoreAccountSettings().jumpKeyMap(); +void MainWin::onJumpKey() +{ + QAction *action = qobject_cast(sender()); + if (!action || !Client::bufferModel()) + return; + int idx = action->property("Index").toInt(); - if(!_jumpKeyMap.contains(idx)) - return; + if (_jumpKeyMap.isEmpty()) + _jumpKeyMap = CoreAccountSettings().jumpKeyMap(); - BufferId buffer = _jumpKeyMap.value(idx); - if(buffer.isValid()) - Client::bufferModel()->switchToBuffer(buffer); + if (!_jumpKeyMap.contains(idx)) + return; + BufferId buffer = _jumpKeyMap.value(idx); + if (buffer.isValid()) + Client::bufferModel()->switchToBuffer(buffer); } -void MainWin::bindJumpKey() { - QAction *action = qobject_cast(sender()); - if(!action || !Client::bufferModel()) - return; - int idx = action->property("Index").toInt(); - _jumpKeyMap[idx] = Client::bufferModel()->currentBuffer(); - CoreAccountSettings().setJumpKeyMap(_jumpKeyMap); +void MainWin::bindJumpKey() +{ + QAction *action = qobject_cast(sender()); + if (!action || !Client::bufferModel()) + return; + int idx = action->property("Index").toInt(); + + _jumpKeyMap[idx] = Client::bufferModel()->currentBuffer(); + CoreAccountSettings().setJumpKeyMap(_jumpKeyMap); } -void MainWin::on_actionDebugNetworkModel_triggered() { - QTreeView *view = new QTreeView; - view->setAttribute(Qt::WA_DeleteOnClose); - view->setWindowTitle("Debug NetworkModel View"); - view->setModel(Client::networkModel()); - view->setColumnWidth(0, 250); - view->setColumnWidth(1, 250); - view->setColumnWidth(2, 80); - view->resize(610, 300); - view->show(); + +void MainWin::on_actionDebugNetworkModel_triggered() +{ + QTreeView *view = new QTreeView; + view->setAttribute(Qt::WA_DeleteOnClose); + view->setWindowTitle("Debug NetworkModel View"); + view->setModel(Client::networkModel()); + view->setColumnWidth(0, 250); + view->setColumnWidth(1, 250); + view->setColumnWidth(2, 80); + view->resize(610, 300); + view->show(); } -void MainWin::on_actionDebugHotList_triggered() { - QTreeView *view = new QTreeView; - view->setAttribute(Qt::WA_DeleteOnClose); - view->setModel(_bufferHotList); - view->show(); + +void MainWin::on_actionDebugHotList_triggered() +{ + QTreeView *view = new QTreeView; + view->setAttribute(Qt::WA_DeleteOnClose); + view->setModel(_bufferHotList); + view->show(); } -void MainWin::on_actionDebugBufferViewOverlay_triggered() { - DebugBufferViewOverlay *overlay = new DebugBufferViewOverlay(0); - overlay->setAttribute(Qt::WA_DeleteOnClose); - overlay->show(); + +void MainWin::on_actionDebugBufferViewOverlay_triggered() +{ + DebugBufferViewOverlay *overlay = new DebugBufferViewOverlay(0); + overlay->setAttribute(Qt::WA_DeleteOnClose); + overlay->show(); } -void MainWin::on_actionDebugMessageModel_triggered() { - QTableView *view = new QTableView(0); - DebugMessageModelFilter *filter = new DebugMessageModelFilter(view); - filter->setSourceModel(Client::messageModel()); - view->setModel(filter); - view->setAttribute(Qt::WA_DeleteOnClose, true); - view->verticalHeader()->hide(); - view->horizontalHeader()->setStretchLastSection(true); - view->show(); + +void MainWin::on_actionDebugMessageModel_triggered() +{ + QTableView *view = new QTableView(0); + DebugMessageModelFilter *filter = new DebugMessageModelFilter(view); + filter->setSourceModel(Client::messageModel()); + view->setModel(filter); + view->setAttribute(Qt::WA_DeleteOnClose, true); + view->verticalHeader()->hide(); + view->horizontalHeader()->setStretchLastSection(true); + view->show(); } -void MainWin::on_actionDebugLog_triggered() { - DebugLogWidget *logWidget = new DebugLogWidget(0); - logWidget->show(); + +void MainWin::on_actionDebugLog_triggered() +{ + DebugLogWidget *logWidget = new DebugLogWidget(0); + logWidget->show(); } -void MainWin::showStatusBarMessage(const QString &message) { - statusBar()->showMessage(message, 10000); + +void MainWin::showStatusBarMessage(const QString &message) +{ + statusBar()->showMessage(message, 10000); } diff --git a/src/qtui/mainwin.h b/src/qtui/mainwin.h index 49b49d70..8f404052 100644 --- a/src/qtui/mainwin.h +++ b/src/qtui/mainwin.h @@ -56,13 +56,14 @@ class KHelpMenu; //!\brief The main window of Quassel's QtUi. class MainWin #ifdef HAVE_KDE -: public KMainWindow { + : public KMainWindow +{ #else : public QMainWindow { #endif - Q_OBJECT + Q_OBJECT - public: +public: MainWin(QWidget *parent = 0); virtual ~MainWin(); @@ -83,7 +84,7 @@ class MainWin void saveStateToSettings(UiSettings &); void restoreStateFromSettings(UiSettings &); - public slots: +public slots: void showStatusBarMessage(const QString &message); void hideCurrentBuffer(); void nextBufferView(); //!< Activate the next bufferview @@ -94,18 +95,18 @@ class MainWin //! Quit application void quit(); - protected: +protected: void closeEvent(QCloseEvent *event); void moveEvent(QMoveEvent *event); void resizeEvent(QResizeEvent *event); - protected slots: +protected slots: void connectedToCore(); void setConnectedState(); void disconnectedFromCore(); void setDisconnectedState(); - private slots: +private slots: void addBufferView(int bufferViewConfigId); void awayLogDestroyed(); void removeBufferView(int bufferViewConfigId); @@ -160,11 +161,11 @@ class MainWin void changeActiveBufferView(bool backwards); void changeActiveBufferView(int bufferViewId); - signals: +signals: void connectToCore(const QVariantMap &connInfo); void disconnectFromCore(); - private: +private: #ifdef HAVE_KDE KHelpMenu *_kHelpMenu; #endif @@ -217,4 +218,5 @@ class MainWin friend class QtUi; }; + #endif diff --git a/src/qtui/markerlineitem.cpp b/src/qtui/markerlineitem.cpp index 563ef4ed..2a46bbc0 100644 --- a/src/qtui/markerlineitem.cpp +++ b/src/qtui/markerlineitem.cpp @@ -24,44 +24,51 @@ #include "qtui.h" MarkerLineItem::MarkerLineItem(qreal sceneWidth, QGraphicsItem *parent) - : QGraphicsObject(parent), + : QGraphicsObject(parent), _boundingRect(0, 0, sceneWidth, 1), _chatLine(0) { - setVisible(false); - setZValue(8); - styleChanged(); // init brush and height - connect(QtUi::style(), SIGNAL(changed()), SLOT(styleChanged())); + setVisible(false); + setZValue(8); + styleChanged(); // init brush and height + connect(QtUi::style(), SIGNAL(changed()), SLOT(styleChanged())); } -void MarkerLineItem::setChatLine(ChatLine *line) { - _chatLine = line; - if(!line) - setVisible(false); + +void MarkerLineItem::setChatLine(ChatLine *line) +{ + _chatLine = line; + if (!line) + setVisible(false); } -void MarkerLineItem::styleChanged() { - _brush = QtUi::style()->brush(UiStyle::MarkerLine); - // if this is a solid color, we assume 1px because wesurely don't surely don't want to fill the entire chatline. - // else, use the height of a single line of text to play around with gradients etc. - qreal height = 1.; - if(_brush.style() != Qt::SolidPattern) - height = QtUi::style()->fontMetrics(QtUiStyle::PlainMsg, 0)->lineSpacing(); +void MarkerLineItem::styleChanged() +{ + _brush = QtUi::style()->brush(UiStyle::MarkerLine); + // if this is a solid color, we assume 1px because wesurely don't surely don't want to fill the entire chatline. + // else, use the height of a single line of text to play around with gradients etc. + qreal height = 1.; + if (_brush.style() != Qt::SolidPattern) + height = QtUi::style()->fontMetrics(QtUiStyle::PlainMsg, 0)->lineSpacing(); - prepareGeometryChange(); - _boundingRect = QRectF(0, 0, scene()? scene()->width() : 100, height); + prepareGeometryChange(); + _boundingRect = QRectF(0, 0, scene() ? scene()->width() : 100, height); } -void MarkerLineItem::sceneRectChanged(const QRectF &rect) { - prepareGeometryChange(); - _boundingRect.setWidth(rect.width()); + +void MarkerLineItem::sceneRectChanged(const QRectF &rect) +{ + prepareGeometryChange(); + _boundingRect.setWidth(rect.width()); } -void MarkerLineItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { - Q_UNUSED(option); - Q_UNUSED(widget); - painter->fillRect(boundingRect(), _brush); +void MarkerLineItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(option); + Q_UNUSED(widget); + + painter->fillRect(boundingRect(), _brush); } diff --git a/src/qtui/markerlineitem.h b/src/qtui/markerlineitem.h index 827fa258..1eaa93dc 100644 --- a/src/qtui/markerlineitem.h +++ b/src/qtui/markerlineitem.h @@ -27,30 +27,32 @@ class ChatLine; -class MarkerLineItem : public QGraphicsObject { - Q_OBJECT +class MarkerLineItem : public QGraphicsObject +{ + Q_OBJECT public: - MarkerLineItem(qreal sceneWidth, QGraphicsItem *parent = 0); - virtual inline int type() const { return ChatScene::MarkerLineType; } + MarkerLineItem(qreal sceneWidth, QGraphicsItem *parent = 0); + virtual inline int type() const { return ChatScene::MarkerLineType; } - inline QRectF boundingRect() const { return _boundingRect; } - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); + inline QRectF boundingRect() const { return _boundingRect; } + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - inline ChatLine *chatLine() const { return _chatLine; } + inline ChatLine *chatLine() const { return _chatLine; } public slots: - //! Set the ChatLine this MarkerLineItem is associated to - void setChatLine(ChatLine *line); - void sceneRectChanged(const QRectF &); + //! Set the ChatLine this MarkerLineItem is associated to + void setChatLine(ChatLine *line); + void sceneRectChanged(const QRectF &); private slots: - void styleChanged(); + void styleChanged(); private: - QRectF _boundingRect; - QBrush _brush; - ChatLine *_chatLine; + QRectF _boundingRect; + QBrush _brush; + ChatLine *_chatLine; }; + #endif diff --git a/src/qtui/monoapplication.cpp b/src/qtui/monoapplication.cpp index 5ed2611d..2592242c 100644 --- a/src/qtui/monoapplication.cpp +++ b/src/qtui/monoapplication.cpp @@ -25,42 +25,48 @@ #include "qtui.h" MonolithicApplication::MonolithicApplication(int &argc, char **argv) - : QtUiApplication(argc, argv), + : QtUiApplication(argc, argv), _internalInitDone(false) { - _internal = new CoreApplicationInternal(); // needed for parser options + _internal = new CoreApplicationInternal(); // needed for parser options #if defined(HAVE_KDE) || defined(Q_OS_MAC) - disableCrashhandler(); + disableCrashhandler(); #endif /* HAVE_KDE || Q_OS_MAC */ - setRunMode(Quassel::Monolithic); + setRunMode(Quassel::Monolithic); } -bool MonolithicApplication::init() { - if(!Quassel::init()) // parse args - return false; - connect(Client::coreConnection(), SIGNAL(startInternalCore()), SLOT(startInternalCore())); +bool MonolithicApplication::init() +{ + if (!Quassel::init()) // parse args + return false; + + connect(Client::coreConnection(), SIGNAL(startInternalCore()), SLOT(startInternalCore())); - if(isOptionSet("port")) { - startInternalCore(); - } + if (isOptionSet("port")) { + startInternalCore(); + } - return QtUiApplication::init(); + return QtUiApplication::init(); } -MonolithicApplication::~MonolithicApplication() { - // Client needs to be destroyed first - Client::destroy(); - delete _internal; + +MonolithicApplication::~MonolithicApplication() +{ + // Client needs to be destroyed first + Client::destroy(); + delete _internal; } -void MonolithicApplication::startInternalCore() { - if(!_internalInitDone) { - _internal->init(); - _internalInitDone = true; - } - Core *core = Core::instance(); - CoreConnection *connection = Client::coreConnection(); - connect(connection, SIGNAL(connectToInternalCore(SignalProxy *)), core, SLOT(setupInternalClientSession(SignalProxy *))); - connect(core, SIGNAL(sessionState(const QVariant &)), connection, SLOT(internalSessionStateReceived(const QVariant &))); + +void MonolithicApplication::startInternalCore() +{ + if (!_internalInitDone) { + _internal->init(); + _internalInitDone = true; + } + Core *core = Core::instance(); + CoreConnection *connection = Client::coreConnection(); + connect(connection, SIGNAL(connectToInternalCore(SignalProxy *)), core, SLOT(setupInternalClientSession(SignalProxy *))); + connect(core, SIGNAL(sessionState(const QVariant &)), connection, SLOT(internalSessionStateReceived(const QVariant &))); } diff --git a/src/qtui/monoapplication.h b/src/qtui/monoapplication.h index 086bb473..55aae0fc 100644 --- a/src/qtui/monoapplication.h +++ b/src/qtui/monoapplication.h @@ -25,20 +25,22 @@ class CoreApplicationInternal; -class MonolithicApplication : public QtUiApplication { - Q_OBJECT +class MonolithicApplication : public QtUiApplication +{ + Q_OBJECT public: - MonolithicApplication(int &, char **); - ~MonolithicApplication(); + MonolithicApplication(int &, char **); + ~MonolithicApplication(); - bool init(); + bool init(); private slots: - void startInternalCore(); + void startInternalCore(); private: - CoreApplicationInternal *_internal; - bool _internalInitDone; + CoreApplicationInternal *_internal; + bool _internalInitDone; }; + #endif diff --git a/src/qtui/msgprocessorstatuswidget.cpp b/src/qtui/msgprocessorstatuswidget.cpp index f5616bf6..4dc19ac7 100644 --- a/src/qtui/msgprocessorstatuswidget.cpp +++ b/src/qtui/msgprocessorstatuswidget.cpp @@ -21,19 +21,22 @@ #include "msgprocessorstatuswidget.h" MsgProcessorStatusWidget::MsgProcessorStatusWidget(QWidget *parent) - : QWidget(parent) + : QWidget(parent) { - ui.setupUi(this); - hide(); + ui.setupUi(this); + hide(); } -void MsgProcessorStatusWidget::setProgress(int value, int max) { - if(max <= 0 || value == max) { - hide(); - } else { - if(isHidden()) - show(); - ui.progressBar->setMaximum(max); - ui.progressBar->setValue(value); - } + +void MsgProcessorStatusWidget::setProgress(int value, int max) +{ + if (max <= 0 || value == max) { + hide(); + } + else { + if (isHidden()) + show(); + ui.progressBar->setMaximum(max); + ui.progressBar->setValue(value); + } } diff --git a/src/qtui/msgprocessorstatuswidget.h b/src/qtui/msgprocessorstatuswidget.h index b29f671b..818992a5 100644 --- a/src/qtui/msgprocessorstatuswidget.h +++ b/src/qtui/msgprocessorstatuswidget.h @@ -23,17 +23,19 @@ #include "ui_msgprocessorstatuswidget.h" -class MsgProcessorStatusWidget : public QWidget { - Q_OBJECT +class MsgProcessorStatusWidget : public QWidget +{ + Q_OBJECT public: - MsgProcessorStatusWidget(QWidget *parent = 0); + MsgProcessorStatusWidget(QWidget *parent = 0); public slots: - void setProgress(int value, int max); + void setProgress(int value, int max); private: - Ui::MsgProcessorStatusWidget ui; + Ui::MsgProcessorStatusWidget ui; }; + #endif diff --git a/src/qtui/nicklistwidget.cpp b/src/qtui/nicklistwidget.cpp index d2ef8e87..1b4b73c2 100644 --- a/src/qtui/nicklistwidget.cpp +++ b/src/qtui/nicklistwidget.cpp @@ -33,61 +33,71 @@ #include NickListWidget::NickListWidget(QWidget *parent) - : AbstractItemView(parent) + : AbstractItemView(parent) { - ui.setupUi(this); + ui.setupUi(this); } -QDockWidget *NickListWidget::dock() const { - QDockWidget *dock = qobject_cast(parent()); - if(dock) - return dock; - else - return 0; -} -void NickListWidget::hideEvent(QHideEvent *event) { - emit nickSelectionChanged(QModelIndexList()); - AbstractItemView::hideEvent(event); +QDockWidget *NickListWidget::dock() const +{ + QDockWidget *dock = qobject_cast(parent()); + if (dock) + return dock; + else + return 0; } -void NickListWidget::showEvent(QShowEvent *event) { - NickView *view = qobject_cast(ui.stackedWidget->currentWidget()); - if(view) - emit nickSelectionChanged(view->selectedIndexes()); - AbstractItemView::showEvent(event); +void NickListWidget::hideEvent(QHideEvent *event) +{ + emit nickSelectionChanged(QModelIndexList()); + AbstractItemView::hideEvent(event); } -void NickListWidget::showWidget(bool visible) { - if(!selectionModel()) - return; - QModelIndex currentIndex = selectionModel()->currentIndex(); - if(currentIndex.data(NetworkModel::BufferTypeRole) == BufferInfo::ChannelBuffer) { - QDockWidget *dock_ = dock(); - if(!dock_) - return; +void NickListWidget::showEvent(QShowEvent *event) +{ + NickView *view = qobject_cast(ui.stackedWidget->currentWidget()); + if (view) + emit nickSelectionChanged(view->selectedIndexes()); - if(visible) - dock_->show(); - else - dock_->close(); - } + AbstractItemView::showEvent(event); } -void NickListWidget::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { - BufferInfo::Type bufferType = (BufferInfo::Type)current.data(NetworkModel::BufferTypeRole).toInt(); - BufferId newBufferId = current.data(NetworkModel::BufferIdRole).value(); - BufferId oldBufferId = previous.data(NetworkModel::BufferIdRole).value(); - if(bufferType != BufferInfo::ChannelBuffer) { - ui.stackedWidget->setCurrentWidget(ui.emptyPage); - emit nickSelectionChanged(QModelIndexList()); - return; - } +void NickListWidget::showWidget(bool visible) +{ + if (!selectionModel()) + return; + + QModelIndex currentIndex = selectionModel()->currentIndex(); + if (currentIndex.data(NetworkModel::BufferTypeRole) == BufferInfo::ChannelBuffer) { + QDockWidget *dock_ = dock(); + if (!dock_) + return; + + if (visible) + dock_->show(); + else + dock_->close(); + } +} + - // See NickListDock::NickListDock() below +void NickListWidget::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) +{ + BufferInfo::Type bufferType = (BufferInfo::Type)current.data(NetworkModel::BufferTypeRole).toInt(); + BufferId newBufferId = current.data(NetworkModel::BufferIdRole).value(); + BufferId oldBufferId = previous.data(NetworkModel::BufferIdRole).value(); + + if (bufferType != BufferInfo::ChannelBuffer) { + ui.stackedWidget->setCurrentWidget(ui.emptyPage); + emit nickSelectionChanged(QModelIndexList()); + return; + } + + // See NickListDock::NickListDock() below // if(bufferType != BufferInfo::ChannelBuffer) { // ui.stackedWidget->setCurrentWidget(ui.emptyPage); // QDockWidget *dock_ = dock(); @@ -102,89 +112,99 @@ void NickListWidget::currentChanged(const QModelIndex ¤t, const QModelInde // } // } - if(newBufferId == oldBufferId) - return; - - NickView *view; - if(nickViews.contains(newBufferId)) { - view = nickViews.value(newBufferId); - ui.stackedWidget->setCurrentWidget(view); - } else { - view = new NickView(this); - NickViewFilter *filter = new NickViewFilter(newBufferId, Client::networkModel()); - view->setModel(filter); - QModelIndex source_current = Client::bufferModel()->mapToSource(current); - view->setRootIndex(filter->mapFromSource(source_current)); - nickViews[newBufferId] = view; - ui.stackedWidget->addWidget(view); - ui.stackedWidget->setCurrentWidget(view); - connect(view, SIGNAL(selectionUpdated()), SLOT(nickSelectionChanged())); - } - emit nickSelectionChanged(view->selectedIndexes()); + if (newBufferId == oldBufferId) + return; + + NickView *view; + if (nickViews.contains(newBufferId)) { + view = nickViews.value(newBufferId); + ui.stackedWidget->setCurrentWidget(view); + } + else { + view = new NickView(this); + NickViewFilter *filter = new NickViewFilter(newBufferId, Client::networkModel()); + view->setModel(filter); + QModelIndex source_current = Client::bufferModel()->mapToSource(current); + view->setRootIndex(filter->mapFromSource(source_current)); + nickViews[newBufferId] = view; + ui.stackedWidget->addWidget(view); + ui.stackedWidget->setCurrentWidget(view); + connect(view, SIGNAL(selectionUpdated()), SLOT(nickSelectionChanged())); + } + emit nickSelectionChanged(view->selectedIndexes()); } -void NickListWidget::nickSelectionChanged() { - NickView *view = qobject_cast(sender()); - Q_ASSERT(view); - if(view != ui.stackedWidget->currentWidget()) { - qDebug() << "Nick selection of hidden view changed!"; - return; - } - emit nickSelectionChanged(view->selectedIndexes()); + +void NickListWidget::nickSelectionChanged() +{ + NickView *view = qobject_cast(sender()); + Q_ASSERT(view); + if (view != ui.stackedWidget->currentWidget()) { + qDebug() << "Nick selection of hidden view changed!"; + return; + } + emit nickSelectionChanged(view->selectedIndexes()); } -void NickListWidget::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { - Q_ASSERT(model()); - if(!parent.isValid()) { - // ok this means that whole networks are about to be removed - // we can't determine which buffers are affect, so we hope that all nets are removed - // this is the most common case (for example disconnecting from the core or terminating the clint) - NickView *nickView; - QHash::iterator iter = nickViews.begin(); - while(iter != nickViews.end()) { - nickView = *iter; - iter = nickViews.erase(iter); - ui.stackedWidget->removeWidget(nickView); - QAbstractItemModel *model = nickView->model(); - nickView->setModel(0); - if(QSortFilterProxyModel *filter = qobject_cast(model)) - filter->setSourceModel(0); - model->deleteLater(); - nickView->deleteLater(); + +void NickListWidget::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) +{ + Q_ASSERT(model()); + if (!parent.isValid()) { + // ok this means that whole networks are about to be removed + // we can't determine which buffers are affect, so we hope that all nets are removed + // this is the most common case (for example disconnecting from the core or terminating the clint) + NickView *nickView; + QHash::iterator iter = nickViews.begin(); + while (iter != nickViews.end()) { + nickView = *iter; + iter = nickViews.erase(iter); + ui.stackedWidget->removeWidget(nickView); + QAbstractItemModel *model = nickView->model(); + nickView->setModel(0); + if (QSortFilterProxyModel *filter = qobject_cast(model)) + filter->setSourceModel(0); + model->deleteLater(); + nickView->deleteLater(); + } } - } else { - // check if there are explicitly buffers removed - for(int i = start; i <= end; i++) { - QVariant variant = parent.child(i,0).data(NetworkModel::BufferIdRole); - if(!variant.isValid()) - continue; - - BufferId bufferId = qVariantValue(variant); - removeBuffer(bufferId); + else { + // check if there are explicitly buffers removed + for (int i = start; i <= end; i++) { + QVariant variant = parent.child(i, 0).data(NetworkModel::BufferIdRole); + if (!variant.isValid()) + continue; + + BufferId bufferId = qVariantValue(variant); + removeBuffer(bufferId); + } } - } } -void NickListWidget::removeBuffer(BufferId bufferId) { - if(!nickViews.contains(bufferId)) - return; - - NickView *view = nickViews.take(bufferId); - ui.stackedWidget->removeWidget(view); - QAbstractItemModel *model = view->model(); - view->setModel(0); - if(QSortFilterProxyModel *filter = qobject_cast(model)) - filter->setSourceModel(0); - model->deleteLater(); - view->deleteLater(); + +void NickListWidget::removeBuffer(BufferId bufferId) +{ + if (!nickViews.contains(bufferId)) + return; + + NickView *view = nickViews.take(bufferId); + ui.stackedWidget->removeWidget(view); + QAbstractItemModel *model = view->model(); + view->setModel(0); + if (QSortFilterProxyModel *filter = qobject_cast(model)) + filter->setSourceModel(0); + model->deleteLater(); + view->deleteLater(); } -QSize NickListWidget::sizeHint() const { - QWidget *currentWidget = ui.stackedWidget->currentWidget(); - if(!currentWidget || currentWidget == ui.emptyPage) - return QSize(100, height()); - else - return currentWidget->sizeHint(); + +QSize NickListWidget::sizeHint() const +{ + QWidget *currentWidget = ui.stackedWidget->currentWidget(); + if (!currentWidget || currentWidget == ui.emptyPage) + return QSize(100, height()); + else + return currentWidget->sizeHint(); } @@ -192,11 +212,11 @@ QSize NickListWidget::sizeHint() const { // NickList Dock // ============================== NickListDock::NickListDock(const QString &title, QWidget *parent) - : QDockWidget(title, parent) + : QDockWidget(title, parent) { - // THIS STUFF IS NEEDED FOR NICKLIST AUTOHIDE... - // AS THIS BRINGS LOTS OF FUCKUPS WITH IT IT'S DEACTIVATED FOR NOW... - + // THIS STUFF IS NEEDED FOR NICKLIST AUTOHIDE... + // AS THIS BRINGS LOTS OF FUCKUPS WITH IT IT'S DEACTIVATED FOR NOW... + // QAction *toggleView = toggleViewAction(); // disconnect(toggleView, SIGNAL(triggered(bool)), this, 0); // toggleView->setChecked(QtUiSettings().value("ShowNickList", QVariant(true)).toBool()); @@ -208,6 +228,7 @@ NickListDock::NickListDock(const QString &title, QWidget *parent) // } } + // NickListDock::~NickListDock() { // QtUiSettings().setValue("ShowNickList", toggleViewAction()->isChecked()); // } diff --git a/src/qtui/nicklistwidget.h b/src/qtui/nicklistwidget.h index 18f966aa..f28ced67 100644 --- a/src/qtui/nicklistwidget.h +++ b/src/qtui/nicklistwidget.h @@ -34,50 +34,53 @@ class Buffer; class NickView; class QDockWidget; -class NickListWidget : public AbstractItemView { - Q_OBJECT +class NickListWidget : public AbstractItemView +{ + Q_OBJECT public: - NickListWidget(QWidget *parent = 0); + NickListWidget(QWidget *parent = 0); public slots: - void showWidget(bool visible); + void showWidget(bool visible); signals: - void nickSelectionChanged(const QModelIndexList &); + void nickSelectionChanged(const QModelIndexList &); protected: - virtual QSize sizeHint() const; - virtual void hideEvent(QHideEvent *); - virtual void showEvent(QShowEvent *); + virtual QSize sizeHint() const; + virtual void hideEvent(QHideEvent *); + virtual void showEvent(QShowEvent *); protected slots: - virtual void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); - virtual void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); + virtual void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); + virtual void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); private slots: - void removeBuffer(BufferId bufferId); - void nickSelectionChanged(); + void removeBuffer(BufferId bufferId); + void nickSelectionChanged(); private: - Ui::NickListWidget ui; - QHash nickViews; + Ui::NickListWidget ui; + QHash nickViews; - QDockWidget *dock() const; + QDockWidget *dock() const; }; // ============================== // NickList Dock // ============================== -class NickListDock : public QDockWidget { - Q_OBJECT +class NickListDock : public QDockWidget +{ + Q_OBJECT public: - NickListDock(const QString &title, QWidget *parent = 0); - // ~NickListDock(); + NickListDock(const QString &title, QWidget *parent = 0); + // ~NickListDock(); - // virtual bool event(QEvent *event); + // virtual bool event(QEvent *event); }; + #endif diff --git a/src/qtui/phononnotificationbackend.cpp b/src/qtui/phononnotificationbackend.cpp index 1a106d4b..b2116b5a 100644 --- a/src/qtui/phononnotificationbackend.cpp +++ b/src/qtui/phononnotificationbackend.cpp @@ -30,131 +30,162 @@ #include "qtui.h" PhononNotificationBackend::PhononNotificationBackend(QObject *parent) - : AbstractNotificationBackend(parent), - _media(0) + : AbstractNotificationBackend(parent), + _media(0) { - NotificationSettings notificationSettings; - _enabled = notificationSettings.value("Phonon/Enabled", true).toBool(); - createMediaObject(notificationSettings.value("Phonon/AudioFile", QString()).toString()); + NotificationSettings notificationSettings; + _enabled = notificationSettings.value("Phonon/Enabled", true).toBool(); + createMediaObject(notificationSettings.value("Phonon/AudioFile", QString()).toString()); - notificationSettings.notify("Phonon/Enabled", this, SLOT(enabledChanged(const QVariant &))); - notificationSettings.notify("Phonon/AudioFile", this, SLOT(audioFileChanged(const QVariant &))); + notificationSettings.notify("Phonon/Enabled", this, SLOT(enabledChanged(const QVariant &))); + notificationSettings.notify("Phonon/AudioFile", this, SLOT(audioFileChanged(const QVariant &))); } -PhononNotificationBackend::~PhononNotificationBackend() { - if(_media) - delete _media; + +PhononNotificationBackend::~PhononNotificationBackend() +{ + if (_media) + delete _media; } -void PhononNotificationBackend::notify(const Notification ¬ification) { - if(_enabled && _media && (notification.type == Highlight || notification.type == PrivMsg)) { - _media->stop(); - _media->play(); - } + +void PhononNotificationBackend::notify(const Notification ¬ification) +{ + if (_enabled && _media && (notification.type == Highlight || notification.type == PrivMsg)) { + _media->stop(); + _media->play(); + } } -void PhononNotificationBackend::close(uint notificationId) { - Q_UNUSED(notificationId); + +void PhononNotificationBackend::close(uint notificationId) +{ + Q_UNUSED(notificationId); } -void PhononNotificationBackend::enabledChanged(const QVariant &v) { - _enabled = v.toBool(); + +void PhononNotificationBackend::enabledChanged(const QVariant &v) +{ + _enabled = v.toBool(); } -void PhononNotificationBackend::audioFileChanged(const QVariant &v) { - createMediaObject(v.toString()); + +void PhononNotificationBackend::audioFileChanged(const QVariant &v) +{ + createMediaObject(v.toString()); } -SettingsPage *PhononNotificationBackend::createConfigWidget() const { - return new ConfigWidget(); + +SettingsPage *PhononNotificationBackend::createConfigWidget() const +{ + return new ConfigWidget(); } -void PhononNotificationBackend::createMediaObject(const QString &file) { - if(_media) - delete _media; - if(file.isEmpty()) { - _media = 0; - return; - } +void PhononNotificationBackend::createMediaObject(const QString &file) +{ + if (_media) + delete _media; + + if (file.isEmpty()) { + _media = 0; + return; + } - _media = Phonon::createPlayer(Phonon::NotificationCategory, - Phonon::MediaSource(file)); + _media = Phonon::createPlayer(Phonon::NotificationCategory, + Phonon::MediaSource(file)); } + /***************************************************************************/ PhononNotificationBackend::ConfigWidget::ConfigWidget(QWidget *parent) -: SettingsPage("Internal", "PhononNotification", parent), - audioPreview(0) + : SettingsPage("Internal", "PhononNotification", parent), + audioPreview(0) { - ui.setupUi(this); - ui.enabled->setIcon(SmallIcon("media-playback-start")); - ui.play->setIcon(SmallIcon("media-playback-start")); - ui.open->setIcon(SmallIcon("document-open")); + ui.setupUi(this); + ui.enabled->setIcon(SmallIcon("media-playback-start")); + ui.play->setIcon(SmallIcon("media-playback-start")); + ui.open->setIcon(SmallIcon("document-open")); - connect(ui.enabled, SIGNAL(toggled(bool)), SLOT(widgetChanged())); - connect(ui.filename, SIGNAL(textChanged(const QString &)), SLOT(widgetChanged())); + connect(ui.enabled, SIGNAL(toggled(bool)), SLOT(widgetChanged())); + connect(ui.filename, SIGNAL(textChanged(const QString &)), SLOT(widgetChanged())); } -PhononNotificationBackend::ConfigWidget::~ConfigWidget() { - if(audioPreview) - delete audioPreview; + +PhononNotificationBackend::ConfigWidget::~ConfigWidget() +{ + if (audioPreview) + delete audioPreview; } -void PhononNotificationBackend::ConfigWidget::widgetChanged() { - ui.play->setEnabled(ui.enabled->isChecked() && !ui.filename->text().isEmpty()); - bool changed = (enabled != ui.enabled->isChecked() - || filename != ui.filename->text()); +void PhononNotificationBackend::ConfigWidget::widgetChanged() +{ + ui.play->setEnabled(ui.enabled->isChecked() && !ui.filename->text().isEmpty()); + + bool changed = (enabled != ui.enabled->isChecked() + || filename != ui.filename->text()); - if(changed != hasChanged()) setChangedState(changed); + if (changed != hasChanged()) setChangedState(changed); } -bool PhononNotificationBackend::ConfigWidget::hasDefaults() const { - return true; + +bool PhononNotificationBackend::ConfigWidget::hasDefaults() const +{ + return true; } -void PhononNotificationBackend::ConfigWidget::defaults() { - ui.enabled->setChecked(false); - ui.filename->setText(QString()); - widgetChanged(); + +void PhononNotificationBackend::ConfigWidget::defaults() +{ + ui.enabled->setChecked(false); + ui.filename->setText(QString()); + widgetChanged(); } -void PhononNotificationBackend::ConfigWidget::load() { - NotificationSettings s; - enabled = s.value("Phonon/Enabled", false).toBool(); - filename = s.value("Phonon/AudioFile", QString()).toString(); - ui.enabled->setChecked(enabled); - ui.filename->setText(filename); +void PhononNotificationBackend::ConfigWidget::load() +{ + NotificationSettings s; + enabled = s.value("Phonon/Enabled", false).toBool(); + filename = s.value("Phonon/AudioFile", QString()).toString(); + + ui.enabled->setChecked(enabled); + ui.filename->setText(filename); - setChangedState(false); + setChangedState(false); } -void PhononNotificationBackend::ConfigWidget::save() { - NotificationSettings s; - s.setValue("Phonon/Enabled", ui.enabled->isChecked()); - s.setValue("Phonon/AudioFile", ui.filename->text()); - load(); + +void PhononNotificationBackend::ConfigWidget::save() +{ + NotificationSettings s; + s.setValue("Phonon/Enabled", ui.enabled->isChecked()); + s.setValue("Phonon/AudioFile", ui.filename->text()); + load(); } -void PhononNotificationBackend::ConfigWidget::on_open_clicked() { - QString file = QFileDialog::getOpenFileName(this, tr("Select Audio File")); - if(!file.isEmpty()) { - ui.filename->setText(file); - ui.play->setEnabled(true); - widgetChanged(); - } + +void PhononNotificationBackend::ConfigWidget::on_open_clicked() +{ + QString file = QFileDialog::getOpenFileName(this, tr("Select Audio File")); + if (!file.isEmpty()) { + ui.filename->setText(file); + ui.play->setEnabled(true); + widgetChanged(); + } } -void PhononNotificationBackend::ConfigWidget::on_play_clicked() { - if(!ui.filename->text().isEmpty()) { - if(audioPreview) - delete audioPreview; - audioPreview = Phonon::createPlayer(Phonon::NotificationCategory, - Phonon::MediaSource(ui.filename->text())); - audioPreview->play(); - } +void PhononNotificationBackend::ConfigWidget::on_play_clicked() +{ + if (!ui.filename->text().isEmpty()) { + if (audioPreview) + delete audioPreview; + + audioPreview = Phonon::createPlayer(Phonon::NotificationCategory, + Phonon::MediaSource(ui.filename->text())); + audioPreview->play(); + } } diff --git a/src/qtui/phononnotificationbackend.h b/src/qtui/phononnotificationbackend.h index a15942f6..6eaf2662 100644 --- a/src/qtui/phononnotificationbackend.h +++ b/src/qtui/phononnotificationbackend.h @@ -28,52 +28,56 @@ #include "ui_phononnotificationconfigwidget.h" -class PhononNotificationBackend : public AbstractNotificationBackend { - Q_OBJECT +class PhononNotificationBackend : public AbstractNotificationBackend +{ + Q_OBJECT public: - PhononNotificationBackend(QObject *parent = 0); - ~PhononNotificationBackend(); + PhononNotificationBackend(QObject *parent = 0); + ~PhononNotificationBackend(); - void notify(const Notification &); - void close(uint notificationId); - virtual SettingsPage *createConfigWidget() const; + void notify(const Notification &); + void close(uint notificationId); + virtual SettingsPage *createConfigWidget() const; private slots: - void enabledChanged(const QVariant &); - void audioFileChanged(const QVariant &); - void createMediaObject(const QString &name); + void enabledChanged(const QVariant &); + void audioFileChanged(const QVariant &); + void createMediaObject(const QString &name); private: - class ConfigWidget; + class ConfigWidget; - bool _enabled; - Phonon::MediaObject *_media; + bool _enabled; + Phonon::MediaObject *_media; }; -class PhononNotificationBackend::ConfigWidget : public SettingsPage { - Q_OBJECT + +class PhononNotificationBackend::ConfigWidget : public SettingsPage +{ + Q_OBJECT public: - ConfigWidget(QWidget *parent = 0); - ~ConfigWidget(); + ConfigWidget(QWidget *parent = 0); + ~ConfigWidget(); - void save(); - void load(); - bool hasDefaults() const; - void defaults(); + void save(); + void load(); + bool hasDefaults() const; + void defaults(); private slots: - void widgetChanged(); - void on_open_clicked(); - void on_play_clicked(); + void widgetChanged(); + void on_open_clicked(); + void on_play_clicked(); private: - Ui::PhononNotificationConfigWidget ui; + Ui::PhononNotificationConfigWidget ui; - bool enabled; - QString filename; - Phonon::MediaObject *audioPreview; + bool enabled; + QString filename; + Phonon::MediaObject *audioPreview; }; + #endif diff --git a/src/qtui/qtui.cpp b/src/qtui/qtui.cpp index f2b0ec90..9b1f6af6 100644 --- a/src/qtui/qtui.cpp +++ b/src/qtui/qtui.cpp @@ -42,168 +42,213 @@ MainWin *QtUi::_mainWin = 0; QList QtUi::_notificationBackends; QList QtUi::_notifications; -QtUi::QtUi() : GraphicalUi() { - if(_instance != 0) { - qWarning() << "QtUi has been instantiated again!"; - return; - } - _instance = this; +QtUi::QtUi() : GraphicalUi() +{ + if (_instance != 0) { + qWarning() << "QtUi has been instantiated again!"; + return; + } + _instance = this; - QtUiSettings uiSettings; - Quassel::loadTranslation(uiSettings.value("Locale", QLocale::system()).value()); + QtUiSettings uiSettings; + Quassel::loadTranslation(uiSettings.value("Locale", QLocale::system()).value()); - setContextMenuActionProvider(new ContextMenuActionProvider(this)); - setToolBarActionProvider(new ToolBarActionProvider(this)); + setContextMenuActionProvider(new ContextMenuActionProvider(this)); + setToolBarActionProvider(new ToolBarActionProvider(this)); - setUiStyle(new QtUiStyle(this)); - _mainWin = new MainWin(); + setUiStyle(new QtUiStyle(this)); + _mainWin = new MainWin(); - setMainWidget(_mainWin); + setMainWidget(_mainWin); - connect(_mainWin, SIGNAL(connectToCore(const QVariantMap &)), this, SIGNAL(connectToCore(const QVariantMap &))); - connect(_mainWin, SIGNAL(disconnectFromCore()), this, SIGNAL(disconnectFromCore())); - connect(Client::instance(), SIGNAL(bufferMarkedAsRead(BufferId)), SLOT(closeNotifications(BufferId))); + connect(_mainWin, SIGNAL(connectToCore(const QVariantMap &)), this, SIGNAL(connectToCore(const QVariantMap &))); + connect(_mainWin, SIGNAL(disconnectFromCore()), this, SIGNAL(disconnectFromCore())); + connect(Client::instance(), SIGNAL(bufferMarkedAsRead(BufferId)), SLOT(closeNotifications(BufferId))); } -QtUi::~QtUi() { - unregisterAllNotificationBackends(); - delete _mainWin; - _mainWin = 0; - _instance = 0; + +QtUi::~QtUi() +{ + unregisterAllNotificationBackends(); + delete _mainWin; + _mainWin = 0; + _instance = 0; } -void QtUi::init() { - _mainWin->init(); - QtUiSettings uiSettings; - uiSettings.initAndNotify("UseSystemTrayIcon", this, SLOT(useSystemTrayChanged(QVariant)), true); - GraphicalUi::init(); // needs to be called after the mainWin is initialized +void QtUi::init() +{ + _mainWin->init(); + QtUiSettings uiSettings; + uiSettings.initAndNotify("UseSystemTrayIcon", this, SLOT(useSystemTrayChanged(QVariant)), true); + + GraphicalUi::init(); // needs to be called after the mainWin is initialized } -MessageModel *QtUi::createMessageModel(QObject *parent) { - return new ChatLineModel(parent); + +MessageModel *QtUi::createMessageModel(QObject *parent) +{ + return new ChatLineModel(parent); } -AbstractMessageProcessor *QtUi::createMessageProcessor(QObject *parent) { - return new QtUiMessageProcessor(parent); + +AbstractMessageProcessor *QtUi::createMessageProcessor(QObject *parent) +{ + return new QtUiMessageProcessor(parent); } -void QtUi::connectedToCore() { - _mainWin->connectedToCore(); + +void QtUi::connectedToCore() +{ + _mainWin->connectedToCore(); } -void QtUi::disconnectedFromCore() { - _mainWin->disconnectedFromCore(); - GraphicalUi::disconnectedFromCore(); + +void QtUi::disconnectedFromCore() +{ + _mainWin->disconnectedFromCore(); + GraphicalUi::disconnectedFromCore(); } -void QtUi::useSystemTrayChanged(const QVariant &v) { - _useSystemTray = v.toBool(); - SystemTray *tray = mainWindow()->systemTray(); - if(_useSystemTray) { - if(tray->isSystemTrayAvailable()) - tray->setVisible(true); - } else { - if(tray->isSystemTrayAvailable() && mainWindow()->isVisible()) - tray->setVisible(false); - } + +void QtUi::useSystemTrayChanged(const QVariant &v) +{ + _useSystemTray = v.toBool(); + SystemTray *tray = mainWindow()->systemTray(); + if (_useSystemTray) { + if (tray->isSystemTrayAvailable()) + tray->setVisible(true); + } + else { + if (tray->isSystemTrayAvailable() && mainWindow()->isVisible()) + tray->setVisible(false); + } } -bool QtUi::haveSystemTray() { - return mainWindow()->systemTray()->isSystemTrayAvailable() && instance()->_useSystemTray; + +bool QtUi::haveSystemTray() +{ + return mainWindow()->systemTray()->isSystemTrayAvailable() && instance()->_useSystemTray; } -bool QtUi::isHidingMainWidgetAllowed() const { - return haveSystemTray(); + +bool QtUi::isHidingMainWidgetAllowed() const +{ + return haveSystemTray(); } -void QtUi::minimizeRestore(bool show) { - SystemTray *tray = mainWindow()->systemTray(); - if(show) { - if(tray && !_useSystemTray) - tray->setVisible(false); - } else { - if(tray && _useSystemTray) - tray->setVisible(true); - } - GraphicalUi::minimizeRestore(show); + +void QtUi::minimizeRestore(bool show) +{ + SystemTray *tray = mainWindow()->systemTray(); + if (show) { + if (tray && !_useSystemTray) + tray->setVisible(false); + } + else { + if (tray && _useSystemTray) + tray->setVisible(true); + } + GraphicalUi::minimizeRestore(show); } -void QtUi::registerNotificationBackend(AbstractNotificationBackend *backend) { - if(!_notificationBackends.contains(backend)) { - _notificationBackends.append(backend); - instance()->connect(backend, SIGNAL(activated(uint)), SLOT(notificationActivated(uint))); - } + +void QtUi::registerNotificationBackend(AbstractNotificationBackend *backend) +{ + if (!_notificationBackends.contains(backend)) { + _notificationBackends.append(backend); + instance()->connect(backend, SIGNAL(activated(uint)), SLOT(notificationActivated(uint))); + } } -void QtUi::unregisterNotificationBackend(AbstractNotificationBackend *backend) { - _notificationBackends.removeAll(backend); + +void QtUi::unregisterNotificationBackend(AbstractNotificationBackend *backend) +{ + _notificationBackends.removeAll(backend); } -void QtUi::unregisterAllNotificationBackends() { - _notificationBackends.clear(); + +void QtUi::unregisterAllNotificationBackends() +{ + _notificationBackends.clear(); } -const QList &QtUi::notificationBackends() { - return _notificationBackends; + +const QList &QtUi::notificationBackends() +{ + return _notificationBackends; } -uint QtUi::invokeNotification(BufferId bufId, AbstractNotificationBackend::NotificationType type, const QString &sender, const QString &text) { - static int notificationId = 0; - AbstractNotificationBackend::Notification notification(++notificationId, bufId, type, sender, text); - _notifications.append(notification); - foreach(AbstractNotificationBackend *backend, _notificationBackends) +uint QtUi::invokeNotification(BufferId bufId, AbstractNotificationBackend::NotificationType type, const QString &sender, const QString &text) +{ + static int notificationId = 0; + + AbstractNotificationBackend::Notification notification(++notificationId, bufId, type, sender, text); + _notifications.append(notification); + foreach(AbstractNotificationBackend *backend, _notificationBackends) backend->notify(notification); - return notificationId; + return notificationId; } -void QtUi::closeNotification(uint notificationId) { - QList::iterator i = _notifications.begin(); - while(i != _notifications.end()) { - if(i->notificationId == notificationId) { - foreach(AbstractNotificationBackend *backend, _notificationBackends) - backend->close(notificationId); - i = _notifications.erase(i); - } else ++i; - } + +void QtUi::closeNotification(uint notificationId) +{ + QList::iterator i = _notifications.begin(); + while (i != _notifications.end()) { + if (i->notificationId == notificationId) { + foreach(AbstractNotificationBackend *backend, _notificationBackends) + backend->close(notificationId); + i = _notifications.erase(i); + } + else ++i; + } } -void QtUi::closeNotifications(BufferId bufferId) { - QList::iterator i = _notifications.begin(); - while(i != _notifications.end()) { - if(!bufferId.isValid() || i->bufferId == bufferId) { - foreach(AbstractNotificationBackend *backend, _notificationBackends) - backend->close(i->notificationId); - i = _notifications.erase(i); - } else ++i; - } + +void QtUi::closeNotifications(BufferId bufferId) +{ + QList::iterator i = _notifications.begin(); + while (i != _notifications.end()) { + if (!bufferId.isValid() || i->bufferId == bufferId) { + foreach(AbstractNotificationBackend *backend, _notificationBackends) + backend->close(i->notificationId); + i = _notifications.erase(i); + } + else ++i; + } } -const QList &QtUi::activeNotifications() { - return _notifications; + +const QList &QtUi::activeNotifications() +{ + return _notifications; } -void QtUi::notificationActivated(uint notificationId) { - if(notificationId != 0) { - QList::iterator i = _notifications.begin(); - while(i != _notifications.end()) { - if(i->notificationId == notificationId) { - BufferId bufId = i->bufferId; - if(bufId.isValid()) - Client::bufferModel()->switchToBuffer(bufId); - break; - } - ++i; + +void QtUi::notificationActivated(uint notificationId) +{ + if (notificationId != 0) { + QList::iterator i = _notifications.begin(); + while (i != _notifications.end()) { + if (i->notificationId == notificationId) { + BufferId bufId = i->bufferId; + if (bufId.isValid()) + Client::bufferModel()->switchToBuffer(bufId); + break; + } + ++i; + } } - } - closeNotification(notificationId); + closeNotification(notificationId); - activateMainWidget(); + activateMainWidget(); } -void QtUi::bufferMarkedAsRead(BufferId bufferId) { - if(bufferId.isValid()) { - closeNotifications(bufferId); - } + +void QtUi::bufferMarkedAsRead(BufferId bufferId) +{ + if (bufferId.isValid()) { + closeNotifications(bufferId); + } } diff --git a/src/qtui/qtui.h b/src/qtui/qtui.h index 5d60c26b..4584c483 100644 --- a/src/qtui/qtui.h +++ b/src/qtui/qtui.h @@ -34,61 +34,63 @@ class QtUiMessageProcessor; /** This is basically a wrapper around MainWin, which is necessary because we cannot derive MainWin * from both QMainWindow and AbstractUi (because of multiple inheritance of QObject). */ -class QtUi : public GraphicalUi { - Q_OBJECT +class QtUi : public GraphicalUi +{ + Q_OBJECT public: - QtUi(); - ~QtUi(); + QtUi(); + ~QtUi(); - MessageModel *createMessageModel(QObject *parent); - AbstractMessageProcessor *createMessageProcessor(QObject *parent); + MessageModel *createMessageModel(QObject *parent); + AbstractMessageProcessor *createMessageProcessor(QObject *parent); - inline static QtUi *instance(); - inline static QtUiStyle *style(); - inline static MainWin *mainWindow(); + inline static QtUi *instance(); + inline static QtUiStyle *style(); + inline static MainWin *mainWindow(); - static bool haveSystemTray(); + static bool haveSystemTray(); - /* Notifications */ + /* Notifications */ - static void registerNotificationBackend(AbstractNotificationBackend *); - static void unregisterNotificationBackend(AbstractNotificationBackend *); - static void unregisterAllNotificationBackends(); - static const QList ¬ificationBackends(); - static const QList &activeNotifications(); + static void registerNotificationBackend(AbstractNotificationBackend *); + static void unregisterNotificationBackend(AbstractNotificationBackend *); + static void unregisterAllNotificationBackends(); + static const QList ¬ificationBackends(); + static const QList &activeNotifications(); public slots: - virtual void init(); + virtual void init(); - uint invokeNotification(BufferId bufId, AbstractNotificationBackend::NotificationType type, const QString &sender, const QString &text); - void closeNotification(uint notificationId); - void closeNotifications(BufferId bufferId = BufferId()); + uint invokeNotification(BufferId bufId, AbstractNotificationBackend::NotificationType type, const QString &sender, const QString &text); + void closeNotification(uint notificationId); + void closeNotifications(BufferId bufferId = BufferId()); protected slots: - void connectedToCore(); - void disconnectedFromCore(); - void notificationActivated(uint notificationId); - void bufferMarkedAsRead(BufferId); + void connectedToCore(); + void disconnectedFromCore(); + void notificationActivated(uint notificationId); + void bufferMarkedAsRead(BufferId); protected: - virtual void minimizeRestore(bool show); - virtual bool isHidingMainWidgetAllowed() const; + virtual void minimizeRestore(bool show); + virtual bool isHidingMainWidgetAllowed() const; private slots: - void useSystemTrayChanged(const QVariant &); + void useSystemTrayChanged(const QVariant &); private: - static QtUi *_instance; - static MainWin *_mainWin; - static QList _notificationBackends; - static QList _notifications; + static QtUi *_instance; + static MainWin *_mainWin; + static QList _notificationBackends; + static QList _notifications; - bool _useSystemTray; + bool _useSystemTray; }; + QtUi *QtUi::instance() { return _instance ? _instance : new QtUi(); } -QtUiStyle *QtUi::style() { return qobject_cast(uiStyle()); } +QtUiStyle *QtUi::style() { return qobject_cast(uiStyle()); } MainWin *QtUi::mainWindow() { return _mainWin; } #endif diff --git a/src/qtui/qtuiapplication.cpp b/src/qtui/qtuiapplication.cpp index fb38348e..ab514355 100644 --- a/src/qtui/qtuiapplication.cpp +++ b/src/qtui/qtuiapplication.cpp @@ -34,129 +34,141 @@ QtUiApplication::QtUiApplication(int &argc, char **argv) #ifdef HAVE_KDE - : KApplication(), + : KApplication(), #else - : QApplication(argc, argv), + : QApplication(argc, argv), #endif Quassel(), _aboutToQuit(false) { #ifdef HAVE_KDE - Q_UNUSED(argc); Q_UNUSED(argv); + Q_UNUSED(argc); Q_UNUSED(argv); - // We need to setup KDE's data dirs - QStringList dataDirs = KGlobal::dirs()->findDirs("data", ""); - for(int i = 0; i < dataDirs.count(); i++) - dataDirs[i].append("quassel/"); - dataDirs.append(":/data/"); - setDataDirPaths(dataDirs); + // We need to setup KDE's data dirs + QStringList dataDirs = KGlobal::dirs()->findDirs("data", ""); + for (int i = 0; i < dataDirs.count(); i++) + dataDirs[i].append("quassel/"); + dataDirs.append(":/data/"); + setDataDirPaths(dataDirs); #else /* HAVE_KDE */ - setDataDirPaths(findDataDirPaths()); + setDataDirPaths(findDataDirPaths()); #endif /* HAVE_KDE */ #if defined(HAVE_KDE) || defined(Q_OS_MAC) - disableCrashhandler(); + disableCrashhandler(); #endif /* HAVE_KDE || Q_OS_MAC */ - setRunMode(Quassel::ClientOnly); + setRunMode(Quassel::ClientOnly); - qInstallMsgHandler(Client::logMessage); + qInstallMsgHandler(Client::logMessage); } -bool QtUiApplication::init() { - if(Quassel::init()) { - // FIXME: MIGRATION 0.3 -> 0.4: Move database and core config to new location - // Move settings, note this does not delete the old files +bool QtUiApplication::init() +{ + if (Quassel::init()) { + // FIXME: MIGRATION 0.3 -> 0.4: Move database and core config to new location + // Move settings, note this does not delete the old files #ifdef Q_WS_MAC - QSettings newSettings("quassel-irc.org", "quasselclient"); + QSettings newSettings("quassel-irc.org", "quasselclient"); #else # ifdef Q_WS_WIN - QSettings::Format format = QSettings::IniFormat; + QSettings::Format format = QSettings::IniFormat; # else - QSettings::Format format = QSettings::NativeFormat; + QSettings::Format format = QSettings::NativeFormat; # endif - QString newFilePath = Quassel::configDirPath() + "quasselclient" - + ((format == QSettings::NativeFormat) ? QLatin1String(".conf") : QLatin1String(".ini")); - QSettings newSettings(newFilePath, format); + QString newFilePath = Quassel::configDirPath() + "quasselclient" + + ((format == QSettings::NativeFormat) ? QLatin1String(".conf") : QLatin1String(".ini")); + QSettings newSettings(newFilePath, format); #endif /* Q_WS_MAC */ - if(newSettings.value("Config/Version").toUInt() == 0) { + if (newSettings.value("Config/Version").toUInt() == 0) { # ifdef Q_WS_MAC - QString org = "quassel-irc.org"; + QString org = "quassel-irc.org"; # else - QString org = "Quassel Project"; + QString org = "Quassel Project"; # endif - QSettings oldSettings(org, "Quassel Client"); - if(oldSettings.allKeys().count()) { - qWarning() << "\n\n*** IMPORTANT: Config and data file locations have changed. Attempting to auto-migrate your client settings..."; - foreach(QString key, oldSettings.allKeys()) - newSettings.setValue(key, oldSettings.value(key)); - newSettings.setValue("Config/Version", 1); - qWarning() << "* Your client settings have been migrated to" << newSettings.fileName(); - qWarning() << "*** Migration completed.\n\n"; - } + QSettings oldSettings(org, "Quassel Client"); + if (oldSettings.allKeys().count()) { + qWarning() << "\n\n*** IMPORTANT: Config and data file locations have changed. Attempting to auto-migrate your client settings..."; + foreach(QString key, oldSettings.allKeys()) + newSettings.setValue(key, oldSettings.value(key)); + newSettings.setValue("Config/Version", 1); + qWarning() << "* Your client settings have been migrated to" << newSettings.fileName(); + qWarning() << "*** Migration completed.\n\n"; + } + } + + // MIGRATION end + + // check settings version + // so far, we only have 1 + QtUiSettings s; + if (s.version() != 1) { + qCritical() << "Invalid client settings version, terminating!"; + return false; + } + + // session resume + QtUi *gui = new QtUi(); + Client::init(gui); + // init gui only after the event loop has started + // QTimer::singleShot(0, gui, SLOT(init())); + gui->init(); + resumeSessionIfPossible(); + return true; } + return false; +} - // MIGRATION end - // check settings version - // so far, we only have 1 - QtUiSettings s; - if(s.version() != 1) { - qCritical() << "Invalid client settings version, terminating!"; - return false; - } - - // session resume - QtUi *gui = new QtUi(); - Client::init(gui); - // init gui only after the event loop has started - // QTimer::singleShot(0, gui, SLOT(init())); - gui->init(); - resumeSessionIfPossible(); - return true; - } - return false; +QtUiApplication::~QtUiApplication() +{ + Client::destroy(); } -QtUiApplication::~QtUiApplication() { - Client::destroy(); -} -void QtUiApplication::quit() { - QtUi::mainWindow()->quit(); +void QtUiApplication::quit() +{ + QtUi::mainWindow()->quit(); } -void QtUiApplication::commitData(QSessionManager &manager) { - Q_UNUSED(manager) - _aboutToQuit = true; -} -void QtUiApplication::saveState(QSessionManager & manager) { - //qDebug() << QString("saving session state to id %1").arg(manager.sessionId()); - // AccountId activeCore = Client::currentCoreAccount().accountId(); // FIXME store this! - SessionSettings s(manager.sessionId()); - s.setSessionAge(0); - QtUi::mainWindow()->saveStateToSettings(s); +void QtUiApplication::commitData(QSessionManager &manager) +{ + Q_UNUSED(manager) + _aboutToQuit = true; } -void QtUiApplication::resumeSessionIfPossible() { - // load all sessions - if(isSessionRestored()) { - qDebug() << QString("restoring from session %1").arg(sessionId()); - SessionSettings s(sessionId()); - s.sessionAging(); + +void QtUiApplication::saveState(QSessionManager &manager) +{ + //qDebug() << QString("saving session state to id %1").arg(manager.sessionId()); + // AccountId activeCore = Client::currentCoreAccount().accountId(); // FIXME store this! + SessionSettings s(manager.sessionId()); s.setSessionAge(0); - QtUi::mainWindow()->restoreStateFromSettings(s); - s.cleanup(); - } else { - SessionSettings s(QString("1")); - s.sessionAging(); - s.cleanup(); - } + QtUi::mainWindow()->saveStateToSettings(s); +} + + +void QtUiApplication::resumeSessionIfPossible() +{ + // load all sessions + if (isSessionRestored()) { + qDebug() << QString("restoring from session %1").arg(sessionId()); + SessionSettings s(sessionId()); + s.sessionAging(); + s.setSessionAge(0); + QtUi::mainWindow()->restoreStateFromSettings(s); + s.cleanup(); + } + else { + SessionSettings s(QString("1")); + s.sessionAging(); + s.cleanup(); + } } diff --git a/src/qtui/qtuiapplication.h b/src/qtui/qtuiapplication.h index 74788754..525a22ab 100644 --- a/src/qtui/qtuiapplication.h +++ b/src/qtui/qtuiapplication.h @@ -35,29 +35,32 @@ class QtUi; #ifdef HAVE_KDE -class QtUiApplication : public KApplication, public Quassel { +class QtUiApplication : public KApplication, public Quassel +{ #else -class QtUiApplication : public QApplication, public Quassel { +class QtUiApplication : public QApplication, public Quassel +{ #endif - Q_OBJECT + Q_OBJECT public: - QtUiApplication(int &, char **); - ~QtUiApplication(); - virtual bool init(); + QtUiApplication(int &, char **); + ~QtUiApplication(); + virtual bool init(); - void resumeSessionIfPossible(); - virtual void commitData(QSessionManager &manager); - virtual void saveState(QSessionManager &manager); + void resumeSessionIfPossible(); + virtual void commitData(QSessionManager &manager); + virtual void saveState(QSessionManager &manager); - inline bool isAboutToQuit() const { return _aboutToQuit; } + inline bool isAboutToQuit() const { return _aboutToQuit; } protected: - virtual void quit(); + virtual void quit(); private: - bool _aboutToQuit; + bool _aboutToQuit; }; + #endif diff --git a/src/qtui/qtuimessageprocessor.cpp b/src/qtui/qtuimessageprocessor.cpp index 4754a024..ca939387 100644 --- a/src/qtui/qtuimessageprocessor.cpp +++ b/src/qtui/qtuimessageprocessor.cpp @@ -29,155 +29,175 @@ const int progressUpdateDelay = 100; // ms between progress signal updates QtUiMessageProcessor::QtUiMessageProcessor(QObject *parent) - : AbstractMessageProcessor(parent), + : AbstractMessageProcessor(parent), _processing(false), _processMode(TimerBased) { - NotificationSettings notificationSettings; - _nicksCaseSensitive = notificationSettings.nicksCaseSensitive(); - _highlightNick = notificationSettings.highlightNick(); - highlightListChanged(notificationSettings.highlightList()); - notificationSettings.notify("Highlights/NicksCaseSensitive", this, SLOT(nicksCaseSensitiveChanged(const QVariant &))); - notificationSettings.notify("Highlights/CustomList", this, SLOT(highlightListChanged(const QVariant &))); - notificationSettings.notify("Highlights/HighlightNick", this, SLOT(highlightNickChanged(const QVariant &))); - - _processTimer.setInterval(0); - connect(&_processTimer, SIGNAL(timeout()), this, SLOT(processNextMessage())); + NotificationSettings notificationSettings; + _nicksCaseSensitive = notificationSettings.nicksCaseSensitive(); + _highlightNick = notificationSettings.highlightNick(); + highlightListChanged(notificationSettings.highlightList()); + notificationSettings.notify("Highlights/NicksCaseSensitive", this, SLOT(nicksCaseSensitiveChanged(const QVariant &))); + notificationSettings.notify("Highlights/CustomList", this, SLOT(highlightListChanged(const QVariant &))); + notificationSettings.notify("Highlights/HighlightNick", this, SLOT(highlightNickChanged(const QVariant &))); + + _processTimer.setInterval(0); + connect(&_processTimer, SIGNAL(timeout()), this, SLOT(processNextMessage())); } -void QtUiMessageProcessor::reset() { - if(processMode() == TimerBased) { - if(_processTimer.isActive()) _processTimer.stop(); - _processing = false; - _currentBatch.clear(); - _processQueue.clear(); - } -} -void QtUiMessageProcessor::process(Message &msg) { - checkForHighlight(msg); - preProcess(msg); - Client::messageModel()->insertMessage(msg); +void QtUiMessageProcessor::reset() +{ + if (processMode() == TimerBased) { + if (_processTimer.isActive()) _processTimer.stop(); + _processing = false; + _currentBatch.clear(); + _processQueue.clear(); + } } -void QtUiMessageProcessor::process(QList &msgs) { - QList::iterator msgIter = msgs.begin(); - QList::iterator msgIterEnd = msgs.end(); - while(msgIter != msgIterEnd) { - checkForHighlight(*msgIter); - preProcess(*msgIter); - msgIter++; - } - Client::messageModel()->insertMessages(msgs); - return; - - - if(msgs.isEmpty()) return; - _processQueue.append(msgs); - if(!isProcessing()) - startProcessing(); + +void QtUiMessageProcessor::process(Message &msg) +{ + checkForHighlight(msg); + preProcess(msg); + Client::messageModel()->insertMessage(msg); } -void QtUiMessageProcessor::startProcessing() { - if(processMode() == TimerBased) { - if(_currentBatch.isEmpty() && _processQueue.isEmpty()) - return; - _processing = true; - if(!_processTimer.isActive()) - _processTimer.start(); - } + +void QtUiMessageProcessor::process(QList &msgs) +{ + QList::iterator msgIter = msgs.begin(); + QList::iterator msgIterEnd = msgs.end(); + while (msgIter != msgIterEnd) { + checkForHighlight(*msgIter); + preProcess(*msgIter); + msgIter++; + } + Client::messageModel()->insertMessages(msgs); + return; + + if (msgs.isEmpty()) return; + _processQueue.append(msgs); + if (!isProcessing()) + startProcessing(); } -void QtUiMessageProcessor::processNextMessage() { - if(_currentBatch.isEmpty()) { - if(_processQueue.isEmpty()) { - _processTimer.stop(); - _processing = false; - return; + +void QtUiMessageProcessor::startProcessing() +{ + if (processMode() == TimerBased) { + if (_currentBatch.isEmpty() && _processQueue.isEmpty()) + return; + _processing = true; + if (!_processTimer.isActive()) + _processTimer.start(); } - _currentBatch = _processQueue.takeFirst(); - } - Message msg = _currentBatch.takeFirst(); - process(msg); } -void QtUiMessageProcessor::checkForHighlight(Message &msg) { - if(!((msg.type() & (Message::Plain | Message::Notice | Message::Action)) && !(msg.flags() & Message::Self))) - return; - // TODO: Cache this (per network) - const Network *net = Client::network(msg.bufferInfo().networkId()); - if(net && !net->myNick().isEmpty()) { - QStringList nickList; - if(_highlightNick == NotificationSettings::CurrentNick) { - nickList << net->myNick(); - } else if(_highlightNick == NotificationSettings::AllNicks) { - const Identity *myIdentity = Client::identity(net->identity()); - if(myIdentity) - nickList = myIdentity->nicks(); - if(!nickList.contains(net->myNick())) - nickList.prepend(net->myNick()); +void QtUiMessageProcessor::processNextMessage() +{ + if (_currentBatch.isEmpty()) { + if (_processQueue.isEmpty()) { + _processTimer.stop(); + _processing = false; + return; + } + _currentBatch = _processQueue.takeFirst(); } - foreach(QString nickname, nickList) { - QRegExp nickRegExp("(^|\\W)" + QRegExp::escape(nickname) + "(\\W|$)", _nicksCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive); - if(nickRegExp.indexIn(msg.contents()) >= 0) { - msg.setFlags(msg.flags() | Message::Highlight); + Message msg = _currentBatch.takeFirst(); + process(msg); +} + + +void QtUiMessageProcessor::checkForHighlight(Message &msg) +{ + if (!((msg.type() & (Message::Plain | Message::Notice | Message::Action)) && !(msg.flags() & Message::Self))) return; - } - } - for(int i = 0; i < _highlightRules.count(); i++) { - const HighlightRule &rule = _highlightRules.at(i); - if(!rule.isEnabled) - continue; - - if(rule.chanName.size() > 0 && rule.chanName.compare(".*") != 0) { - if(rule.chanName.startsWith("!")) { - QRegExp rx(rule.chanName.mid(1), Qt::CaseInsensitive); - if(rx.exactMatch(msg.bufferInfo().bufferName())) - continue; - } else { - QRegExp rx(rule.chanName, Qt::CaseInsensitive); - if(!rx.exactMatch(msg.bufferInfo().bufferName())) - continue; + // TODO: Cache this (per network) + const Network *net = Client::network(msg.bufferInfo().networkId()); + if (net && !net->myNick().isEmpty()) { + QStringList nickList; + if (_highlightNick == NotificationSettings::CurrentNick) { + nickList << net->myNick(); + } + else if (_highlightNick == NotificationSettings::AllNicks) { + const Identity *myIdentity = Client::identity(net->identity()); + if (myIdentity) + nickList = myIdentity->nicks(); + if (!nickList.contains(net->myNick())) + nickList.prepend(net->myNick()); + } + foreach(QString nickname, nickList) { + QRegExp nickRegExp("(^|\\W)" + QRegExp::escape(nickname) + "(\\W|$)", _nicksCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive); + if (nickRegExp.indexIn(msg.contents()) >= 0) { + msg.setFlags(msg.flags() | Message::Highlight); + return; + } + } + + for (int i = 0; i < _highlightRules.count(); i++) { + const HighlightRule &rule = _highlightRules.at(i); + if (!rule.isEnabled) + continue; + + if (rule.chanName.size() > 0 && rule.chanName.compare(".*") != 0) { + if (rule.chanName.startsWith("!")) { + QRegExp rx(rule.chanName.mid(1), Qt::CaseInsensitive); + if (rx.exactMatch(msg.bufferInfo().bufferName())) + continue; + } + else { + QRegExp rx(rule.chanName, Qt::CaseInsensitive); + if (!rx.exactMatch(msg.bufferInfo().bufferName())) + continue; + } + } + + QRegExp rx; + if (rule.isRegExp) { + rx = QRegExp(rule.name, rule.caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive); + } + else { + rx = QRegExp("(^|\\W)" + QRegExp::escape(rule.name) + "(\\W|$)", rule.caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive); + } + bool match = (rx.indexIn(msg.contents()) >= 0); + if (match) { + msg.setFlags(msg.flags() | Message::Highlight); + return; + } } - } - - QRegExp rx; - if(rule.isRegExp) { - rx = QRegExp(rule.name, rule.caseSensitive? Qt::CaseSensitive : Qt::CaseInsensitive); - } else { - rx = QRegExp("(^|\\W)" + QRegExp::escape(rule.name) + "(\\W|$)", rule.caseSensitive? Qt::CaseSensitive : Qt::CaseInsensitive); - } - bool match = (rx.indexIn(msg.contents()) >= 0); - if(match) { - msg.setFlags(msg.flags() | Message::Highlight); - return; - } } - } } -void QtUiMessageProcessor::nicksCaseSensitiveChanged(const QVariant &variant) { - _nicksCaseSensitive = variant.toBool(); + +void QtUiMessageProcessor::nicksCaseSensitiveChanged(const QVariant &variant) +{ + _nicksCaseSensitive = variant.toBool(); } -void QtUiMessageProcessor::highlightListChanged(const QVariant &variant) { - QVariantList varList = variant.toList(); - - _highlightRules.clear(); - QVariantList::const_iterator iter = varList.constBegin(); - while(iter != varList.constEnd()) { - QVariantMap rule = iter->toMap(); - _highlightRules << HighlightRule(rule["Name"].toString(), - rule["Enable"].toBool(), - rule["CS"].toBool() ? Qt::CaseSensitive : Qt::CaseInsensitive, - rule["RegEx"].toBool(), - rule["Channel"].toString()); - iter++; - } + +void QtUiMessageProcessor::highlightListChanged(const QVariant &variant) +{ + QVariantList varList = variant.toList(); + + _highlightRules.clear(); + QVariantList::const_iterator iter = varList.constBegin(); + while (iter != varList.constEnd()) { + QVariantMap rule = iter->toMap(); + _highlightRules << HighlightRule(rule["Name"].toString(), + rule["Enable"].toBool(), + rule["CS"].toBool() ? Qt::CaseSensitive : Qt::CaseInsensitive, + rule["RegEx"].toBool(), + rule["Channel"].toString()); + iter++; + } } -void QtUiMessageProcessor::highlightNickChanged(const QVariant &variant) { - _highlightNick = (NotificationSettings::HighlightNickType)variant.toInt(); + +void QtUiMessageProcessor::highlightNickChanged(const QVariant &variant) +{ + _highlightNick = (NotificationSettings::HighlightNickType)variant.toInt(); } diff --git a/src/qtui/qtuimessageprocessor.h b/src/qtui/qtuimessageprocessor.h index 3073c7bf..58af4c86 100644 --- a/src/qtui/qtuimessageprocessor.h +++ b/src/qtui/qtuimessageprocessor.h @@ -26,55 +26,57 @@ #include "abstractmessageprocessor.h" -class QtUiMessageProcessor : public AbstractMessageProcessor { - Q_OBJECT +class QtUiMessageProcessor : public AbstractMessageProcessor +{ + Q_OBJECT public: - enum Mode { - TimerBased, - Concurrent - }; + enum Mode { + TimerBased, + Concurrent + }; - QtUiMessageProcessor(QObject *parent); + QtUiMessageProcessor(QObject *parent); - inline bool isProcessing() const { return _processing; } - inline Mode processMode() const { return _processMode; } + inline bool isProcessing() const { return _processing; } + inline Mode processMode() const { return _processMode; } - void reset(); + void reset(); public slots: - void process(Message &msg); - void process(QList &msgs); + void process(Message &msg); + void process(QList &msgs); private slots: - void processNextMessage(); - void nicksCaseSensitiveChanged(const QVariant &variant); - void highlightListChanged(const QVariant &variant); - void highlightNickChanged(const QVariant &variant); + void processNextMessage(); + void nicksCaseSensitiveChanged(const QVariant &variant); + void highlightListChanged(const QVariant &variant); + void highlightNickChanged(const QVariant &variant); private: - void checkForHighlight(Message &msg); - void startProcessing(); - - QList > _processQueue; - QList _currentBatch; - QTimer _processTimer; - bool _processing; - Mode _processMode; - - struct HighlightRule { - QString name; - bool isEnabled; - Qt::CaseSensitivity caseSensitive; - bool isRegExp; - QString chanName; - inline HighlightRule(const QString &name, bool enabled, Qt::CaseSensitivity cs, bool regExp, const QString &chanName) - : name(name), isEnabled(enabled), caseSensitive(cs), isRegExp(regExp), chanName(chanName) {} - }; - - QList _highlightRules; - NotificationSettings::HighlightNickType _highlightNick; - bool _nicksCaseSensitive; + void checkForHighlight(Message &msg); + void startProcessing(); + + QList > _processQueue; + QList _currentBatch; + QTimer _processTimer; + bool _processing; + Mode _processMode; + + struct HighlightRule { + QString name; + bool isEnabled; + Qt::CaseSensitivity caseSensitive; + bool isRegExp; + QString chanName; + inline HighlightRule(const QString &name, bool enabled, Qt::CaseSensitivity cs, bool regExp, const QString &chanName) + : name(name), isEnabled(enabled), caseSensitive(cs), isRegExp(regExp), chanName(chanName) {} + }; + + QList _highlightRules; + NotificationSettings::HighlightNickType _highlightNick; + bool _nicksCaseSensitive; }; + #endif diff --git a/src/qtui/qtuisettings.cpp b/src/qtui/qtuisettings.cpp index 7a3d9142..dc0a82c5 100644 --- a/src/qtui/qtuisettings.cpp +++ b/src/qtui/qtuisettings.cpp @@ -21,36 +21,44 @@ #include "qtuisettings.h" QtUiSettings::QtUiSettings(const QString &subGroup) - : UiSettings(QString("QtUi/%1").arg(subGroup)) + : UiSettings(QString("QtUi/%1").arg(subGroup)) { } + QtUiSettings::QtUiSettings() - : UiSettings("QtUi") + : UiSettings("QtUi") { } + /***********************************************************************/ QtUiStyleSettings::QtUiStyleSettings(const QString &subGroup) - : UiSettings(QString("QtUiStyle/%1").arg(subGroup)) + : UiSettings(QString("QtUiStyle/%1").arg(subGroup)) { } + QtUiStyleSettings::QtUiStyleSettings() - : UiSettings("QtUiStyle") + : UiSettings("QtUiStyle") { } -/***********************************************************************/ -WarningsSettings::WarningsSettings() : UiSettings("Warnings") { +/***********************************************************************/ +WarningsSettings::WarningsSettings() : UiSettings("Warnings") +{ } -bool WarningsSettings::showWarning(const QString &key) { - return localValue(key, true).toBool(); + +bool WarningsSettings::showWarning(const QString &key) +{ + return localValue(key, true).toBool(); } -void WarningsSettings::setShowWarning(const QString &key, bool show) { - setLocalValue(key, show); + +void WarningsSettings::setShowWarning(const QString &key, bool show) +{ + setLocalValue(key, show); } diff --git a/src/qtui/qtuisettings.h b/src/qtui/qtuisettings.h index 0a4e9cac..eaace7ab 100644 --- a/src/qtui/qtuisettings.h +++ b/src/qtui/qtuisettings.h @@ -25,24 +25,30 @@ #include "uisettings.h" -class QtUiSettings : public UiSettings { +class QtUiSettings : public UiSettings +{ public: - QtUiSettings(const QString &subGroup); - QtUiSettings(); + QtUiSettings(const QString &subGroup); + QtUiSettings(); }; -class QtUiStyleSettings : public UiSettings { + +class QtUiStyleSettings : public UiSettings +{ public: - QtUiStyleSettings(const QString &subGroup); - QtUiStyleSettings(); + QtUiStyleSettings(const QString &subGroup); + QtUiStyleSettings(); }; -class WarningsSettings : public UiSettings { + +class WarningsSettings : public UiSettings +{ public: - WarningsSettings(); + WarningsSettings(); - bool showWarning(const QString &key); - void setShowWarning(const QString &key, bool show); + bool showWarning(const QString &key); + void setShowWarning(const QString &key, bool show); }; + #endif diff --git a/src/qtui/qtuistyle.cpp b/src/qtui/qtuistyle.cpp index cc5fa262..5f7e27fb 100644 --- a/src/qtui/qtuistyle.cpp +++ b/src/qtui/qtuistyle.cpp @@ -24,46 +24,51 @@ #include #include -QtUiStyle::QtUiStyle(QObject *parent) : UiStyle(parent) { - ChatViewSettings s; - s.notify("TimestampFormat", this, SLOT(updateTimestampFormatString())); - updateTimestampFormatString(); +QtUiStyle::QtUiStyle(QObject *parent) : UiStyle(parent) +{ + ChatViewSettings s; + s.notify("TimestampFormat", this, SLOT(updateTimestampFormatString())); + updateTimestampFormatString(); } + QtUiStyle::~QtUiStyle() {} -void QtUiStyle::updateTimestampFormatString() { - ChatViewSettings s; - setTimestampFormatString(s.timestampFormatString()); +void QtUiStyle::updateTimestampFormatString() +{ + ChatViewSettings s; + setTimestampFormatString(s.timestampFormatString()); } -void QtUiStyle::generateSettingsQss() const { - QFile settingsQss(Quassel::configDirPath() + "settings.qss"); - if(!settingsQss.open(QFile::WriteOnly|QFile::Truncate)) { - qWarning() << "Could not open" << settingsQss.fileName() << "for writing!"; - return; - } - QTextStream out(&settingsQss); - out << "// Style settings made in Quassel's configuration dialog\n" - << "// This file is automatically generated, do not edit\n"; +void QtUiStyle::generateSettingsQss() const +{ + QFile settingsQss(Quassel::configDirPath() + "settings.qss"); + if (!settingsQss.open(QFile::WriteOnly|QFile::Truncate)) { + qWarning() << "Could not open" << settingsQss.fileName() << "for writing!"; + return; + } + QTextStream out(&settingsQss); + + out << "// Style settings made in Quassel's configuration dialog\n" + << "// This file is automatically generated, do not edit\n"; - // ChatView - /////////// - QtUiStyleSettings fs("Fonts"); - if(fs.value("UseCustomChatViewFont").toBool()) - out << "\n// ChatView Font\n" - << "ChatLine { " << fontDescription(fs.value("ChatView").value()) << "; }\n"; + // ChatView + /////////// + QtUiStyleSettings fs("Fonts"); + if (fs.value("UseCustomChatViewFont").toBool()) + out << "\n// ChatView Font\n" + << "ChatLine { " << fontDescription(fs.value("ChatView").value()) << "; }\n"; - QtUiStyleSettings s("Colors"); - if(s.value("UseChatViewColors").toBool()) { - out << "\n// Custom ChatView Colors\n" + QtUiStyleSettings s("Colors"); + if (s.value("UseChatViewColors").toBool()) { + out << "\n// Custom ChatView Colors\n" // markerline is special in that it always used to use a gradient, so we keep this behavior even with the new implementation << "Palette { marker-line: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 " << color("MarkerLine", s) << ", stop: 0.1 transparent); }\n" << "ChatView { background: " << color("ChatViewBackground", s) << "; }\n\n" << "ChatLine[label=\"highlight\"] {\n" - << " foreground: " << color("Highlight",s) << ";\n" + << " foreground: " << color("Highlight", s) << ";\n" << " background: " << color("HighlightBackground", s) << ";\n" << "}\n\n" << "ChatLine::timestamp { foreground: " << color("Timestamp", s) << "; }\n\n" @@ -87,74 +92,84 @@ void QtUiStyle::generateSettingsQss() const { << msgTypeQss("netsplit-quit", "CommandMsg", s) << msgTypeQss("invite", "CommandMsg", s) << "\n"; - } - - if(s.value("UseSenderColors").toBool()) { - out << "\n// Sender Colors\n" - << "ChatLine::sender#plain[sender=\"self\"] { foreground: " << color("SenderSelf", s) << "; }\n\n"; - - for(int i = 0; i < 16; i++) - out << senderQss(i, s); - } - - // ItemViews - //////////// - - UiStyleSettings uiFonts("Fonts"); - if(uiFonts.value("UseCustomItemViewFont").toBool()) { - QString fontDesc = fontDescription(uiFonts.value("ItemView").value()); - out << "\n// ItemView Font\n" - << "ChatListItem { " << fontDesc << "; }\n" - << "NickListItem { " << fontDesc << "; }\n\n"; - } - - UiStyleSettings uiColors("Colors"); - if(uiColors.value("UseBufferViewColors").toBool()) { - out << "\n// BufferView Colors\n" - << "ChatListItem { foreground: " << color("DefaultBuffer", uiColors) << "; }\n" - << chatListItemQss("inactive", "InactiveBuffer", uiColors) - << chatListItemQss("channel-event", "ActiveBuffer", uiColors) - << chatListItemQss("unread-message", "UnreadBuffer", uiColors) - << chatListItemQss("highlighted", "HighlightedBuffer", uiColors); - } - - if(uiColors.value("UseNickViewColors").toBool()) { - out << "\n// NickView Colors\n" - << "NickListItem[type=\"category\"] { foreground: " << color("DefaultBuffer", uiColors) << "; }\n" - << "NickListItem[type=\"user\"] { foreground: " << color("OnlineNick", uiColors) << "; }\n" - << "NickListItem[type=\"user\", state=\"away\"] { foreground: " << color("AwayNick", uiColors) << "; }\n"; - } - - settingsQss.close(); + } + + if (s.value("UseSenderColors").toBool()) { + out << "\n// Sender Colors\n" + << "ChatLine::sender#plain[sender=\"self\"] { foreground: " << color("SenderSelf", s) << "; }\n\n"; + + for (int i = 0; i < 16; i++) + out << senderQss(i, s); + } + + // ItemViews + //////////// + + UiStyleSettings uiFonts("Fonts"); + if (uiFonts.value("UseCustomItemViewFont").toBool()) { + QString fontDesc = fontDescription(uiFonts.value("ItemView").value()); + out << "\n// ItemView Font\n" + << "ChatListItem { " << fontDesc << "; }\n" + << "NickListItem { " << fontDesc << "; }\n\n"; + } + + UiStyleSettings uiColors("Colors"); + if (uiColors.value("UseBufferViewColors").toBool()) { + out << "\n// BufferView Colors\n" + << "ChatListItem { foreground: " << color("DefaultBuffer", uiColors) << "; }\n" + << chatListItemQss("inactive", "InactiveBuffer", uiColors) + << chatListItemQss("channel-event", "ActiveBuffer", uiColors) + << chatListItemQss("unread-message", "UnreadBuffer", uiColors) + << chatListItemQss("highlighted", "HighlightedBuffer", uiColors); + } + + if (uiColors.value("UseNickViewColors").toBool()) { + out << "\n// NickView Colors\n" + << "NickListItem[type=\"category\"] { foreground: " << color("DefaultBuffer", uiColors) << "; }\n" + << "NickListItem[type=\"user\"] { foreground: " << color("OnlineNick", uiColors) << "; }\n" + << "NickListItem[type=\"user\", state=\"away\"] { foreground: " << color("AwayNick", uiColors) << "; }\n"; + } + + settingsQss.close(); } -QString QtUiStyle::color(const QString &key, UiSettings &settings) const { - return settings.value(key).value().name(); + +QString QtUiStyle::color(const QString &key, UiSettings &settings) const +{ + return settings.value(key).value().name(); } -QString QtUiStyle::fontDescription(const QFont &font) const { - QString desc = "font: "; - if(font.italic()) - desc += "italic "; - if(font.bold()) - desc += "bold "; - if(!font.italic() && !font.bold()) - desc += "normal "; - desc += QString("%1pt \"%2\"").arg(font.pointSize()).arg(font.family()); - return desc; + +QString QtUiStyle::fontDescription(const QFont &font) const +{ + QString desc = "font: "; + if (font.italic()) + desc += "italic "; + if (font.bold()) + desc += "bold "; + if (!font.italic() && !font.bold()) + desc += "normal "; + desc += QString("%1pt \"%2\"").arg(font.pointSize()).arg(font.family()); + return desc; } -QString QtUiStyle::msgTypeQss(const QString &msgType, const QString &key, UiSettings &settings) const { - return QString("ChatLine#%1 { foreground: %2; }\n").arg(msgType, color(key, settings)); + +QString QtUiStyle::msgTypeQss(const QString &msgType, const QString &key, UiSettings &settings) const +{ + return QString("ChatLine#%1 { foreground: %2; }\n").arg(msgType, color(key, settings)); } -QString QtUiStyle::senderQss(int i, UiSettings &settings) const { - QString dez = QString::number(i); - if(dez.length() == 1) dez.prepend('0'); - return QString("ChatLine::sender#plain[sender=\"0%1\"] { foreground: %2; }\n").arg(QString::number(i, 16), color("Sender"+dez, settings)); +QString QtUiStyle::senderQss(int i, UiSettings &settings) const +{ + QString dez = QString::number(i); + if (dez.length() == 1) dez.prepend('0'); + + return QString("ChatLine::sender#plain[sender=\"0%1\"] { foreground: %2; }\n").arg(QString::number(i, 16), color("Sender"+dez, settings)); } -QString QtUiStyle::chatListItemQss(const QString &state, const QString &key, UiSettings &settings) const { - return QString("ChatListItem[state=\"%1\"] { foreground: %2; }\n").arg(state, color(key, settings)); + +QString QtUiStyle::chatListItemQss(const QString &state, const QString &key, UiSettings &settings) const +{ + return QString("ChatListItem[state=\"%1\"] { foreground: %2; }\n").arg(state, color(key, settings)); } diff --git a/src/qtui/qtuistyle.h b/src/qtui/qtuistyle.h index d57c6791..14920f82 100644 --- a/src/qtui/qtuistyle.h +++ b/src/qtui/qtuistyle.h @@ -24,29 +24,31 @@ #include "uistyle.h" #include "qtuisettings.h" -class QtUiStyle : public UiStyle { - Q_OBJECT +class QtUiStyle : public UiStyle +{ + Q_OBJECT public: - QtUiStyle(QObject *parent = 0); - virtual ~QtUiStyle(); + QtUiStyle(QObject *parent = 0); + virtual ~QtUiStyle(); - virtual inline qreal firstColumnSeparator() const { return 6; } - virtual inline qreal secondColumnSeparator() const { return 6; } + virtual inline qreal firstColumnSeparator() const { return 6; } + virtual inline qreal secondColumnSeparator() const { return 6; } public slots: - void generateSettingsQss() const; + void generateSettingsQss() const; private slots: - void updateTimestampFormatString(); + void updateTimestampFormatString(); private: - QString fontDescription(const QFont &font) const; - QString color(const QString &key, UiSettings &settings) const; + QString fontDescription(const QFont &font) const; + QString color(const QString &key, UiSettings &settings) const; - QString msgTypeQss(const QString &msgType, const QString &key, UiSettings &settings) const; - QString senderQss(int i, UiSettings &settings) const; - QString chatListItemQss(const QString &state, const QString &key, UiSettings &settings) const; + QString msgTypeQss(const QString &msgType, const QString &key, UiSettings &settings) const; + QString senderQss(int i, UiSettings &settings) const; + QString chatListItemQss(const QString &state, const QString &key, UiSettings &settings) const; }; + #endif diff --git a/src/qtui/settingsdlg.cpp b/src/qtui/settingsdlg.cpp index 96ae5fa9..7b26e069 100644 --- a/src/qtui/settingsdlg.cpp +++ b/src/qtui/settingsdlg.cpp @@ -27,184 +27,210 @@ #include "iconloader.h" SettingsDlg::SettingsDlg(QWidget *parent) - : QDialog(parent), + : QDialog(parent), _currentPage(0) { - ui.setupUi(this); - setModal(true); - setAttribute(Qt::WA_DeleteOnClose, true); - setWindowIcon(SmallIcon("configure")); + ui.setupUi(this); + setModal(true); + setAttribute(Qt::WA_DeleteOnClose, true); + setWindowIcon(SmallIcon("configure")); - updateGeometry(); + updateGeometry(); - ui.settingsTree->setRootIsDecorated(false); + ui.settingsTree->setRootIsDecorated(false); - connect(ui.settingsTree, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelected())); - connect(ui.buttonBox, SIGNAL(clicked(QAbstractButton *)), this, SLOT(buttonClicked(QAbstractButton *))); + connect(ui.settingsTree, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelected())); + connect(ui.buttonBox, SIGNAL(clicked(QAbstractButton *)), this, SLOT(buttonClicked(QAbstractButton *))); - connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), SLOT(coreConnectionStateChanged())); + connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), SLOT(coreConnectionStateChanged())); - setButtonStates(); + setButtonStates(); } -void SettingsDlg::coreConnectionStateChanged() { - for(int i = 0; i < ui.settingsTree->topLevelItemCount(); i++) { - QTreeWidgetItem *catItem = ui.settingsTree->topLevelItem(i); - for(int j = 0; j < catItem->childCount(); j++) { - QTreeWidgetItem *item = catItem->child(j); - setItemState(item); + +void SettingsDlg::coreConnectionStateChanged() +{ + for (int i = 0; i < ui.settingsTree->topLevelItemCount(); i++) { + QTreeWidgetItem *catItem = ui.settingsTree->topLevelItem(i); + for (int j = 0; j < catItem->childCount(); j++) { + QTreeWidgetItem *item = catItem->child(j); + setItemState(item); + } + setItemState(catItem); } - setItemState(catItem); - } } -void SettingsDlg::setItemState(QTreeWidgetItem *item) { - SettingsPage *sp = qobject_cast(item->data(0, SettingsPageRole).value()); - Q_ASSERT(sp); - item->setDisabled(!Client::isConnected() && sp->needsCoreConnection()); -} -void SettingsDlg::registerSettingsPage(SettingsPage *sp) { - sp->setParent(ui.settingsStack); - ui.settingsStack->addWidget(sp); - - connect(sp, SIGNAL(changed(bool)), this, SLOT(setButtonStates())); - - QTreeWidgetItem *cat; - QList cats = ui.settingsTree->findItems(sp->category(), Qt::MatchExactly); - if(!cats.count()) { - cat = new QTreeWidgetItem(ui.settingsTree, QStringList(sp->category())); - cat->setExpanded(true); - cat->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); - } else { - cat = cats[0]; - } - - QTreeWidgetItem *item; - if(sp->title().isEmpty()) - item = cat; - else - item = new QTreeWidgetItem(cat, QStringList(sp->title())); - - item->setData(0, SettingsPageRole, QVariant::fromValue(sp)); - ui.settingsTree->setMinimumWidth(ui.settingsTree->header()->sectionSizeHint(0) + 5); - pageIsLoaded[sp] = false; - if(!ui.settingsTree->selectedItems().count()) - ui.settingsTree->setCurrentItem(item); - - setItemState(item); +void SettingsDlg::setItemState(QTreeWidgetItem *item) +{ + SettingsPage *sp = qobject_cast(item->data(0, SettingsPageRole).value()); + Q_ASSERT(sp); + item->setDisabled(!Client::isConnected() && sp->needsCoreConnection()); } -void SettingsDlg::selectPage(SettingsPage *sp) { - if(!sp) { - _currentPage = 0; - ui.settingsStack->setCurrentIndex(0); - ui.pageTitle->setText(tr("Settings")); - return; - } - - if(!pageIsLoaded[sp]) { - sp->load(); - pageIsLoaded[sp] = true; - } - - if(sp != currentPage() && currentPage() != 0 && currentPage()->hasChanged()) { - int ret = QMessageBox::warning(this, tr("Save changes"), - tr("There are unsaved changes on the current configuration page. Would you like to apply your changes now?"), - QMessageBox::Discard|QMessageBox::Save|QMessageBox::Cancel, QMessageBox::Cancel); - if(ret == QMessageBox::Save) { - if(!applyChanges()) sp = currentPage(); - } else if(ret == QMessageBox::Discard) { - undoChanges(); - } else sp = currentPage(); - } - - if(sp != currentPage()) { - if(sp->title().isEmpty()) { - ui.pageTitle->setText(sp->category()); - setWindowTitle(tr("Configure %1").arg(sp->category())); + +void SettingsDlg::registerSettingsPage(SettingsPage *sp) +{ + sp->setParent(ui.settingsStack); + ui.settingsStack->addWidget(sp); + + connect(sp, SIGNAL(changed(bool)), this, SLOT(setButtonStates())); + + QTreeWidgetItem *cat; + QList cats = ui.settingsTree->findItems(sp->category(), Qt::MatchExactly); + if (!cats.count()) { + cat = new QTreeWidgetItem(ui.settingsTree, QStringList(sp->category())); + cat->setExpanded(true); + cat->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); } else { - ui.pageTitle->setText(sp->title()); - setWindowTitle(tr("Configure %1").arg(sp->title())); + cat = cats[0]; } - ui.settingsStack->setCurrentWidget(sp); - _currentPage = sp; - } - setButtonStates(); + QTreeWidgetItem *item; + if (sp->title().isEmpty()) + item = cat; + else + item = new QTreeWidgetItem(cat, QStringList(sp->title())); + + item->setData(0, SettingsPageRole, QVariant::fromValue(sp)); + ui.settingsTree->setMinimumWidth(ui.settingsTree->header()->sectionSizeHint(0) + 5); + pageIsLoaded[sp] = false; + if (!ui.settingsTree->selectedItems().count()) + ui.settingsTree->setCurrentItem(item); + + setItemState(item); } -void SettingsDlg::itemSelected() { - QList items = ui.settingsTree->selectedItems(); - SettingsPage *sp = 0; - if(!items.isEmpty()) { - sp = qobject_cast(items[0]->data(0, SettingsPageRole).value()); - } - selectPage(sp); + +void SettingsDlg::selectPage(SettingsPage *sp) +{ + if (!sp) { + _currentPage = 0; + ui.settingsStack->setCurrentIndex(0); + ui.pageTitle->setText(tr("Settings")); + return; + } + + if (!pageIsLoaded[sp]) { + sp->load(); + pageIsLoaded[sp] = true; + } + + if (sp != currentPage() && currentPage() != 0 && currentPage()->hasChanged()) { + int ret = QMessageBox::warning(this, tr("Save changes"), + tr("There are unsaved changes on the current configuration page. Would you like to apply your changes now?"), + QMessageBox::Discard|QMessageBox::Save|QMessageBox::Cancel, QMessageBox::Cancel); + if (ret == QMessageBox::Save) { + if (!applyChanges()) sp = currentPage(); + } + else if (ret == QMessageBox::Discard) { + undoChanges(); + } + else sp = currentPage(); + } + + if (sp != currentPage()) { + if (sp->title().isEmpty()) { + ui.pageTitle->setText(sp->category()); + setWindowTitle(tr("Configure %1").arg(sp->category())); + } + else { + ui.pageTitle->setText(sp->title()); + setWindowTitle(tr("Configure %1").arg(sp->title())); + } + + ui.settingsStack->setCurrentWidget(sp); + _currentPage = sp; + } + setButtonStates(); } -void SettingsDlg::setButtonStates() { - SettingsPage *sp = currentPage(); - ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(sp && sp->hasChanged()); - ui.buttonBox->button(QDialogButtonBox::Reset)->setEnabled(sp && sp->hasChanged()); - ui.buttonBox->button(QDialogButtonBox::RestoreDefaults)->setEnabled(sp && sp->hasDefaults()); + +void SettingsDlg::itemSelected() +{ + QList items = ui.settingsTree->selectedItems(); + SettingsPage *sp = 0; + if (!items.isEmpty()) { + sp = qobject_cast(items[0]->data(0, SettingsPageRole).value()); + } + selectPage(sp); +} + + +void SettingsDlg::setButtonStates() +{ + SettingsPage *sp = currentPage(); + ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(sp && sp->hasChanged()); + ui.buttonBox->button(QDialogButtonBox::Reset)->setEnabled(sp && sp->hasChanged()); + ui.buttonBox->button(QDialogButtonBox::RestoreDefaults)->setEnabled(sp && sp->hasDefaults()); } -void SettingsDlg::buttonClicked(QAbstractButton *button) { - switch(ui.buttonBox->standardButton(button)) { + +void SettingsDlg::buttonClicked(QAbstractButton *button) +{ + switch (ui.buttonBox->standardButton(button)) { case QDialogButtonBox::Ok: - if(currentPage() && currentPage()->hasChanged()) { - if(applyChanges()) accept(); - } else accept(); - break; + if (currentPage() && currentPage()->hasChanged()) { + if (applyChanges()) accept(); + } + else accept(); + break; case QDialogButtonBox::Apply: - applyChanges(); - break; + applyChanges(); + break; case QDialogButtonBox::Cancel: - undoChanges(); - reject(); - break; + undoChanges(); + reject(); + break; case QDialogButtonBox::Reset: - reload(); - break; + reload(); + break; case QDialogButtonBox::RestoreDefaults: - loadDefaults(); - break; + loadDefaults(); + break; default: - break; - } + break; + } } -bool SettingsDlg::applyChanges() { - if(!currentPage()) return false; - if(currentPage()->aboutToSave()) { - currentPage()->save(); - return true; - } - return false; + +bool SettingsDlg::applyChanges() +{ + if (!currentPage()) return false; + if (currentPage()->aboutToSave()) { + currentPage()->save(); + return true; + } + return false; } -void SettingsDlg::undoChanges() { - if(currentPage()) { - currentPage()->load(); - } + +void SettingsDlg::undoChanges() +{ + if (currentPage()) { + currentPage()->load(); + } } -void SettingsDlg::reload() { - if(!currentPage()) return; - int ret = QMessageBox::question(this, tr("Reload Settings"), tr("Do you like to reload the settings, undoing your changes on this page?"), - QMessageBox::Yes|QMessageBox::No, QMessageBox::No); - if(ret == QMessageBox::Yes) { - currentPage()->load(); - } + +void SettingsDlg::reload() +{ + if (!currentPage()) return; + int ret = QMessageBox::question(this, tr("Reload Settings"), tr("Do you like to reload the settings, undoing your changes on this page?"), + QMessageBox::Yes|QMessageBox::No, QMessageBox::No); + if (ret == QMessageBox::Yes) { + currentPage()->load(); + } } -void SettingsDlg::loadDefaults() { - if(!currentPage()) return; - int ret = QMessageBox::question(this, tr("Restore Defaults"), tr("Do you like to restore the default values for this page?"), - QMessageBox::RestoreDefaults|QMessageBox::Cancel, QMessageBox::Cancel); - if(ret == QMessageBox::RestoreDefaults) { - currentPage()->defaults(); - } + +void SettingsDlg::loadDefaults() +{ + if (!currentPage()) return; + int ret = QMessageBox::question(this, tr("Restore Defaults"), tr("Do you like to restore the default values for this page?"), + QMessageBox::RestoreDefaults|QMessageBox::Cancel, QMessageBox::Cancel); + if (ret == QMessageBox::RestoreDefaults) { + currentPage()->defaults(); + } } diff --git a/src/qtui/settingsdlg.h b/src/qtui/settingsdlg.h index b45cbcb9..521647e3 100644 --- a/src/qtui/settingsdlg.h +++ b/src/qtui/settingsdlg.h @@ -27,39 +27,40 @@ #include "settingspage.h" -class SettingsDlg : public QDialog { - Q_OBJECT +class SettingsDlg : public QDialog +{ + Q_OBJECT public: - SettingsDlg(QWidget *parent = 0); - void registerSettingsPage(SettingsPage *); - void unregisterSettingsPage(SettingsPage *); + SettingsDlg(QWidget *parent = 0); + void registerSettingsPage(SettingsPage *); + void unregisterSettingsPage(SettingsPage *); - inline SettingsPage *currentPage() const { return _currentPage; } + inline SettingsPage *currentPage() const { return _currentPage; } public slots: - void selectPage(SettingsPage *sp); // const QString &category, const QString &title); + void selectPage(SettingsPage *sp); // const QString &category, const QString &title); private slots: - void coreConnectionStateChanged(); - void itemSelected(); - void buttonClicked(QAbstractButton *); - bool applyChanges(); - void undoChanges(); - void reload(); - void loadDefaults(); - void setButtonStates(); - void setItemState(QTreeWidgetItem *); + void coreConnectionStateChanged(); + void itemSelected(); + void buttonClicked(QAbstractButton *); + bool applyChanges(); + void undoChanges(); + void reload(); + void loadDefaults(); + void setButtonStates(); + void setItemState(QTreeWidgetItem *); private: - Ui::SettingsDlg ui; + Ui::SettingsDlg ui; - SettingsPage *_currentPage; - QHash pageIsLoaded; + SettingsPage *_currentPage; + QHash pageIsLoaded; - enum { - SettingsPageRole = Qt::UserRole - }; + enum { + SettingsPageRole = Qt::UserRole + }; }; diff --git a/src/qtui/settingspagedlg.cpp b/src/qtui/settingspagedlg.cpp index 0c070a81..f1b0f206 100644 --- a/src/qtui/settingspagedlg.cpp +++ b/src/qtui/settingspagedlg.cpp @@ -26,96 +26,111 @@ #include "iconloader.h" SettingsPageDlg::SettingsPageDlg(SettingsPage *page, QWidget *parent) - : QDialog(parent) + : QDialog(parent) { - ui.setupUi(this); - _currentPage = page; - page->setParent(this); + ui.setupUi(this); + _currentPage = page; + page->setParent(this); - // make it look more native under Mac OS X: - setWindowFlags(Qt::Sheet); + // make it look more native under Mac OS X: + setWindowFlags(Qt::Sheet); - ui.pageTitle->setText(page->title()); - setWindowTitle(tr("Configure %1").arg(page->title())); - setWindowIcon(SmallIcon("configure")); + ui.pageTitle->setText(page->title()); + setWindowTitle(tr("Configure %1").arg(page->title())); + setWindowIcon(SmallIcon("configure")); - // make the scrollarea behave sanely - ui.settingsFrame->setWidgetResizable(true); - ui.settingsFrame->setWidget(page); + // make the scrollarea behave sanely + ui.settingsFrame->setWidgetResizable(true); + ui.settingsFrame->setWidget(page); - updateGeometry(); + updateGeometry(); - connect(page, SIGNAL(changed(bool)), this, SLOT(setButtonStates())); - connect(ui.buttonBox, SIGNAL(clicked(QAbstractButton *)), this, SLOT(buttonClicked(QAbstractButton *))); - page->load(); - setButtonStates(); + connect(page, SIGNAL(changed(bool)), this, SLOT(setButtonStates())); + connect(ui.buttonBox, SIGNAL(clicked(QAbstractButton *)), this, SLOT(buttonClicked(QAbstractButton *))); + page->load(); + setButtonStates(); } -SettingsPage *SettingsPageDlg::currentPage() const { - return _currentPage; + +SettingsPage *SettingsPageDlg::currentPage() const +{ + return _currentPage; } -void SettingsPageDlg::setButtonStates() { - SettingsPage *sp = currentPage(); - ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(sp && sp->hasChanged()); - ui.buttonBox->button(QDialogButtonBox::Reset)->setEnabled(sp && sp->hasChanged()); - ui.buttonBox->button(QDialogButtonBox::RestoreDefaults)->setEnabled(sp && sp->hasDefaults()); + +void SettingsPageDlg::setButtonStates() +{ + SettingsPage *sp = currentPage(); + ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(sp && sp->hasChanged()); + ui.buttonBox->button(QDialogButtonBox::Reset)->setEnabled(sp && sp->hasChanged()); + ui.buttonBox->button(QDialogButtonBox::RestoreDefaults)->setEnabled(sp && sp->hasDefaults()); } -void SettingsPageDlg::buttonClicked(QAbstractButton *button) { - switch(ui.buttonBox->standardButton(button)) { + +void SettingsPageDlg::buttonClicked(QAbstractButton *button) +{ + switch (ui.buttonBox->standardButton(button)) { case QDialogButtonBox::Ok: - if(currentPage() && currentPage()->hasChanged()) { - if(applyChanges()) accept(); - } else accept(); - break; + if (currentPage() && currentPage()->hasChanged()) { + if (applyChanges()) accept(); + } + else accept(); + break; case QDialogButtonBox::Apply: - applyChanges(); - break; + applyChanges(); + break; case QDialogButtonBox::Cancel: - undoChanges(); - reject(); - break; + undoChanges(); + reject(); + break; case QDialogButtonBox::Reset: - reload(); - break; + reload(); + break; case QDialogButtonBox::RestoreDefaults: - loadDefaults(); - break; + loadDefaults(); + break; default: - break; - } + break; + } } -bool SettingsPageDlg::applyChanges() { - if(!currentPage()) return false; - if(currentPage()->aboutToSave()) { - currentPage()->save(); - return true; - } - return false; + +bool SettingsPageDlg::applyChanges() +{ + if (!currentPage()) return false; + if (currentPage()->aboutToSave()) { + currentPage()->save(); + return true; + } + return false; } -void SettingsPageDlg::undoChanges() { - if(currentPage()) { - currentPage()->load(); - } + +void SettingsPageDlg::undoChanges() +{ + if (currentPage()) { + currentPage()->load(); + } } -void SettingsPageDlg::reload() { - if(!currentPage()) return; - int ret = QMessageBox::question(this, tr("Reload Settings"), tr("Do you like to reload the settings, undoing your changes on this page?"), - QMessageBox::Yes|QMessageBox::No, QMessageBox::No); - if(ret == QMessageBox::Yes) { - currentPage()->load(); - } + +void SettingsPageDlg::reload() +{ + if (!currentPage()) return; + int ret = QMessageBox::question(this, tr("Reload Settings"), tr("Do you like to reload the settings, undoing your changes on this page?"), + QMessageBox::Yes|QMessageBox::No, QMessageBox::No); + if (ret == QMessageBox::Yes) { + currentPage()->load(); + } } -void SettingsPageDlg::loadDefaults() { - if(!currentPage()) return; - int ret = QMessageBox::question(this, tr("Restore Defaults"), tr("Do you like to restore the default values for this page?"), - QMessageBox::RestoreDefaults|QMessageBox::Cancel, QMessageBox::Cancel); - if(ret == QMessageBox::RestoreDefaults) { - currentPage()->defaults(); - } + +void SettingsPageDlg::loadDefaults() +{ + if (!currentPage()) return; + int ret = QMessageBox::question(this, tr("Restore Defaults"), tr("Do you like to restore the default values for this page?"), + QMessageBox::RestoreDefaults|QMessageBox::Cancel, QMessageBox::Cancel); + if (ret == QMessageBox::RestoreDefaults) { + currentPage()->defaults(); + } } diff --git a/src/qtui/settingspagedlg.h b/src/qtui/settingspagedlg.h index 73cec989..dbcfbffb 100644 --- a/src/qtui/settingspagedlg.h +++ b/src/qtui/settingspagedlg.h @@ -27,14 +27,15 @@ #include "settingspage.h" -class SettingsPageDlg : public QDialog { - Q_OBJECT - public: - SettingsPageDlg(SettingsPage * page, QWidget *parent = 0); +class SettingsPageDlg : public QDialog +{ + Q_OBJECT +public: + SettingsPageDlg(SettingsPage *page, QWidget *parent = 0); SettingsPage *currentPage() const; - private slots: +private slots: void buttonClicked(QAbstractButton *); bool applyChanges(); void undoChanges(); @@ -42,11 +43,11 @@ class SettingsPageDlg : public QDialog { void loadDefaults(); void setButtonStates(); - private: +private: Ui::SettingsPageDlg ui; SettingsPage *_currentPage; - }; + #endif diff --git a/src/qtui/settingspages/aliasesmodel.cpp b/src/qtui/settingspages/aliasesmodel.cpp index 4d00d375..acc0b2ad 100644 --- a/src/qtui/settingspages/aliasesmodel.cpp +++ b/src/qtui/settingspages/aliasesmodel.cpp @@ -27,222 +27,254 @@ #include "signalproxy.h" AliasesModel::AliasesModel(QObject *parent) - : QAbstractItemModel(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())); + // 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); +} - if(Client::isConnected()) - clientConnected(); - else - emit modelReady(false); + +QVariant AliasesModel::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 tr("The shortcut for the alias
" + "It can be used as a regular slash command.

" + "Example: \"foo\" can be used per /foo"); + case 1: + return tr("The string the shortcut will be expanded to
" + "special variables:
" + " - $i represents the i'th parameter.
" + " - $i..j represents the i'th to j'th parameter separated by spaces.
" + " - $i.. represents all parameters from i on separated by spaces.
" + " - $i:hostname represents the hostname of the user identified by the i'th parameter or a * if unknown.
" + " - $0 the whole string.
" + " - $nick your current nickname
" + " - $channel the name of the selected channel

" + "Multiple commands can be separated with semicolons

" + "Example: \"Test $1; Test $2; Test All $0\" will be expanded to three separate messages \"Test 1\", \"Test 2\" and \"Test All 1 2 3\" when called like /test 1 2 3"); + default: + return QVariant(); + } + case Qt::DisplayRole: + case Qt::EditRole: + switch (index.column()) { + case 0: + return aliasManager()[index.row()].name; + case 1: + return aliasManager()[index.row()].expansion; + default: + return QVariant(); + } + default: + return QVariant(); + } } -QVariant AliasesModel::data(const QModelIndex &index, int role) const { - if(!_modelReady) - return QVariant(); - if(!index.isValid() || index.row() >= rowCount() || index.column() >= columnCount()) - return QVariant(); +bool AliasesModel::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; + + QString newValue = value.toString(); + if (newValue.isEmpty()) + return false; - switch(role) { - case Qt::ToolTipRole: - switch(index.column()) { + switch (index.column()) { case 0: - return tr("The shortcut for the alias
" - "It can be used as a regular slash command.

" - "Example: \"foo\" can be used per /foo"); + if (aliasManager().contains(newValue)) { + return false; + } + else { + cloneAliasManager()[index.row()].name = newValue; + return true; + } case 1: - return tr("The string the shortcut will be expanded to
" - "special variables:
" - " - $i represents the i'th parameter.
" - " - $i..j represents the i'th to j'th parameter separated by spaces.
" - " - $i.. represents all parameters from i on separated by spaces.
" - " - $i:hostname represents the hostname of the user identified by the i'th parameter or a * if unknown.
" - " - $0 the whole string.
" - " - $nick your current nickname
" - " - $channel the name of the selected channel

" - "Multiple commands can be separated with semicolons

" - "Example: \"Test $1; Test $2; Test All $0\" will be expanded to three separate messages \"Test 1\", \"Test 2\" and \"Test All 1 2 3\" when called like /test 1 2 3"); + cloneAliasManager()[index.row()].expansion = newValue; + return true; default: - return QVariant(); + return false; } - case Qt::DisplayRole: - case Qt::EditRole: - switch(index.column()) { - case 0: - return aliasManager()[index.row()].name; - case 1: - return aliasManager()[index.row()].expansion; - default: - return QVariant(); +} + + +void AliasesModel::newAlias() +{ + QString newName("alias"); + int i = 0; + AliasManager &manager = cloneAliasManager(); + while (manager.contains(newName)) { + i++; + newName = QString("alias%1").arg(i); } - default: - return QVariant(); - } + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + manager.addAlias(newName, "Expansion"); + endInsertRows(); } -bool AliasesModel::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; +void AliasesModel::loadDefaults() +{ + if (!_modelReady) + return; - QString newValue = value.toString(); - if(newValue.isEmpty()) - return false; + AliasManager &manager = cloneAliasManager(); - switch(index.column()) { - case 0: - if(aliasManager().contains(newValue)) { - return false; - } else { - cloneAliasManager()[index.row()].name = newValue; - return true; + if (!manager.isEmpty()) { + beginRemoveRows(QModelIndex(), 0, rowCount() - 1); + for (int i = rowCount() - 1; i >= 0; i--) + manager.removeAt(i); + endRemoveRows(); } - case 1: - cloneAliasManager()[index.row()].expansion = newValue; - return true; - default: - return false; - } -} - -void AliasesModel::newAlias() { - QString newName("alias"); - int i = 0; - AliasManager &manager = cloneAliasManager(); - while(manager.contains(newName)) { - i++; - newName = QString("alias%1").arg(i); - } - beginInsertRows(QModelIndex(), rowCount(), rowCount()); - manager.addAlias(newName, "Expansion"); - endInsertRows(); -} - -void AliasesModel::loadDefaults() { - if(!_modelReady) - return; - - AliasManager &manager = cloneAliasManager(); - - if(!manager.isEmpty()) { - beginRemoveRows(QModelIndex(), 0, rowCount() - 1); - for(int i = rowCount() - 1; i >= 0; i--) - manager.removeAt(i); - endRemoveRows(); - } - AliasManager::AliasList defaults = AliasManager::defaults(); - beginInsertRows(QModelIndex(), 0, defaults.count() - 1); - foreach(AliasManager::Alias alias, defaults) { - manager.addAlias(alias.name, alias.expansion); - } - endInsertRows(); + AliasManager::AliasList defaults = AliasManager::defaults(); + beginInsertRows(QModelIndex(), 0, defaults.count() - 1); + foreach(AliasManager::Alias alias, defaults) { + manager.addAlias(alias.name, alias.expansion); + } + endInsertRows(); } -void AliasesModel::removeAlias(int index) { - if(index < 0 || index >= rowCount()) - return; - AliasManager &manager = cloneAliasManager(); - beginRemoveRows(QModelIndex(), index, index); - manager.removeAt(index); - endRemoveRows(); +void AliasesModel::removeAlias(int index) +{ + if (index < 0 || index >= rowCount()) + return; + + AliasManager &manager = cloneAliasManager(); + beginRemoveRows(QModelIndex(), index, index); + manager.removeAt(index); + endRemoveRows(); } -Qt::ItemFlags AliasesModel::flags(const QModelIndex &index) const { - if(!index.isValid()) { - return Qt::ItemIsDropEnabled; - } else { - return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable; - } + +Qt::ItemFlags AliasesModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) { + return Qt::ItemIsDropEnabled; + } + else { + return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable; + } } -QVariant AliasesModel::headerData(int section, Qt::Orientation orientation, int role) const { - QStringList header; - header << tr("Alias") - << tr("Expansion"); +QVariant AliasesModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + QStringList header; + header << tr("Alias") + << tr("Expansion"); - if(orientation == Qt::Horizontal && role == Qt::DisplayRole) - return header[section]; + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) + return header[section]; - return QVariant(); + return QVariant(); } -QModelIndex AliasesModel::index(int row, int column, const QModelIndex &parent) const { - Q_UNUSED(parent); - if(row >= rowCount() || column >= columnCount()) - return QModelIndex(); - return createIndex(row, column); +QModelIndex AliasesModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + if (row >= rowCount() || column >= columnCount()) + return QModelIndex(); + + return createIndex(row, column); } -const AliasManager &AliasesModel::aliasManager() const { - if(_configChanged) - return _clonedAliasManager; - else - return *Client::aliasManager(); +const AliasManager &AliasesModel::aliasManager() const +{ + if (_configChanged) + return _clonedAliasManager; + else + return *Client::aliasManager(); } -AliasManager &AliasesModel::aliasManager() { - if(_configChanged) - return _clonedAliasManager; - else - return *Client::aliasManager(); + +AliasManager &AliasesModel::aliasManager() +{ + if (_configChanged) + return _clonedAliasManager; + else + return *Client::aliasManager(); } -AliasManager &AliasesModel::cloneAliasManager() { - if(!_configChanged) { - _clonedAliasManager = *Client::aliasManager(); - _configChanged = true; - emit configChanged(true); - } - return _clonedAliasManager; + +AliasManager &AliasesModel::cloneAliasManager() +{ + if (!_configChanged) { + _clonedAliasManager = *Client::aliasManager(); + _configChanged = true; + emit configChanged(true); + } + return _clonedAliasManager; } -void AliasesModel::revert() { - if(!_configChanged) - return; - _configChanged = false; - emit configChanged(false); - reset(); +void AliasesModel::revert() +{ + if (!_configChanged) + return; + + _configChanged = false; + emit configChanged(false); + reset(); } -void AliasesModel::commit() { - if(!_configChanged) - return; - Client::aliasManager()->requestUpdate(_clonedAliasManager.toVariantMap()); - revert(); +void AliasesModel::commit() +{ + if (!_configChanged) + return; + + Client::aliasManager()->requestUpdate(_clonedAliasManager.toVariantMap()); + revert(); } -void AliasesModel::initDone() { - _modelReady = true; - reset(); - emit modelReady(true); + +void AliasesModel::initDone() +{ + _modelReady = true; + reset(); + emit modelReady(true); } -void AliasesModel::clientConnected() { - connect(Client::aliasManager(), SIGNAL(updated()), SLOT(revert())); - if(Client::aliasManager()->isInitialized()) - initDone(); - else - connect(Client::aliasManager(), SIGNAL(initDone()), SLOT(initDone())); + +void AliasesModel::clientConnected() +{ + connect(Client::aliasManager(), SIGNAL(updated()), SLOT(revert())); + if (Client::aliasManager()->isInitialized()) + initDone(); + else + connect(Client::aliasManager(), SIGNAL(initDone()), SLOT(initDone())); } -void AliasesModel::clientDisconnected() { - // clear - _clonedAliasManager = ClientAliasManager(); - _modelReady = false; - reset(); - emit modelReady(false); + +void AliasesModel::clientDisconnected() +{ + // clear + _clonedAliasManager = ClientAliasManager(); + _modelReady = false; + reset(); + emit modelReady(false); } diff --git a/src/qtui/settingspages/aliasesmodel.h b/src/qtui/settingspages/aliasesmodel.h index 74a0cfd6..6df43538 100644 --- a/src/qtui/settingspages/aliasesmodel.h +++ b/src/qtui/settingspages/aliasesmodel.h @@ -26,65 +26,70 @@ #include "clientaliasmanager.h" -class AliasesModel : public QAbstractItemModel { - Q_OBJECT +class AliasesModel : public QAbstractItemModel +{ + Q_OBJECT public: - AliasesModel(QObject *parent = 0); + AliasesModel(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 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; + virtual Qt::ItemFlags flags(const QModelIndex &index) const; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; - inline QModelIndex parent(const QModelIndex &) const { return QModelIndex(); } + 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 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; } + inline bool configChanged() const { return _configChanged; } + inline bool isReady() const { return _modelReady; } public slots: - void newAlias(); - void loadDefaults(); - void removeAlias(int index); - void revert(); - void commit(); + void newAlias(); + void loadDefaults(); + void removeAlias(int index); + void revert(); + void commit(); signals: - void configChanged(bool); - void modelReady(bool); + void configChanged(bool); + void modelReady(bool); private: - ClientAliasManager _clonedAliasManager; - bool _configChanged; - bool _modelReady; + ClientAliasManager _clonedAliasManager; + bool _configChanged; + bool _modelReady; - const AliasManager &aliasManager() const; - AliasManager &aliasManager(); - AliasManager &cloneAliasManager(); + const AliasManager &aliasManager() const; + AliasManager &aliasManager(); + AliasManager &cloneAliasManager(); private slots: - void clientConnected(); - void clientDisconnected(); - void initDone(); + void clientConnected(); + void clientDisconnected(); + void initDone(); }; + // Inlines -int AliasesModel::rowCount(const QModelIndex &parent) const { - Q_UNUSED(parent); - return isReady() ? aliasManager().count() : 0; +int AliasesModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return isReady() ? aliasManager().count() : 0; } -int AliasesModel::columnCount(const QModelIndex &parent) const { - Q_UNUSED(parent); - return isReady() ? 2 : 0; + +int AliasesModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return isReady() ? 2 : 0; } - + #endif //ALIASESMODEL_H diff --git a/src/qtui/settingspages/aliasessettingspage.cpp b/src/qtui/settingspages/aliasessettingspage.cpp index 2a7feaee..750816c4 100644 --- a/src/qtui/settingspages/aliasessettingspage.cpp +++ b/src/qtui/settingspages/aliasessettingspage.cpp @@ -26,52 +26,62 @@ #include "iconloader.h" AliasesSettingsPage::AliasesSettingsPage(QWidget *parent) - : SettingsPage(tr("IRC"), tr("Aliases"), parent) + : SettingsPage(tr("IRC"), tr("Aliases"), parent) { - ui.setupUi(this); - ui.newAliasButton->setIcon(SmallIcon("list-add")); - ui.deleteAliasButton->setIcon(SmallIcon("edit-delete")); - - ui.aliasesView->setSelectionBehavior(QAbstractItemView::SelectRows); - ui.aliasesView->setSelectionMode(QAbstractItemView::SingleSelection); - ui.aliasesView->setAlternatingRowColors(true); - ui.aliasesView->setTabKeyNavigation(false); - ui.aliasesView->setModel(&_aliasesModel); - // ui.aliasesView->setSortingEnabled(true); - ui.aliasesView->verticalHeader()->hide(); - ui.aliasesView->horizontalHeader()->setStretchLastSection(true); - - connect(ui.newAliasButton, SIGNAL(clicked()), &_aliasesModel, SLOT(newAlias())); - connect(ui.deleteAliasButton, SIGNAL(clicked()), this, SLOT(deleteSelectedAlias())); - connect(&_aliasesModel, SIGNAL(configChanged(bool)), this, SLOT(setChangedState(bool))); - connect(&_aliasesModel, SIGNAL(modelReady(bool)), this, SLOT(enableDialog(bool))); - - enableDialog(_aliasesModel.isReady()); + ui.setupUi(this); + ui.newAliasButton->setIcon(SmallIcon("list-add")); + ui.deleteAliasButton->setIcon(SmallIcon("edit-delete")); + + ui.aliasesView->setSelectionBehavior(QAbstractItemView::SelectRows); + ui.aliasesView->setSelectionMode(QAbstractItemView::SingleSelection); + ui.aliasesView->setAlternatingRowColors(true); + ui.aliasesView->setTabKeyNavigation(false); + ui.aliasesView->setModel(&_aliasesModel); + // ui.aliasesView->setSortingEnabled(true); + ui.aliasesView->verticalHeader()->hide(); + ui.aliasesView->horizontalHeader()->setStretchLastSection(true); + + connect(ui.newAliasButton, SIGNAL(clicked()), &_aliasesModel, SLOT(newAlias())); + connect(ui.deleteAliasButton, SIGNAL(clicked()), this, SLOT(deleteSelectedAlias())); + connect(&_aliasesModel, SIGNAL(configChanged(bool)), this, SLOT(setChangedState(bool))); + connect(&_aliasesModel, SIGNAL(modelReady(bool)), this, SLOT(enableDialog(bool))); + + enableDialog(_aliasesModel.isReady()); } -void AliasesSettingsPage::load() { - if(_aliasesModel.configChanged()) - _aliasesModel.revert(); + +void AliasesSettingsPage::load() +{ + if (_aliasesModel.configChanged()) + _aliasesModel.revert(); } -void AliasesSettingsPage::defaults() { - _aliasesModel.loadDefaults(); + +void AliasesSettingsPage::defaults() +{ + _aliasesModel.loadDefaults(); } -void AliasesSettingsPage::save() { - if(_aliasesModel.configChanged()) - _aliasesModel.commit(); + +void AliasesSettingsPage::save() +{ + if (_aliasesModel.configChanged()) + _aliasesModel.commit(); } -void AliasesSettingsPage::enableDialog(bool enabled) { - ui.newAliasButton->setEnabled(enabled); - ui.deleteAliasButton->setEnabled(enabled); - setEnabled(enabled); + +void AliasesSettingsPage::enableDialog(bool enabled) +{ + ui.newAliasButton->setEnabled(enabled); + ui.deleteAliasButton->setEnabled(enabled); + setEnabled(enabled); } -void AliasesSettingsPage::deleteSelectedAlias() { - if(!ui.aliasesView->selectionModel()->hasSelection()) - return; - _aliasesModel.removeAlias(ui.aliasesView->selectionModel()->selectedIndexes()[0].row()); +void AliasesSettingsPage::deleteSelectedAlias() +{ + if (!ui.aliasesView->selectionModel()->hasSelection()) + return; + + _aliasesModel.removeAlias(ui.aliasesView->selectionModel()->selectedIndexes()[0].row()); } diff --git a/src/qtui/settingspages/aliasessettingspage.h b/src/qtui/settingspages/aliasessettingspage.h index d6aea9d5..a76deaf7 100644 --- a/src/qtui/settingspages/aliasessettingspage.h +++ b/src/qtui/settingspages/aliasessettingspage.h @@ -26,28 +26,30 @@ #include "aliasesmodel.h" -class AliasesSettingsPage : public SettingsPage { - Q_OBJECT +class AliasesSettingsPage : public SettingsPage +{ + Q_OBJECT public: - AliasesSettingsPage(QWidget *parent = 0); + AliasesSettingsPage(QWidget *parent = 0); - virtual inline bool hasDefaults() const { return true; } - virtual inline bool needsCoreConnection() const { return true; } + virtual inline bool hasDefaults() const { return true; } + virtual inline bool needsCoreConnection() const { return true; } public slots: - void save(); - void load(); - void defaults(); + void save(); + void load(); + void defaults(); private slots: - void enableDialog(bool); - void deleteSelectedAlias(); + void enableDialog(bool); + void deleteSelectedAlias(); private: - Ui::AliasesSettingsPage ui; + Ui::AliasesSettingsPage ui; - AliasesModel _aliasesModel; + AliasesModel _aliasesModel; }; + #endif //ALIASESSETTINGSPAGE_H diff --git a/src/qtui/settingspages/appearancesettingspage.cpp b/src/qtui/settingspages/appearancesettingspage.cpp index 0795e911..692d8ade 100644 --- a/src/qtui/settingspages/appearancesettingspage.cpp +++ b/src/qtui/settingspages/appearancesettingspage.cpp @@ -32,220 +32,241 @@ #include AppearanceSettingsPage::AppearanceSettingsPage(QWidget *parent) - : SettingsPage(tr("Interface"), QString(), parent) + : SettingsPage(tr("Interface"), QString(), parent) { - ui.setupUi(this); + ui.setupUi(this); #ifdef Q_WS_MAC - ui.minimizeOnClose->hide(); + ui.minimizeOnClose->hide(); #endif #ifdef QT_NO_SYSTEMTRAYICON - ui.useSystemTrayIcon->hide(); + ui.useSystemTrayIcon->hide(); #endif - initAutoWidgets(); - initStyleComboBox(); - initLanguageComboBox(); + initAutoWidgets(); + initStyleComboBox(); + initLanguageComboBox(); - foreach(QComboBox *comboBox, findChildren()) { - connect(comboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(widgetHasChanged())); - } - foreach(QCheckBox *checkBox, findChildren()) { - connect(checkBox, SIGNAL(clicked()), this, SLOT(widgetHasChanged())); - } + foreach(QComboBox *comboBox, findChildren()) { + connect(comboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(widgetHasChanged())); + } + foreach(QCheckBox *checkBox, findChildren()) { + connect(checkBox, SIGNAL(clicked()), this, SLOT(widgetHasChanged())); + } - connect(ui.chooseStyleSheet, SIGNAL(clicked()), SLOT(chooseStyleSheet())); + connect(ui.chooseStyleSheet, SIGNAL(clicked()), SLOT(chooseStyleSheet())); - connect(ui.userNoticesInDefaultBuffer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.userNoticesInStatusBuffer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.userNoticesInCurrentBuffer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.userNoticesInDefaultBuffer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.userNoticesInStatusBuffer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.userNoticesInCurrentBuffer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.serverNoticesInDefaultBuffer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.serverNoticesInStatusBuffer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.serverNoticesInCurrentBuffer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.serverNoticesInDefaultBuffer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.serverNoticesInStatusBuffer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.serverNoticesInCurrentBuffer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.errorMsgsInDefaultBuffer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.errorMsgsInStatusBuffer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.errorMsgsInCurrentBuffer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.errorMsgsInDefaultBuffer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.errorMsgsInStatusBuffer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.errorMsgsInCurrentBuffer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); } -void AppearanceSettingsPage::initStyleComboBox() { - QStringList styleList = QStyleFactory::keys(); - ui.styleComboBox->addItem(tr("")); - foreach(QString style, styleList) { - ui.styleComboBox->addItem(style); - } -} -void AppearanceSettingsPage::initLanguageComboBox() { - QDir i18nDir(Quassel::translationDirPath(), "*.qm"); - - QRegExp rx("(qt_)?([a-zA-Z_]+)\\.qm"); - foreach(QString translationFile, i18nDir.entryList()) { - if(!rx.exactMatch(translationFile)) - continue; - if(!rx.cap(1).isEmpty()) - continue; - QLocale locale(rx.cap(2)); - _locales[QLocale::languageToString(locale.language())] = locale; - } - foreach(QString language, _locales.keys()) { - ui.languageComboBox->addItem(language); - } +void AppearanceSettingsPage::initStyleComboBox() +{ + QStringList styleList = QStyleFactory::keys(); + ui.styleComboBox->addItem(tr("")); + foreach(QString style, styleList) { + ui.styleComboBox->addItem(style); + } } -void AppearanceSettingsPage::defaults() { - ui.styleComboBox->setCurrentIndex(0); - ui.languageComboBox->setCurrentIndex(1); - SettingsPage::defaults(); - widgetHasChanged(); +void AppearanceSettingsPage::initLanguageComboBox() +{ + QDir i18nDir(Quassel::translationDirPath(), "*.qm"); + + QRegExp rx("(qt_)?([a-zA-Z_]+)\\.qm"); + foreach(QString translationFile, i18nDir.entryList()) { + if (!rx.exactMatch(translationFile)) + continue; + if (!rx.cap(1).isEmpty()) + continue; + QLocale locale(rx.cap(2)); + _locales[QLocale::languageToString(locale.language())] = locale; + } + foreach(QString language, _locales.keys()) { + ui.languageComboBox->addItem(language); + } } -void AppearanceSettingsPage::load() { - QtUiSettings uiSettings; - // Gui Style - QString style = uiSettings.value("Style", QString("")).toString(); - if(style.isEmpty()) { +void AppearanceSettingsPage::defaults() +{ ui.styleComboBox->setCurrentIndex(0); - } else { - ui.styleComboBox->setCurrentIndex(ui.styleComboBox->findText(style, Qt::MatchExactly)); - } - ui.styleComboBox->setProperty("storedValue", ui.styleComboBox->currentIndex()); - - // Language - QLocale locale = uiSettings.value("Locale", QLocale::system()).value(); - if(locale == QLocale::system()) ui.languageComboBox->setCurrentIndex(1); - else if(locale.language() == QLocale::C) // we use C for "untranslated" - ui.languageComboBox->setCurrentIndex(0); - else - ui.languageComboBox->setCurrentIndex(ui.languageComboBox->findText(QLocale::languageToString(locale.language()), Qt::MatchExactly)); - ui.languageComboBox->setProperty("storedValue", ui.languageComboBox->currentIndex()); - Quassel::loadTranslation(selectedLocale()); - - // bufferSettings: - BufferSettings bufferSettings; - int redirectTarget = bufferSettings.userNoticesTarget(); - SettingsPage::load(ui.userNoticesInDefaultBuffer, redirectTarget & BufferSettings::DefaultBuffer); - SettingsPage::load(ui.userNoticesInStatusBuffer, redirectTarget & BufferSettings::StatusBuffer); - SettingsPage::load(ui.userNoticesInCurrentBuffer, redirectTarget & BufferSettings::CurrentBuffer); - - redirectTarget = bufferSettings.serverNoticesTarget(); - SettingsPage::load(ui.serverNoticesInDefaultBuffer, redirectTarget & BufferSettings::DefaultBuffer); - SettingsPage::load(ui.serverNoticesInStatusBuffer, redirectTarget & BufferSettings::StatusBuffer); - SettingsPage::load(ui.serverNoticesInCurrentBuffer, redirectTarget & BufferSettings::CurrentBuffer); - - redirectTarget = bufferSettings.errorMsgsTarget(); - SettingsPage::load(ui.errorMsgsInDefaultBuffer, redirectTarget & BufferSettings::DefaultBuffer); - SettingsPage::load(ui.errorMsgsInStatusBuffer, redirectTarget & BufferSettings::StatusBuffer); - SettingsPage::load(ui.errorMsgsInCurrentBuffer, redirectTarget & BufferSettings::CurrentBuffer); - - SettingsPage::load(); - setChangedState(false); + + SettingsPage::defaults(); + widgetHasChanged(); +} + + +void AppearanceSettingsPage::load() +{ + QtUiSettings uiSettings; + + // Gui Style + QString style = uiSettings.value("Style", QString("")).toString(); + if (style.isEmpty()) { + ui.styleComboBox->setCurrentIndex(0); + } + else { + ui.styleComboBox->setCurrentIndex(ui.styleComboBox->findText(style, Qt::MatchExactly)); + } + ui.styleComboBox->setProperty("storedValue", ui.styleComboBox->currentIndex()); + + // Language + QLocale locale = uiSettings.value("Locale", QLocale::system()).value(); + if (locale == QLocale::system()) + ui.languageComboBox->setCurrentIndex(1); + else if (locale.language() == QLocale::C) // we use C for "untranslated" + ui.languageComboBox->setCurrentIndex(0); + else + ui.languageComboBox->setCurrentIndex(ui.languageComboBox->findText(QLocale::languageToString(locale.language()), Qt::MatchExactly)); + ui.languageComboBox->setProperty("storedValue", ui.languageComboBox->currentIndex()); + Quassel::loadTranslation(selectedLocale()); + + // bufferSettings: + BufferSettings bufferSettings; + int redirectTarget = bufferSettings.userNoticesTarget(); + SettingsPage::load(ui.userNoticesInDefaultBuffer, redirectTarget & BufferSettings::DefaultBuffer); + SettingsPage::load(ui.userNoticesInStatusBuffer, redirectTarget & BufferSettings::StatusBuffer); + SettingsPage::load(ui.userNoticesInCurrentBuffer, redirectTarget & BufferSettings::CurrentBuffer); + + redirectTarget = bufferSettings.serverNoticesTarget(); + SettingsPage::load(ui.serverNoticesInDefaultBuffer, redirectTarget & BufferSettings::DefaultBuffer); + SettingsPage::load(ui.serverNoticesInStatusBuffer, redirectTarget & BufferSettings::StatusBuffer); + SettingsPage::load(ui.serverNoticesInCurrentBuffer, redirectTarget & BufferSettings::CurrentBuffer); + + redirectTarget = bufferSettings.errorMsgsTarget(); + SettingsPage::load(ui.errorMsgsInDefaultBuffer, redirectTarget & BufferSettings::DefaultBuffer); + SettingsPage::load(ui.errorMsgsInStatusBuffer, redirectTarget & BufferSettings::StatusBuffer); + SettingsPage::load(ui.errorMsgsInCurrentBuffer, redirectTarget & BufferSettings::CurrentBuffer); + + SettingsPage::load(); + setChangedState(false); } -void AppearanceSettingsPage::save() { - QtUiSettings uiSettings; - - if(ui.styleComboBox->currentIndex() < 1) { - uiSettings.setValue("Style", QString("")); - } else { - uiSettings.setValue("Style", ui.styleComboBox->currentText()); - QApplication::setStyle(ui.styleComboBox->currentText()); - } - ui.styleComboBox->setProperty("storedValue", ui.styleComboBox->currentIndex()); - - if(ui.languageComboBox->currentIndex() == 1) { - uiSettings.remove("Locale"); // force the default (QLocale::system()) - } else { - uiSettings.setValue("Locale", selectedLocale()); - } - ui.languageComboBox->setProperty("storedValue", ui.languageComboBox->currentIndex()); - - bool needsStyleReload = + +void AppearanceSettingsPage::save() +{ + QtUiSettings uiSettings; + + if (ui.styleComboBox->currentIndex() < 1) { + uiSettings.setValue("Style", QString("")); + } + else { + uiSettings.setValue("Style", ui.styleComboBox->currentText()); + QApplication::setStyle(ui.styleComboBox->currentText()); + } + ui.styleComboBox->setProperty("storedValue", ui.styleComboBox->currentIndex()); + + if (ui.languageComboBox->currentIndex() == 1) { + uiSettings.remove("Locale"); // force the default (QLocale::system()) + } + else { + uiSettings.setValue("Locale", selectedLocale()); + } + ui.languageComboBox->setProperty("storedValue", ui.languageComboBox->currentIndex()); + + bool needsStyleReload = ui.useCustomStyleSheet->isChecked() != ui.useCustomStyleSheet->property("storedValue").toBool() - || (ui.useCustomStyleSheet->isChecked() && ui.customStyleSheetPath->text() != ui.customStyleSheetPath->property("storedValue").toString()); - - BufferSettings bufferSettings; - int redirectTarget = 0; - if(ui.userNoticesInDefaultBuffer->isChecked()) - redirectTarget |= BufferSettings::DefaultBuffer; - if(ui.userNoticesInStatusBuffer->isChecked()) - redirectTarget |= BufferSettings::StatusBuffer; - if(ui.userNoticesInCurrentBuffer->isChecked()) - redirectTarget |= BufferSettings::CurrentBuffer; - bufferSettings.setUserNoticesTarget(redirectTarget); - - redirectTarget = 0; - if(ui.serverNoticesInDefaultBuffer->isChecked()) - redirectTarget |= BufferSettings::DefaultBuffer; - if(ui.serverNoticesInStatusBuffer->isChecked()) - redirectTarget |= BufferSettings::StatusBuffer; - if(ui.serverNoticesInCurrentBuffer->isChecked()) - redirectTarget |= BufferSettings::CurrentBuffer; - bufferSettings.setServerNoticesTarget(redirectTarget); - - redirectTarget = 0; - if(ui.errorMsgsInDefaultBuffer->isChecked()) - redirectTarget |= BufferSettings::DefaultBuffer; - if(ui.errorMsgsInStatusBuffer->isChecked()) - redirectTarget |= BufferSettings::StatusBuffer; - if(ui.errorMsgsInCurrentBuffer->isChecked()) - redirectTarget |= BufferSettings::CurrentBuffer; - bufferSettings.setErrorMsgsTarget(redirectTarget); - - SettingsPage::save(); - setChangedState(false); - if(needsStyleReload) - QtUi::style()->reload(); + || (ui.useCustomStyleSheet->isChecked() && ui.customStyleSheetPath->text() != ui.customStyleSheetPath->property("storedValue").toString()); + + BufferSettings bufferSettings; + int redirectTarget = 0; + if (ui.userNoticesInDefaultBuffer->isChecked()) + redirectTarget |= BufferSettings::DefaultBuffer; + if (ui.userNoticesInStatusBuffer->isChecked()) + redirectTarget |= BufferSettings::StatusBuffer; + if (ui.userNoticesInCurrentBuffer->isChecked()) + redirectTarget |= BufferSettings::CurrentBuffer; + bufferSettings.setUserNoticesTarget(redirectTarget); + + redirectTarget = 0; + if (ui.serverNoticesInDefaultBuffer->isChecked()) + redirectTarget |= BufferSettings::DefaultBuffer; + if (ui.serverNoticesInStatusBuffer->isChecked()) + redirectTarget |= BufferSettings::StatusBuffer; + if (ui.serverNoticesInCurrentBuffer->isChecked()) + redirectTarget |= BufferSettings::CurrentBuffer; + bufferSettings.setServerNoticesTarget(redirectTarget); + + redirectTarget = 0; + if (ui.errorMsgsInDefaultBuffer->isChecked()) + redirectTarget |= BufferSettings::DefaultBuffer; + if (ui.errorMsgsInStatusBuffer->isChecked()) + redirectTarget |= BufferSettings::StatusBuffer; + if (ui.errorMsgsInCurrentBuffer->isChecked()) + redirectTarget |= BufferSettings::CurrentBuffer; + bufferSettings.setErrorMsgsTarget(redirectTarget); + + SettingsPage::save(); + setChangedState(false); + if (needsStyleReload) + QtUi::style()->reload(); } -QLocale AppearanceSettingsPage::selectedLocale() const { - QLocale locale; - int index = ui.languageComboBox->currentIndex(); - if(index == 1) - locale = QLocale::system(); - else if(index == 0) - locale = QLocale::c(); - else if(index > 1) - locale = _locales.values()[index - 2]; - - return locale; + +QLocale AppearanceSettingsPage::selectedLocale() const +{ + QLocale locale; + int index = ui.languageComboBox->currentIndex(); + if (index == 1) + locale = QLocale::system(); + else if (index == 0) + locale = QLocale::c(); + else if (index > 1) + locale = _locales.values()[index - 2]; + + return locale; } -void AppearanceSettingsPage::chooseStyleSheet() { - QString dir = ui.customStyleSheetPath->property("storedValue").toString(); - if(!dir.isEmpty() && QFile(dir).exists()) - dir = QDir(dir).absolutePath(); - else - dir = QDir(Quassel::findDataFilePath("default.qss")).absolutePath(); - QString name = QFileDialog::getOpenFileName(this, tr("Please choose a stylesheet file"), dir, "*.qss"); - if(!name.isEmpty()) - ui.customStyleSheetPath->setText(name); +void AppearanceSettingsPage::chooseStyleSheet() +{ + QString dir = ui.customStyleSheetPath->property("storedValue").toString(); + if (!dir.isEmpty() && QFile(dir).exists()) + dir = QDir(dir).absolutePath(); + else + dir = QDir(Quassel::findDataFilePath("default.qss")).absolutePath(); + + QString name = QFileDialog::getOpenFileName(this, tr("Please choose a stylesheet file"), dir, "*.qss"); + if (!name.isEmpty()) + ui.customStyleSheetPath->setText(name); } -void AppearanceSettingsPage::widgetHasChanged() { - setChangedState(testHasChanged()); + +void AppearanceSettingsPage::widgetHasChanged() +{ + setChangedState(testHasChanged()); } -bool AppearanceSettingsPage::testHasChanged() { - if(ui.styleComboBox->currentIndex() != ui.styleComboBox->property("storedValue").toInt()) return true; - if(ui.languageComboBox->currentIndex() != ui.languageComboBox->property("storedValue").toInt()) return true; - if(SettingsPage::hasChanged(ui.userNoticesInStatusBuffer)) return true; - if(SettingsPage::hasChanged(ui.userNoticesInDefaultBuffer)) return true; - if(SettingsPage::hasChanged(ui.userNoticesInCurrentBuffer)) return true; +bool AppearanceSettingsPage::testHasChanged() +{ + if (ui.styleComboBox->currentIndex() != ui.styleComboBox->property("storedValue").toInt()) return true; + if (ui.languageComboBox->currentIndex() != ui.languageComboBox->property("storedValue").toInt()) return true; + + if (SettingsPage::hasChanged(ui.userNoticesInStatusBuffer)) return true; + if (SettingsPage::hasChanged(ui.userNoticesInDefaultBuffer)) return true; + if (SettingsPage::hasChanged(ui.userNoticesInCurrentBuffer)) return true; - if(SettingsPage::hasChanged(ui.serverNoticesInStatusBuffer)) return true; - if(SettingsPage::hasChanged(ui.serverNoticesInDefaultBuffer)) return true; - if(SettingsPage::hasChanged(ui.serverNoticesInCurrentBuffer)) return true; + if (SettingsPage::hasChanged(ui.serverNoticesInStatusBuffer)) return true; + if (SettingsPage::hasChanged(ui.serverNoticesInDefaultBuffer)) return true; + if (SettingsPage::hasChanged(ui.serverNoticesInCurrentBuffer)) return true; - if(SettingsPage::hasChanged(ui.errorMsgsInStatusBuffer)) return true; - if(SettingsPage::hasChanged(ui.errorMsgsInDefaultBuffer)) return true; - if(SettingsPage::hasChanged(ui.errorMsgsInCurrentBuffer)) return true; + if (SettingsPage::hasChanged(ui.errorMsgsInStatusBuffer)) return true; + if (SettingsPage::hasChanged(ui.errorMsgsInDefaultBuffer)) return true; + if (SettingsPage::hasChanged(ui.errorMsgsInCurrentBuffer)) return true; - return false; + return false; } diff --git a/src/qtui/settingspages/appearancesettingspage.h b/src/qtui/settingspages/appearancesettingspage.h index 4f47a33b..3e6d3202 100644 --- a/src/qtui/settingspages/appearancesettingspage.h +++ b/src/qtui/settingspages/appearancesettingspage.h @@ -30,35 +30,37 @@ #include "settingspage.h" #include "ui_appearancesettingspage.h" -class AppearanceSettingsPage : public SettingsPage { - Q_OBJECT +class AppearanceSettingsPage : public SettingsPage +{ + Q_OBJECT public: - AppearanceSettingsPage(QWidget *parent = 0); + AppearanceSettingsPage(QWidget *parent = 0); - inline bool hasDefaults() const { return true; } + inline bool hasDefaults() const { return true; } public slots: - void save(); - void load(); - void defaults(); + void save(); + void load(); + void defaults(); private slots: - void widgetHasChanged(); + void widgetHasChanged(); - void chooseStyleSheet(); + void chooseStyleSheet(); private: - bool testHasChanged(); - void initStyleComboBox(); - void initLanguageComboBox(); - QLocale selectedLocale() const; + bool testHasChanged(); + void initStyleComboBox(); + void initLanguageComboBox(); + QLocale selectedLocale() const; - Ui::AppearanceSettingsPage ui; - QHash settings; - QMap _locales; + Ui::AppearanceSettingsPage ui; + QHash settings; + QMap _locales; - inline QString settingsKey() const { return QString("QtUi"); } + inline QString settingsKey() const { return QString("QtUi"); } }; + #endif diff --git a/src/qtui/settingspages/backlogsettingspage.cpp b/src/qtui/settingspages/backlogsettingspage.cpp index 5af18c4f..3a259a9f 100644 --- a/src/qtui/settingspages/backlogsettingspage.cpp +++ b/src/qtui/settingspages/backlogsettingspage.cpp @@ -24,45 +24,55 @@ #include "backlogsettings.h" BacklogSettingsPage::BacklogSettingsPage(QWidget *parent) - : SettingsPage(tr("Interface"), tr("Backlog Fetching"), parent) + : SettingsPage(tr("Interface"), tr("Backlog Fetching"), parent) { - ui.setupUi(this); - initAutoWidgets(); - // not an auto widget, because we store index + 1 + ui.setupUi(this); + initAutoWidgets(); + // not an auto widget, because we store index + 1 - // FIXME: global backlog requester disabled until issues ruled out - ui.requesterType->removeItem(2); + // FIXME: global backlog requester disabled until issues ruled out + ui.requesterType->removeItem(2); - connect(ui.requesterType, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); + connect(ui.requesterType, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); } -bool BacklogSettingsPage::hasDefaults() const { - return true; + +bool BacklogSettingsPage::hasDefaults() const +{ + return true; } -void BacklogSettingsPage::defaults() { - ui.requesterType->setCurrentIndex(0); - SettingsPage::defaults(); +void BacklogSettingsPage::defaults() +{ + ui.requesterType->setCurrentIndex(0); + + SettingsPage::defaults(); } -void BacklogSettingsPage::load() { - BacklogSettings backlogSettings; - int index = backlogSettings.requesterType() - 1; - ui.requesterType->setProperty("storedValue", index); - ui.requesterType->setCurrentIndex(index); - SettingsPage::load(); +void BacklogSettingsPage::load() +{ + BacklogSettings backlogSettings; + int index = backlogSettings.requesterType() - 1; + ui.requesterType->setProperty("storedValue", index); + ui.requesterType->setCurrentIndex(index); + + SettingsPage::load(); } -void BacklogSettingsPage::save() { - BacklogSettings backlogSettings; - backlogSettings.setRequesterType(ui.requesterType->currentIndex() + 1); - ui.requesterType->setProperty("storedValue", ui.requesterType->currentIndex()); - SettingsPage::save(); +void BacklogSettingsPage::save() +{ + BacklogSettings backlogSettings; + backlogSettings.setRequesterType(ui.requesterType->currentIndex() + 1); + ui.requesterType->setProperty("storedValue", ui.requesterType->currentIndex()); + + SettingsPage::save(); } -void BacklogSettingsPage::widgetHasChanged() { - setChangedState(ui.requesterType->currentIndex() != ui.requesterType->property("storedValue").toInt()); + +void BacklogSettingsPage::widgetHasChanged() +{ + setChangedState(ui.requesterType->currentIndex() != ui.requesterType->property("storedValue").toInt()); } diff --git a/src/qtui/settingspages/backlogsettingspage.h b/src/qtui/settingspages/backlogsettingspage.h index 0dad7d76..b5ffbc71 100644 --- a/src/qtui/settingspages/backlogsettingspage.h +++ b/src/qtui/settingspages/backlogsettingspage.h @@ -26,25 +26,27 @@ #include "settingspage.h" #include "ui_backlogsettingspage.h" -class BacklogSettingsPage : public SettingsPage { - Q_OBJECT +class BacklogSettingsPage : public SettingsPage +{ + Q_OBJECT public: - BacklogSettingsPage(QWidget *parent = 0); + BacklogSettingsPage(QWidget *parent = 0); - inline QString settingsKey() const { return "Backlog"; } - bool hasDefaults() const; + inline QString settingsKey() const { return "Backlog"; } + bool hasDefaults() const; public slots: - void save(); - void load(); - void defaults(); + void save(); + void load(); + void defaults(); private slots: - void widgetHasChanged(); + void widgetHasChanged(); private: - Ui::BacklogSettingsPage ui; + Ui::BacklogSettingsPage ui; }; + #endif diff --git a/src/qtui/settingspages/bufferviewsettingspage.cpp b/src/qtui/settingspages/bufferviewsettingspage.cpp index 1d18e389..088825c7 100644 --- a/src/qtui/settingspages/bufferviewsettingspage.cpp +++ b/src/qtui/settingspages/bufferviewsettingspage.cpp @@ -33,499 +33,555 @@ #include "util.h" BufferViewSettingsPage::BufferViewSettingsPage(QWidget *parent) - : SettingsPage(tr("Interface"), tr("Custom Chat Lists"), parent), + : SettingsPage(tr("Interface"), tr("Custom Chat Lists"), parent), _ignoreWidgetChanges(false), _useBufferViewHint(false), _bufferViewHint(0) { - ui.setupUi(this); - ui.renameBufferView->setIcon(SmallIcon("edit-rename")); - ui.addBufferView->setIcon(SmallIcon("list-add")); - ui.deleteBufferView->setIcon(SmallIcon("edit-delete")); - - reset(); - - ui.bufferViewList->setSortingEnabled(true); - ui.settingsGroupBox->setEnabled(false); - ui.bufferViewPreview->setEnabled(false); - - coreConnectionStateChanged(Client::isConnected()); // need a core connection! - connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), this, SLOT(coreConnectionStateChanged(bool))); - connect(ui.bufferViewList->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), - this, SLOT(bufferViewSelectionChanged(const QItemSelection &, const QItemSelection &))); - - connect(ui.onlyStatusBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.onlyChannelBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.onlyQueryBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.addNewBuffersAutomatically, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.sortAlphabetically, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.hideInactiveBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.networkSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); - connect(ui.minimumActivitySelector, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); - - connect(ui.networkSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(enableStatusBuffers(int))); + ui.setupUi(this); + ui.renameBufferView->setIcon(SmallIcon("edit-rename")); + ui.addBufferView->setIcon(SmallIcon("list-add")); + ui.deleteBufferView->setIcon(SmallIcon("edit-delete")); + + reset(); + + ui.bufferViewList->setSortingEnabled(true); + ui.settingsGroupBox->setEnabled(false); + ui.bufferViewPreview->setEnabled(false); + + coreConnectionStateChanged(Client::isConnected()); // need a core connection! + connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), this, SLOT(coreConnectionStateChanged(bool))); + connect(ui.bufferViewList->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), + this, SLOT(bufferViewSelectionChanged(const QItemSelection &, const QItemSelection &))); + + connect(ui.onlyStatusBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.onlyChannelBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.onlyQueryBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.addNewBuffersAutomatically, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.sortAlphabetically, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.hideInactiveBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.networkSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); + connect(ui.minimumActivitySelector, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); + + connect(ui.networkSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(enableStatusBuffers(int))); } -BufferViewSettingsPage::~BufferViewSettingsPage() { - reset(); + +BufferViewSettingsPage::~BufferViewSettingsPage() +{ + reset(); } -void BufferViewSettingsPage::reset() { - ui.bufferViewList->clear(); - ui.deleteBufferView->setEnabled(false); - QHash::iterator changedConfigIter = _changedBufferViews.begin(); - QHash::iterator changedConfigIterEnd = _changedBufferViews.end(); - BufferViewConfig *config; - while(changedConfigIter != changedConfigIterEnd) { - config = changedConfigIter.value(); - changedConfigIter = _changedBufferViews.erase(changedConfigIter); - config->deleteLater(); - } +void BufferViewSettingsPage::reset() +{ + ui.bufferViewList->clear(); + ui.deleteBufferView->setEnabled(false); + + QHash::iterator changedConfigIter = _changedBufferViews.begin(); + QHash::iterator changedConfigIterEnd = _changedBufferViews.end(); + BufferViewConfig *config; + while (changedConfigIter != changedConfigIterEnd) { + config = changedConfigIter.value(); + changedConfigIter = _changedBufferViews.erase(changedConfigIter); + config->deleteLater(); + } - QList::iterator newConfigIter = _newBufferViews.begin(); - QList::iterator newConfigIterEnd = _newBufferViews.end(); - while(newConfigIter != newConfigIterEnd) { - config = *newConfigIter; - newConfigIter = _newBufferViews.erase(newConfigIter); - config->deleteLater(); - } + QList::iterator newConfigIter = _newBufferViews.begin(); + QList::iterator newConfigIterEnd = _newBufferViews.end(); + while (newConfigIter != newConfigIterEnd) { + config = *newConfigIter; + newConfigIter = _newBufferViews.erase(newConfigIter); + config->deleteLater(); + } - _deleteBufferViews.clear(); + _deleteBufferViews.clear(); - _useBufferViewHint = false; + _useBufferViewHint = false; - setChangedState(false); + setChangedState(false); } -void BufferViewSettingsPage::load() { - bool useBufferViewHint = _useBufferViewHint; - int bufferViewHint = _bufferViewHint; - reset(); - - if(!Client::bufferViewManager()) - return; - - const QList bufferViewConfigs = Client::bufferViewManager()->bufferViewConfigs(); - foreach(BufferViewConfig *bufferViewConfig, bufferViewConfigs) { - addBufferView(bufferViewConfig); - } - - _ignoreWidgetChanges = true; - // load network selector - ui.networkSelector->clear(); - ui.networkSelector->addItem(tr("All")); - ui.networkSelector->setItemData(0, qVariantFromValue(NetworkId())); - const Network *net; - foreach(NetworkId netId, Client::networkIds()) { - net = Client::network(netId); - ui.networkSelector->addItem(net->networkName()); - ui.networkSelector->setItemData(ui.networkSelector->count() - 1, qVariantFromValue(net->networkId())); - } - _ignoreWidgetChanges = false; - - - if(!useBufferViewHint || !selectBufferViewById(bufferViewHint)) - ui.bufferViewList->setCurrentRow(0); -} -void BufferViewSettingsPage::save() { - setEnabled(false); - - BufferViewConfig *currentConfig = bufferView(ui.bufferViewList->currentRow()); - if(currentConfig) { - _useBufferViewHint = true; - _bufferViewHint = currentConfig->bufferViewId(); - } - - QVariantList newConfigs; - QVariantList deleteConfigs; - QVariantList changedConfigs; - - foreach(int bufferId, _deleteBufferViews) { - deleteConfigs << bufferId; - } - _deleteBufferViews.clear(); - if(Client::bufferViewManager()) { - Client::bufferViewManager()->requestDeleteBufferViews(deleteConfigs); - } - - QHash::iterator changedConfigIter = _changedBufferViews.begin(); - QHash::iterator changedConfigIterEnd = _changedBufferViews.end(); - BufferViewConfig *config, *changedConfig; - while(changedConfigIter != changedConfigIterEnd) { - config = changedConfigIter.key(); - changedConfig = changedConfigIter.value(); - changedConfigIter = _changedBufferViews.erase(changedConfigIter); - config->requestUpdate(changedConfig->toVariantMap()); - changedConfig->deleteLater(); - } - - QList::iterator newConfigIter = _newBufferViews.begin(); - QList::iterator newConfigIterEnd = _newBufferViews.end(); - while(newConfigIter != newConfigIterEnd) { - config = *newConfigIter; - newConfigIter = _newBufferViews.erase(newConfigIter); - newConfigs << config->toVariantMap(); - config->deleteLater(); - } - if(Client::bufferViewManager()) { - Client::bufferViewManager()->requestCreateBufferViews(newConfigs); - } - - load(); - setEnabled(true); +void BufferViewSettingsPage::load() +{ + bool useBufferViewHint = _useBufferViewHint; + int bufferViewHint = _bufferViewHint; + reset(); + + if (!Client::bufferViewManager()) + return; + + const QList bufferViewConfigs = Client::bufferViewManager()->bufferViewConfigs(); + foreach(BufferViewConfig *bufferViewConfig, bufferViewConfigs) { + addBufferView(bufferViewConfig); + } + + _ignoreWidgetChanges = true; + // load network selector + ui.networkSelector->clear(); + ui.networkSelector->addItem(tr("All")); + ui.networkSelector->setItemData(0, qVariantFromValue(NetworkId())); + const Network *net; + foreach(NetworkId netId, Client::networkIds()) { + net = Client::network(netId); + ui.networkSelector->addItem(net->networkName()); + ui.networkSelector->setItemData(ui.networkSelector->count() - 1, qVariantFromValue(net->networkId())); + } + _ignoreWidgetChanges = false; + + if (!useBufferViewHint || !selectBufferViewById(bufferViewHint)) + ui.bufferViewList->setCurrentRow(0); } -void BufferViewSettingsPage::coreConnectionStateChanged(bool state) { - setEnabled(state); - if(state) { + +void BufferViewSettingsPage::save() +{ + setEnabled(false); + + BufferViewConfig *currentConfig = bufferView(ui.bufferViewList->currentRow()); + if (currentConfig) { + _useBufferViewHint = true; + _bufferViewHint = currentConfig->bufferViewId(); + } + + QVariantList newConfigs; + QVariantList deleteConfigs; + QVariantList changedConfigs; + + foreach(int bufferId, _deleteBufferViews) { + deleteConfigs << bufferId; + } + _deleteBufferViews.clear(); + if (Client::bufferViewManager()) { + Client::bufferViewManager()->requestDeleteBufferViews(deleteConfigs); + } + + QHash::iterator changedConfigIter = _changedBufferViews.begin(); + QHash::iterator changedConfigIterEnd = _changedBufferViews.end(); + BufferViewConfig *config, *changedConfig; + while (changedConfigIter != changedConfigIterEnd) { + config = changedConfigIter.key(); + changedConfig = changedConfigIter.value(); + changedConfigIter = _changedBufferViews.erase(changedConfigIter); + config->requestUpdate(changedConfig->toVariantMap()); + changedConfig->deleteLater(); + } + + QList::iterator newConfigIter = _newBufferViews.begin(); + QList::iterator newConfigIterEnd = _newBufferViews.end(); + while (newConfigIter != newConfigIterEnd) { + config = *newConfigIter; + newConfigIter = _newBufferViews.erase(newConfigIter); + newConfigs << config->toVariantMap(); + config->deleteLater(); + } + if (Client::bufferViewManager()) { + Client::bufferViewManager()->requestCreateBufferViews(newConfigs); + } + load(); - connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigAdded(int)), this, SLOT(addBufferView(int))); - } else { - reset(); - } + setEnabled(true); } -void BufferViewSettingsPage::addBufferView(BufferViewConfig *config) { - QListWidgetItem *item = new QListWidgetItem(config->bufferViewName(), ui.bufferViewList); - item->setData(Qt::UserRole, qVariantFromValue(qobject_cast(config))); - connect(config, SIGNAL(updatedRemotely()), this, SLOT(updateBufferView())); - connect(config, SIGNAL(destroyed()), this, SLOT(bufferViewDeleted())); - ui.deleteBufferView->setEnabled(ui.bufferViewList->count() > 1); + +void BufferViewSettingsPage::coreConnectionStateChanged(bool state) +{ + setEnabled(state); + if (state) { + load(); + connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigAdded(int)), this, SLOT(addBufferView(int))); + } + else { + reset(); + } +} + + +void BufferViewSettingsPage::addBufferView(BufferViewConfig *config) +{ + QListWidgetItem *item = new QListWidgetItem(config->bufferViewName(), ui.bufferViewList); + item->setData(Qt::UserRole, qVariantFromValue(qobject_cast(config))); + connect(config, SIGNAL(updatedRemotely()), this, SLOT(updateBufferView())); + connect(config, SIGNAL(destroyed()), this, SLOT(bufferViewDeleted())); + ui.deleteBufferView->setEnabled(ui.bufferViewList->count() > 1); } -void BufferViewSettingsPage::addBufferView(int bufferViewId) { - // we are informed about a new bufferview from Client::bufferViewManager() - Q_ASSERT(Client::bufferViewManager()); - addBufferView(Client::bufferViewManager()->bufferViewConfig(bufferViewId)); - selectBufferViewById(bufferViewId); + +void BufferViewSettingsPage::addBufferView(int bufferViewId) +{ + // we are informed about a new bufferview from Client::bufferViewManager() + Q_ASSERT(Client::bufferViewManager()); + addBufferView(Client::bufferViewManager()->bufferViewConfig(bufferViewId)); + selectBufferViewById(bufferViewId); } -void BufferViewSettingsPage::bufferViewDeleted() { - BufferViewConfig *config = static_cast(sender()); - QObject *obj; - for(int i = 0; i < ui.bufferViewList->count(); i++) { - obj = ui.bufferViewList->item(i)->data(Qt::UserRole).value(); - if(config == static_cast(obj)) { - QListWidgetItem *item = ui.bufferViewList->takeItem(i); - delete item; - break; + +void BufferViewSettingsPage::bufferViewDeleted() +{ + BufferViewConfig *config = static_cast(sender()); + QObject *obj; + for (int i = 0; i < ui.bufferViewList->count(); i++) { + obj = ui.bufferViewList->item(i)->data(Qt::UserRole).value(); + if (config == static_cast(obj)) { + QListWidgetItem *item = ui.bufferViewList->takeItem(i); + delete item; + break; + } } - } - ui.deleteBufferView->setEnabled(ui.bufferViewList->count() > 1); + ui.deleteBufferView->setEnabled(ui.bufferViewList->count() > 1); } -void BufferViewSettingsPage::newBufferView(const QString &bufferViewName) { - // id's of newly created bufferviews are negative (-1, -2... -n) - int fakeId = -1 * (_newBufferViews.count() + 1); - BufferViewConfig *config = new BufferViewConfig(fakeId); - config->setBufferViewName(bufferViewName); - config->setInitialized(); - QList bufferIds; - if(config->addNewBuffersAutomatically()) { - if(config->sortAlphabetically()) { - bufferIds = Client::networkModel()->allBufferIdsSorted(); - } else { - bufferIds = Client::networkModel()->allBufferIds(); - qSort(bufferIds); - config->setProperty("OriginalBufferList", toVariantList(bufferIds)); + +void BufferViewSettingsPage::newBufferView(const QString &bufferViewName) +{ + // id's of newly created bufferviews are negative (-1, -2... -n) + int fakeId = -1 * (_newBufferViews.count() + 1); + BufferViewConfig *config = new BufferViewConfig(fakeId); + config->setBufferViewName(bufferViewName); + config->setInitialized(); + QList bufferIds; + if (config->addNewBuffersAutomatically()) { + if (config->sortAlphabetically()) { + bufferIds = Client::networkModel()->allBufferIdsSorted(); + } + else { + bufferIds = Client::networkModel()->allBufferIds(); + qSort(bufferIds); + config->setProperty("OriginalBufferList", toVariantList(bufferIds)); + } } - } - config->initSetBufferList(bufferIds); + config->initSetBufferList(bufferIds); - _newBufferViews << config; - addBufferView(config); - ui.bufferViewList->setCurrentRow(listPos(config)); + _newBufferViews << config; + addBufferView(config); + ui.bufferViewList->setCurrentRow(listPos(config)); } -int BufferViewSettingsPage::listPos(BufferViewConfig *config) { - QObject *obj; - for(int i = 0; i < ui.bufferViewList->count(); i++) { - obj = ui.bufferViewList->item(i)->data(Qt::UserRole).value(); - if(config == qobject_cast(obj)) - return i; - } - return -1; + +int BufferViewSettingsPage::listPos(BufferViewConfig *config) +{ + QObject *obj; + for (int i = 0; i < ui.bufferViewList->count(); i++) { + obj = ui.bufferViewList->item(i)->data(Qt::UserRole).value(); + if (config == qobject_cast(obj)) + return i; + } + return -1; } -BufferViewConfig *BufferViewSettingsPage::bufferView(int listPos) { - if(listPos < ui.bufferViewList->count() && listPos >= 0) { - QObject *obj = ui.bufferViewList->item(listPos)->data(Qt::UserRole).value(); - return qobject_cast(obj); - } else { - return 0; - } + +BufferViewConfig *BufferViewSettingsPage::bufferView(int listPos) +{ + if (listPos < ui.bufferViewList->count() && listPos >= 0) { + QObject *obj = ui.bufferViewList->item(listPos)->data(Qt::UserRole).value(); + return qobject_cast(obj); + } + else { + return 0; + } } -bool BufferViewSettingsPage::selectBufferViewById(int bufferViewId) { - BufferViewConfig *config; - for(int i = 0; i < ui.bufferViewList->count(); i++) { - config = qobject_cast(ui.bufferViewList->item(i)->data(Qt::UserRole).value()); - if(config && config->bufferViewId() == bufferViewId) { - ui.bufferViewList->setCurrentRow(i); - return true; + +bool BufferViewSettingsPage::selectBufferViewById(int bufferViewId) +{ + BufferViewConfig *config; + for (int i = 0; i < ui.bufferViewList->count(); i++) { + config = qobject_cast(ui.bufferViewList->item(i)->data(Qt::UserRole).value()); + if (config && config->bufferViewId() == bufferViewId) { + ui.bufferViewList->setCurrentRow(i); + return true; + } } - } - return false; + return false; } -void BufferViewSettingsPage::updateBufferView() { - BufferViewConfig *config = qobject_cast(sender()); - if(!config) - return; - - int itemPos = listPos(config); - if(itemPos == -1) { - qWarning() << "BufferViewSettingsPage::updateBufferView(): view is unknown:" << config->bufferViewId(); - return; - } - ui.bufferViewList->item(itemPos)->setText(config->bufferViewName()); - if(itemPos == ui.bufferViewList->currentRow()) - loadConfig(config); + +void BufferViewSettingsPage::updateBufferView() +{ + BufferViewConfig *config = qobject_cast(sender()); + if (!config) + return; + + int itemPos = listPos(config); + if (itemPos == -1) { + qWarning() << "BufferViewSettingsPage::updateBufferView(): view is unknown:" << config->bufferViewId(); + return; + } + ui.bufferViewList->item(itemPos)->setText(config->bufferViewName()); + if (itemPos == ui.bufferViewList->currentRow()) + loadConfig(config); } -void BufferViewSettingsPage::enableStatusBuffers(int networkIdx) { - // we don't show a status buffer if we show multiple networks as selecting - // the network is the same as selecting the status buffer. - ui.onlyStatusBuffers->setEnabled(networkIdx != 0); + +void BufferViewSettingsPage::enableStatusBuffers(int networkIdx) +{ + // we don't show a status buffer if we show multiple networks as selecting + // the network is the same as selecting the status buffer. + ui.onlyStatusBuffers->setEnabled(networkIdx != 0); } -void BufferViewSettingsPage::on_addBufferView_clicked() { - if(!Client::bufferViewManager()) - return; - QStringList existing; - foreach(BufferViewConfig *bufferConfig, Client::bufferViewManager()->bufferViewConfigs()) { - existing << bufferConfig->bufferViewName(); - } +void BufferViewSettingsPage::on_addBufferView_clicked() +{ + if (!Client::bufferViewManager()) + return; + + QStringList existing; + foreach(BufferViewConfig *bufferConfig, Client::bufferViewManager()->bufferViewConfigs()) { + existing << bufferConfig->bufferViewName(); + } - BufferViewEditDlg dlg(QString(), existing, this); - if(dlg.exec() == QDialog::Accepted) { - newBufferView(dlg.bufferViewName()); - changed(); - } + BufferViewEditDlg dlg(QString(), existing, this); + if (dlg.exec() == QDialog::Accepted) { + newBufferView(dlg.bufferViewName()); + changed(); + } } -void BufferViewSettingsPage::on_renameBufferView_clicked() { - if(ui.bufferViewList->selectedItems().isEmpty()) - return; - - if(!Client::bufferViewManager()) - return; - - BufferViewConfig *config = bufferView(ui.bufferViewList->currentRow()); - if(!config) - return; - - QStringList existing; - foreach(BufferViewConfig *bufferConfig, Client::bufferViewManager()->bufferViewConfigs()) { - existing << bufferConfig->bufferViewName(); - } - - BufferViewEditDlg dlg(config->bufferViewName(), existing, this); - if(dlg.exec() == QDialog::Accepted) { - BufferViewConfig *changedConfig = cloneConfig(config); - changedConfig->setBufferViewName(dlg.bufferViewName()); - ui.bufferViewList->item(listPos(config))->setText(dlg.bufferViewName()); - changed(); - } + +void BufferViewSettingsPage::on_renameBufferView_clicked() +{ + if (ui.bufferViewList->selectedItems().isEmpty()) + return; + + if (!Client::bufferViewManager()) + return; + + BufferViewConfig *config = bufferView(ui.bufferViewList->currentRow()); + if (!config) + return; + + QStringList existing; + foreach(BufferViewConfig *bufferConfig, Client::bufferViewManager()->bufferViewConfigs()) { + existing << bufferConfig->bufferViewName(); + } + + BufferViewEditDlg dlg(config->bufferViewName(), existing, this); + if (dlg.exec() == QDialog::Accepted) { + BufferViewConfig *changedConfig = cloneConfig(config); + changedConfig->setBufferViewName(dlg.bufferViewName()); + ui.bufferViewList->item(listPos(config))->setText(dlg.bufferViewName()); + changed(); + } } -void BufferViewSettingsPage::on_deleteBufferView_clicked() { - if(ui.bufferViewList->selectedItems().isEmpty()) - return; - - QListWidgetItem *currentItem = ui.bufferViewList->item(ui.bufferViewList->currentRow()); - QString viewName = currentItem->text(); - int viewId = bufferView(ui.bufferViewList->currentRow())->bufferViewId(); - int ret = QMessageBox::question(this, tr("Delete Chat List?"), - tr("Do you really want to delete the chat list \"%1\"?").arg(viewName), - QMessageBox::Yes|QMessageBox::No, QMessageBox::No); - - if(ret == QMessageBox::Yes) { - ui.bufferViewList->removeItemWidget(currentItem); - BufferViewConfig *config = qobject_cast(currentItem->data(Qt::UserRole).value()); - delete currentItem; - if(viewId >= 0) { - _deleteBufferViews << viewId; - changed(); - } else if(config) { - QList::iterator iter = _newBufferViews.begin(); - while(iter != _newBufferViews.end()) { - if(*iter == config) { - iter = _newBufferViews.erase(iter); - break; - } else { - iter++; + +void BufferViewSettingsPage::on_deleteBufferView_clicked() +{ + if (ui.bufferViewList->selectedItems().isEmpty()) + return; + + QListWidgetItem *currentItem = ui.bufferViewList->item(ui.bufferViewList->currentRow()); + QString viewName = currentItem->text(); + int viewId = bufferView(ui.bufferViewList->currentRow())->bufferViewId(); + int ret = QMessageBox::question(this, tr("Delete Chat List?"), + tr("Do you really want to delete the chat list \"%1\"?").arg(viewName), + QMessageBox::Yes|QMessageBox::No, QMessageBox::No); + + if (ret == QMessageBox::Yes) { + ui.bufferViewList->removeItemWidget(currentItem); + BufferViewConfig *config = qobject_cast(currentItem->data(Qt::UserRole).value()); + delete currentItem; + if (viewId >= 0) { + _deleteBufferViews << viewId; + changed(); + } + else if (config) { + QList::iterator iter = _newBufferViews.begin(); + while (iter != _newBufferViews.end()) { + if (*iter == config) { + iter = _newBufferViews.erase(iter); + break; + } + else { + iter++; + } + } + delete config; + if (_deleteBufferViews.isEmpty() && _changedBufferViews.isEmpty() && _newBufferViews.isEmpty()) + setChangedState(false); } - } - delete config; - if(_deleteBufferViews.isEmpty() && _changedBufferViews.isEmpty() && _newBufferViews.isEmpty()) - setChangedState(false); } - } } -void BufferViewSettingsPage::bufferViewSelectionChanged(const QItemSelection ¤t, const QItemSelection &previous) { - Q_UNUSED(previous) - if(!current.isEmpty()) { - ui.settingsGroupBox->setEnabled(true); - ui.bufferViewPreview->setEnabled(true); +void BufferViewSettingsPage::bufferViewSelectionChanged(const QItemSelection ¤t, const QItemSelection &previous) +{ + Q_UNUSED(previous) + + if (!current.isEmpty()) { + ui.settingsGroupBox->setEnabled(true); + ui.bufferViewPreview->setEnabled(true); - loadConfig(configForDisplay(bufferView(ui.bufferViewList->currentRow()))); - } else { - ui.settingsGroupBox->setEnabled(false); - ui.bufferViewPreview->setEnabled(false); - } + loadConfig(configForDisplay(bufferView(ui.bufferViewList->currentRow()))); + } + else { + ui.settingsGroupBox->setEnabled(false); + ui.bufferViewPreview->setEnabled(false); + } } -void BufferViewSettingsPage::loadConfig(BufferViewConfig *config) { - if(!config) - return; - - _ignoreWidgetChanges = true; - ui.onlyStatusBuffers->setChecked(BufferInfo::StatusBuffer & config->allowedBufferTypes()); - ui.onlyChannelBuffers->setChecked(BufferInfo::ChannelBuffer & config->allowedBufferTypes()); - ui.onlyQueryBuffers->setChecked(BufferInfo::QueryBuffer & config->allowedBufferTypes()); - ui.addNewBuffersAutomatically->setChecked(config->addNewBuffersAutomatically()); - ui.sortAlphabetically->setChecked(config->sortAlphabetically()); - ui.hideInactiveBuffers->setChecked(config->hideInactiveBuffers()); - - int networkIndex = 0; - for(int i = 0; i < ui.networkSelector->count(); i++) { - if(ui.networkSelector->itemData(i).value() == config->networkId()) { - networkIndex = i; - break; + +void BufferViewSettingsPage::loadConfig(BufferViewConfig *config) +{ + if (!config) + return; + + _ignoreWidgetChanges = true; + ui.onlyStatusBuffers->setChecked(BufferInfo::StatusBuffer & config->allowedBufferTypes()); + ui.onlyChannelBuffers->setChecked(BufferInfo::ChannelBuffer & config->allowedBufferTypes()); + ui.onlyQueryBuffers->setChecked(BufferInfo::QueryBuffer & config->allowedBufferTypes()); + ui.addNewBuffersAutomatically->setChecked(config->addNewBuffersAutomatically()); + ui.sortAlphabetically->setChecked(config->sortAlphabetically()); + ui.hideInactiveBuffers->setChecked(config->hideInactiveBuffers()); + + int networkIndex = 0; + for (int i = 0; i < ui.networkSelector->count(); i++) { + if (ui.networkSelector->itemData(i).value() == config->networkId()) { + networkIndex = i; + break; + } } - } - ui.networkSelector->setCurrentIndex(networkIndex); + ui.networkSelector->setCurrentIndex(networkIndex); - int activityIndex = 0; - int minimumActivity = config->minimumActivity(); - while(minimumActivity) { - activityIndex++; - minimumActivity = minimumActivity >> 1; - } - ui.minimumActivitySelector->setCurrentIndex(activityIndex); + int activityIndex = 0; + int minimumActivity = config->minimumActivity(); + while (minimumActivity) { + activityIndex++; + minimumActivity = minimumActivity >> 1; + } + ui.minimumActivitySelector->setCurrentIndex(activityIndex); - ui.bufferViewPreview->setFilteredModel(Client::bufferModel(), config); + ui.bufferViewPreview->setFilteredModel(Client::bufferModel(), config); - _ignoreWidgetChanges = false; + _ignoreWidgetChanges = false; } -void BufferViewSettingsPage::saveConfig(BufferViewConfig *config) { - if(!config) - return; - - int allowedBufferTypes = 0; - if(ui.onlyStatusBuffers->isChecked()) - allowedBufferTypes |= BufferInfo::StatusBuffer; - if(ui.onlyChannelBuffers->isChecked()) - allowedBufferTypes |= BufferInfo::ChannelBuffer; - if(ui.onlyQueryBuffers->isChecked()) - allowedBufferTypes |= BufferInfo::QueryBuffer; - config->setAllowedBufferTypes(allowedBufferTypes); - - config->setAddNewBuffersAutomatically(ui.addNewBuffersAutomatically->isChecked()); - config->setSortAlphabetically(ui.sortAlphabetically->isChecked()); - config->setHideInactiveBuffers(ui.hideInactiveBuffers->isChecked()); - config->setNetworkId(ui.networkSelector->itemData(ui.networkSelector->currentIndex()).value()); - - int minimumActivity = 0; - if(ui.minimumActivitySelector->currentIndex() > 0) - minimumActivity = 1 << (ui.minimumActivitySelector->currentIndex() - 1); - config->setMinimumActivity(minimumActivity); - - QList bufferIds = fromVariantList(config->property("OriginalBufferList").toList()); - if(config->sortAlphabetically()) - Client::networkModel()->sortBufferIds(bufferIds); - - if(!_newBufferViews.contains(config) || config->addNewBuffersAutomatically()) - config->initSetBufferList(bufferIds); + +void BufferViewSettingsPage::saveConfig(BufferViewConfig *config) +{ + if (!config) + return; + + int allowedBufferTypes = 0; + if (ui.onlyStatusBuffers->isChecked()) + allowedBufferTypes |= BufferInfo::StatusBuffer; + if (ui.onlyChannelBuffers->isChecked()) + allowedBufferTypes |= BufferInfo::ChannelBuffer; + if (ui.onlyQueryBuffers->isChecked()) + allowedBufferTypes |= BufferInfo::QueryBuffer; + config->setAllowedBufferTypes(allowedBufferTypes); + + config->setAddNewBuffersAutomatically(ui.addNewBuffersAutomatically->isChecked()); + config->setSortAlphabetically(ui.sortAlphabetically->isChecked()); + config->setHideInactiveBuffers(ui.hideInactiveBuffers->isChecked()); + config->setNetworkId(ui.networkSelector->itemData(ui.networkSelector->currentIndex()).value()); + + int minimumActivity = 0; + if (ui.minimumActivitySelector->currentIndex() > 0) + minimumActivity = 1 << (ui.minimumActivitySelector->currentIndex() - 1); + config->setMinimumActivity(minimumActivity); + + QList bufferIds = fromVariantList(config->property("OriginalBufferList").toList()); + if (config->sortAlphabetically()) + Client::networkModel()->sortBufferIds(bufferIds); + + if (!_newBufferViews.contains(config) || config->addNewBuffersAutomatically()) + config->initSetBufferList(bufferIds); } -void BufferViewSettingsPage::widgetHasChanged() { - if(_ignoreWidgetChanges) - return; - setChangedState(testHasChanged()); + +void BufferViewSettingsPage::widgetHasChanged() +{ + if (_ignoreWidgetChanges) + return; + setChangedState(testHasChanged()); } -bool BufferViewSettingsPage::testHasChanged() { - saveConfig(cloneConfig(bufferView(ui.bufferViewList->currentRow()))); - - if(!_newBufferViews.isEmpty()) - return true; - - bool changed = false; - QHash::iterator iter = _changedBufferViews.begin(); - QHash::iterator iterEnd = _changedBufferViews.end(); - while(iter != iterEnd) { - if(&(iter.key()) == &(iter.value())) { - iter.value()->deleteLater(); - iter = _changedBufferViews.erase(iter); - } else { - changed = true; - iter++; + +bool BufferViewSettingsPage::testHasChanged() +{ + saveConfig(cloneConfig(bufferView(ui.bufferViewList->currentRow()))); + + if (!_newBufferViews.isEmpty()) + return true; + + bool changed = false; + QHash::iterator iter = _changedBufferViews.begin(); + QHash::iterator iterEnd = _changedBufferViews.end(); + while (iter != iterEnd) { + if (&(iter.key()) == &(iter.value())) { + iter.value()->deleteLater(); + iter = _changedBufferViews.erase(iter); + } + else { + changed = true; + iter++; + } } - } - return changed; + return changed; } -BufferViewConfig *BufferViewSettingsPage::cloneConfig(BufferViewConfig *config) { - if(!config || config->bufferViewId() < 0) - return config; - if(_changedBufferViews.contains(config)) - return _changedBufferViews[config]; - - BufferViewConfig *changedConfig = new BufferViewConfig(-1, this); - changedConfig->fromVariantMap(config->toVariantMap()); - changedConfig->setInitialized(); - _changedBufferViews[config] = changedConfig; - connect(config, SIGNAL(bufferAdded(const BufferId &, int)), changedConfig, SLOT(addBuffer(const BufferId &, int))); - connect(config, SIGNAL(bufferMoved(const BufferId &, int)), changedConfig, SLOT(moveBuffer(const BufferId &, int))); - connect(config, SIGNAL(bufferRemoved(const BufferId &)), changedConfig, SLOT(removeBuffer(const BufferId &))); +BufferViewConfig *BufferViewSettingsPage::cloneConfig(BufferViewConfig *config) +{ + if (!config || config->bufferViewId() < 0) + return config; + + if (_changedBufferViews.contains(config)) + return _changedBufferViews[config]; + + BufferViewConfig *changedConfig = new BufferViewConfig(-1, this); + changedConfig->fromVariantMap(config->toVariantMap()); + changedConfig->setInitialized(); + _changedBufferViews[config] = changedConfig; + connect(config, SIGNAL(bufferAdded(const BufferId &, int)), changedConfig, SLOT(addBuffer(const BufferId &, int))); + connect(config, SIGNAL(bufferMoved(const BufferId &, int)), changedConfig, SLOT(moveBuffer(const BufferId &, int))); + connect(config, SIGNAL(bufferRemoved(const BufferId &)), changedConfig, SLOT(removeBuffer(const BufferId &))); // connect(config, SIGNAL(addBufferRequested(const BufferId &, int)), changedConfig, SLOT(addBuffer(const BufferId &, int))); // connect(config, SIGNAL(moveBufferRequested(const BufferId &, int)), changedConfig, SLOT(moveBuffer(const BufferId &, int))); // connect(config, SIGNAL(removeBufferRequested(const BufferId &)), changedConfig, SLOT(removeBuffer(const BufferId &))); - changedConfig->setProperty("OriginalBufferList", toVariantList(config->bufferList())); - // if this is the currently displayed view we have to change the config of the preview filter - BufferViewFilter *filter = qobject_cast(ui.bufferViewPreview->model()); - if(filter && filter->config() == config) - filter->setConfig(changedConfig); - ui.bufferViewPreview->setConfig(changedConfig); + changedConfig->setProperty("OriginalBufferList", toVariantList(config->bufferList())); + // if this is the currently displayed view we have to change the config of the preview filter + BufferViewFilter *filter = qobject_cast(ui.bufferViewPreview->model()); + if (filter && filter->config() == config) + filter->setConfig(changedConfig); + ui.bufferViewPreview->setConfig(changedConfig); - return changedConfig; + return changedConfig; } -BufferViewConfig *BufferViewSettingsPage::configForDisplay(BufferViewConfig *config) { - if(_changedBufferViews.contains(config)) - return _changedBufferViews[config]; - else - return config; + +BufferViewConfig *BufferViewSettingsPage::configForDisplay(BufferViewConfig *config) +{ + if (_changedBufferViews.contains(config)) + return _changedBufferViews[config]; + else + return config; } /************************************************************************** * BufferViewEditDlg *************************************************************************/ -BufferViewEditDlg::BufferViewEditDlg(const QString &old, const QStringList &exist, QWidget *parent) : QDialog(parent), existing(exist) { - ui.setupUi(this); - - if(old.isEmpty()) { - // new buffer - setWindowTitle(tr("Add Chat List")); - on_bufferViewEdit_textChanged(""); // disable ok button - } else { - ui.bufferViewEdit->setText(old); - } +BufferViewEditDlg::BufferViewEditDlg(const QString &old, const QStringList &exist, QWidget *parent) : QDialog(parent), existing(exist) +{ + ui.setupUi(this); + + if (old.isEmpty()) { + // new buffer + setWindowTitle(tr("Add Chat List")); + on_bufferViewEdit_textChanged(""); // disable ok button + } + else { + ui.bufferViewEdit->setText(old); + } } -void BufferViewEditDlg::on_bufferViewEdit_textChanged(const QString &text) { - ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(text.isEmpty() || existing.contains(text)); +void BufferViewEditDlg::on_bufferViewEdit_textChanged(const QString &text) +{ + ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(text.isEmpty() || existing.contains(text)); } - diff --git a/src/qtui/settingspages/bufferviewsettingspage.h b/src/qtui/settingspages/bufferviewsettingspage.h index 40fc539b..ec787e30 100644 --- a/src/qtui/settingspages/bufferviewsettingspage.h +++ b/src/qtui/settingspages/bufferviewsettingspage.h @@ -29,83 +29,84 @@ class BufferViewConfig; -class BufferViewSettingsPage : public SettingsPage { - Q_OBJECT +class BufferViewSettingsPage : public SettingsPage +{ + Q_OBJECT public: - BufferViewSettingsPage(QWidget *parent = 0); - ~BufferViewSettingsPage(); + BufferViewSettingsPage(QWidget *parent = 0); + ~BufferViewSettingsPage(); public slots: - void save(); - void load(); - void reset(); + void save(); + void load(); + void reset(); private slots: - void coreConnectionStateChanged(bool state); + void coreConnectionStateChanged(bool state); - void addBufferView(BufferViewConfig *config); - void addBufferView(int bufferViewId); - void bufferViewDeleted(); - void newBufferView(const QString &bufferViewName); - void updateBufferView(); + void addBufferView(BufferViewConfig *config); + void addBufferView(int bufferViewId); + void bufferViewDeleted(); + void newBufferView(const QString &bufferViewName); + void updateBufferView(); - void enableStatusBuffers(int networkIdx); + void enableStatusBuffers(int networkIdx); - void on_addBufferView_clicked(); - void on_renameBufferView_clicked(); - void on_deleteBufferView_clicked(); - void bufferViewSelectionChanged(const QItemSelection ¤t, const QItemSelection &previous); + void on_addBufferView_clicked(); + void on_renameBufferView_clicked(); + void on_deleteBufferView_clicked(); + void bufferViewSelectionChanged(const QItemSelection ¤t, const QItemSelection &previous); + + void widgetHasChanged(); - void widgetHasChanged(); - private: - Ui::BufferViewSettingsPage ui; - bool _ignoreWidgetChanges; - bool _useBufferViewHint; - int _bufferViewHint; - - // list of bufferviews to create - QList _newBufferViews; - - // list of buferViews to delete - QList _deleteBufferViews; - - // Hash of pointers to cloned bufferViewConfigs holding the changes - QHash _changedBufferViews; - - int listPos(BufferViewConfig *config); - BufferViewConfig *bufferView(int listPos); - bool selectBufferViewById(int bufferViewId); - BufferViewConfig *cloneConfig(BufferViewConfig *config); - BufferViewConfig *configForDisplay(BufferViewConfig *config); - - void loadConfig(BufferViewConfig *config); - void saveConfig(BufferViewConfig *config); - bool testHasChanged(); + Ui::BufferViewSettingsPage ui; + bool _ignoreWidgetChanges; + bool _useBufferViewHint; + int _bufferViewHint; + + // list of bufferviews to create + QList _newBufferViews; + + // list of buferViews to delete + QList _deleteBufferViews; + + // Hash of pointers to cloned bufferViewConfigs holding the changes + QHash _changedBufferViews; + + int listPos(BufferViewConfig *config); + BufferViewConfig *bufferView(int listPos); + bool selectBufferViewById(int bufferViewId); + BufferViewConfig *cloneConfig(BufferViewConfig *config); + BufferViewConfig *configForDisplay(BufferViewConfig *config); + + void loadConfig(BufferViewConfig *config); + void saveConfig(BufferViewConfig *config); + bool testHasChanged(); }; /************************************************************************** * BufferViewEditDlg *************************************************************************/ -class BufferViewEditDlg : public QDialog { - Q_OBJECT +class BufferViewEditDlg : public QDialog +{ + Q_OBJECT public: - BufferViewEditDlg(const QString &old, const QStringList &existing = QStringList(), QWidget *parent = 0); + BufferViewEditDlg(const QString &old, const QStringList &existing = QStringList(), QWidget *parent = 0); - inline QString bufferViewName() const { return ui.bufferViewEdit->text(); } + inline QString bufferViewName() const { return ui.bufferViewEdit->text(); } private slots: - void on_bufferViewEdit_textChanged(const QString &); - + void on_bufferViewEdit_textChanged(const QString &); + private: - Ui::BufferViewEditDlg ui; + Ui::BufferViewEditDlg ui; - QStringList existing; + QStringList existing; }; - #endif // BUFFERVIEWSETTINGSPAGE_H diff --git a/src/qtui/settingspages/chatmonitorsettingspage.cpp b/src/qtui/settingspages/chatmonitorsettingspage.cpp index 2a434c2c..1b12c885 100644 --- a/src/qtui/settingspages/chatmonitorsettingspage.cpp +++ b/src/qtui/settingspages/chatmonitorsettingspage.cpp @@ -32,138 +32,154 @@ #include ChatMonitorSettingsPage::ChatMonitorSettingsPage(QWidget *parent) - : SettingsPage(tr("Interface"), tr("Chat Monitor"), parent) { - ui.setupUi(this); - - ui.activateBuffer->setIcon(SmallIcon("go-next")); - ui.deactivateBuffer->setIcon(SmallIcon("go-previous")); - - // setup available buffers config (for the bufferview on the left) - _configAvailable = new BufferViewConfig(-667, this); - _configAvailable->setBufferViewName("tmpChatMonitorAvailableBuffers"); - _configAvailable->setSortAlphabetically(true); - _configAvailable->setDisableDecoration(true); - _configAvailable->setNetworkId(NetworkId()); - _configAvailable->setInitialized(); - - // setup active buffers config (for the bufferview on the right) - _configActive = new BufferViewConfig(-666, this); - _configActive->setBufferViewName("tmpChatMonitorActiveBuffers"); - _configActive->setSortAlphabetically(true); - _configActive->setDisableDecoration(true); - _configActive->setNetworkId(NetworkId()); - _configActive->setInitialized(); - - // fill combobox with operation modes - ui.operationMode->addItem(tr("Opt In"), ChatViewSettings::OptIn); - ui.operationMode->addItem(tr("Opt Out"), ChatViewSettings::OptOut); - - // connect slots - connect(ui.operationMode, SIGNAL(currentIndexChanged(int)), SLOT(switchOperationMode(int))); - connect(ui.showHighlights, SIGNAL(toggled(bool)), SLOT(widgetHasChanged())); - connect(ui.showOwnMessages, SIGNAL(toggled(bool)), SLOT(widgetHasChanged())); + : SettingsPage(tr("Interface"), tr("Chat Monitor"), parent) +{ + ui.setupUi(this); + + ui.activateBuffer->setIcon(SmallIcon("go-next")); + ui.deactivateBuffer->setIcon(SmallIcon("go-previous")); + + // setup available buffers config (for the bufferview on the left) + _configAvailable = new BufferViewConfig(-667, this); + _configAvailable->setBufferViewName("tmpChatMonitorAvailableBuffers"); + _configAvailable->setSortAlphabetically(true); + _configAvailable->setDisableDecoration(true); + _configAvailable->setNetworkId(NetworkId()); + _configAvailable->setInitialized(); + + // setup active buffers config (for the bufferview on the right) + _configActive = new BufferViewConfig(-666, this); + _configActive->setBufferViewName("tmpChatMonitorActiveBuffers"); + _configActive->setSortAlphabetically(true); + _configActive->setDisableDecoration(true); + _configActive->setNetworkId(NetworkId()); + _configActive->setInitialized(); + + // fill combobox with operation modes + ui.operationMode->addItem(tr("Opt In"), ChatViewSettings::OptIn); + ui.operationMode->addItem(tr("Opt Out"), ChatViewSettings::OptOut); + + // connect slots + connect(ui.operationMode, SIGNAL(currentIndexChanged(int)), SLOT(switchOperationMode(int))); + connect(ui.showHighlights, SIGNAL(toggled(bool)), SLOT(widgetHasChanged())); + connect(ui.showOwnMessages, SIGNAL(toggled(bool)), SLOT(widgetHasChanged())); } -bool ChatMonitorSettingsPage::hasDefaults() const { - return true; + +bool ChatMonitorSettingsPage::hasDefaults() const +{ + return true; } -void ChatMonitorSettingsPage::defaults() { - settings["OperationMode"] = ChatViewSettings::OptOut; - settings["ShowHighlights"] = false; - settings["ShowOwnMsgs"] = false; - settings["Buffers"] = QVariant(); - settings["Default"] = true; - load(); - widgetHasChanged(); + +void ChatMonitorSettingsPage::defaults() +{ + settings["OperationMode"] = ChatViewSettings::OptOut; + settings["ShowHighlights"] = false; + settings["ShowOwnMsgs"] = false; + settings["Buffers"] = QVariant(); + settings["Default"] = true; + load(); + widgetHasChanged(); } -void ChatMonitorSettingsPage::load() { - if(settings.contains("Default")) - settings.remove("Default"); - else - loadSettings(); - - switchOperationMode(settings["OperationMode"].toInt() - 1); - ui.operationMode->setCurrentIndex(settings["OperationMode"].toInt() - 1); - ui.showHighlights->setChecked(settings["ShowHighlights"].toBool()); - ui.showOwnMessages->setChecked(settings["ShowOwnMsgs"].toBool()); - - // get all available buffer Ids - QList allBufferIds = Client::networkModel()->allBufferIds(); - - if(!settings["Buffers"].toList().isEmpty()) { - QList bufferIdsFromConfig; - // remove all active buffers from the available config - foreach(QVariant v, settings["Buffers"].toList()) { - bufferIdsFromConfig << v.value(); - allBufferIds.removeAll(v.value()); + +void ChatMonitorSettingsPage::load() +{ + if (settings.contains("Default")) + settings.remove("Default"); + else + loadSettings(); + + switchOperationMode(settings["OperationMode"].toInt() - 1); + ui.operationMode->setCurrentIndex(settings["OperationMode"].toInt() - 1); + ui.showHighlights->setChecked(settings["ShowHighlights"].toBool()); + ui.showOwnMessages->setChecked(settings["ShowOwnMsgs"].toBool()); + + // get all available buffer Ids + QList allBufferIds = Client::networkModel()->allBufferIds(); + + if (!settings["Buffers"].toList().isEmpty()) { + QList bufferIdsFromConfig; + // remove all active buffers from the available config + foreach(QVariant v, settings["Buffers"].toList()) { + bufferIdsFromConfig << v.value(); + allBufferIds.removeAll(v.value()); + } + Client::networkModel()->sortBufferIds(bufferIdsFromConfig); + _configActive->initSetBufferList(bufferIdsFromConfig); } - Client::networkModel()->sortBufferIds(bufferIdsFromConfig); - _configActive->initSetBufferList(bufferIdsFromConfig); - } - ui.activeBuffers->setFilteredModel(Client::bufferModel(), _configActive); + ui.activeBuffers->setFilteredModel(Client::bufferModel(), _configActive); - Client::networkModel()->sortBufferIds(allBufferIds); - _configAvailable->initSetBufferList(allBufferIds); - ui.availableBuffers->setFilteredModel(Client::bufferModel(), _configAvailable); + Client::networkModel()->sortBufferIds(allBufferIds); + _configAvailable->initSetBufferList(allBufferIds); + ui.availableBuffers->setFilteredModel(Client::bufferModel(), _configAvailable); - setChangedState(false); + setChangedState(false); } -void ChatMonitorSettingsPage::loadSettings() { - ChatViewSettings chatViewSettings("ChatMonitor"); - settings["OperationMode"] = (ChatViewSettings::OperationMode)chatViewSettings.value("OperationMode", ChatViewSettings::OptOut).toInt(); - settings["ShowHighlights"] = chatViewSettings.value("ShowHighlights", false); - settings["ShowOwnMsgs"] = chatViewSettings.value("ShowOwnMsgs", false); - settings["Buffers"] = chatViewSettings.value("Buffers", QVariantList()); +void ChatMonitorSettingsPage::loadSettings() +{ + ChatViewSettings chatViewSettings("ChatMonitor"); + settings["OperationMode"] = (ChatViewSettings::OperationMode)chatViewSettings.value("OperationMode", ChatViewSettings::OptOut).toInt(); + + settings["ShowHighlights"] = chatViewSettings.value("ShowHighlights", false); + settings["ShowOwnMsgs"] = chatViewSettings.value("ShowOwnMsgs", false); + settings["Buffers"] = chatViewSettings.value("Buffers", QVariantList()); } -void ChatMonitorSettingsPage::save() { - ChatViewSettings chatViewSettings("ChatMonitor"); - // save operation mode - chatViewSettings.setValue("OperationMode", ui.operationMode->currentIndex() + 1); - chatViewSettings.setValue("ShowHighlights", ui.showHighlights->isChecked()); - chatViewSettings.setValue("ShowOwnMsgs", ui.showOwnMessages->isChecked()); - - // save list of active buffers - QVariantList saveableBufferIdList; - foreach(BufferId id, _configActive->bufferList()) { - saveableBufferIdList << QVariant::fromValue(id); - } - - chatViewSettings.setValue("Buffers", saveableBufferIdList); - load(); - setChangedState(false); + +void ChatMonitorSettingsPage::save() +{ + ChatViewSettings chatViewSettings("ChatMonitor"); + // save operation mode + chatViewSettings.setValue("OperationMode", ui.operationMode->currentIndex() + 1); + chatViewSettings.setValue("ShowHighlights", ui.showHighlights->isChecked()); + chatViewSettings.setValue("ShowOwnMsgs", ui.showOwnMessages->isChecked()); + + // save list of active buffers + QVariantList saveableBufferIdList; + foreach(BufferId id, _configActive->bufferList()) { + saveableBufferIdList << QVariant::fromValue(id); + } + + chatViewSettings.setValue("Buffers", saveableBufferIdList); + load(); + setChangedState(false); } -void ChatMonitorSettingsPage::widgetHasChanged() { - bool changed = testHasChanged(); - if(changed != hasChanged()) setChangedState(changed); + +void ChatMonitorSettingsPage::widgetHasChanged() +{ + bool changed = testHasChanged(); + if (changed != hasChanged()) setChangedState(changed); } -bool ChatMonitorSettingsPage::testHasChanged() { - if(settings["OperationMode"].toInt() != ui.operationMode->currentIndex() + 1) - return true; - if(settings["ShowHighlights"].toBool() != ui.showHighlights->isChecked()) - return true; - if(settings["ShowOwnMsgs"].toBool() != ui.showOwnMessages->isChecked()) - return true; - if(_configActive->bufferList().count() != settings["Buffers"].toList().count()) - return true; +bool ChatMonitorSettingsPage::testHasChanged() +{ + if (settings["OperationMode"].toInt() != ui.operationMode->currentIndex() + 1) + return true; + if (settings["ShowHighlights"].toBool() != ui.showHighlights->isChecked()) + return true; + if (settings["ShowOwnMsgs"].toBool() != ui.showOwnMessages->isChecked()) + return true; + + if (_configActive->bufferList().count() != settings["Buffers"].toList().count()) + return true; - QSet uiBufs = _configActive->bufferList().toSet(); - QSet settingsBufs; - foreach(QVariant v, settings["Buffers"].toList()) + QSet uiBufs = _configActive->bufferList().toSet(); + QSet settingsBufs; + foreach(QVariant v, settings["Buffers"].toList()) settingsBufs << v.value(); - if(uiBufs != settingsBufs) - return true; + if (uiBufs != settingsBufs) + return true; - return false; + return false; } + //TODO: - support drag 'n drop // - adding of complete networks(?) @@ -171,72 +187,78 @@ bool ChatMonitorSettingsPage::testHasChanged() { toggleBuffers takes each a bufferView and its config for "input" and "output". Any selected item will be moved over from the input to the output bufferview. */ -void ChatMonitorSettingsPage::toggleBuffers(BufferView *inView, BufferViewConfig *inCfg, BufferView *outView, BufferViewConfig *outCfg) { - - // Fill QMap with selected items ordered by selection row - QMap > selectedBuffers; - foreach(QModelIndex index, inView->selectionModel()->selectedIndexes()) { - BufferId inBufferId = index.data(NetworkModel::BufferIdRole).value(); - if(index.data(NetworkModel::ItemTypeRole) == NetworkModel::NetworkItemType) { - // TODO: - // If item is a network: move over all children and skip other selected items of this node +void ChatMonitorSettingsPage::toggleBuffers(BufferView *inView, BufferViewConfig *inCfg, BufferView *outView, BufferViewConfig *outCfg) +{ + // Fill QMap with selected items ordered by selection row + QMap > selectedBuffers; + foreach(QModelIndex index, inView->selectionModel()->selectedIndexes()) { + BufferId inBufferId = index.data(NetworkModel::BufferIdRole).value(); + if (index.data(NetworkModel::ItemTypeRole) == NetworkModel::NetworkItemType) { + // TODO: + // If item is a network: move over all children and skip other selected items of this node + } + else if (index.data(NetworkModel::ItemTypeRole) == NetworkModel::BufferItemType) { + selectedBuffers[index.parent().row()] << inBufferId; + } } - else if(index.data(NetworkModel::ItemTypeRole) == NetworkModel::BufferItemType) { - selectedBuffers[index.parent().row()] << inBufferId; - } - } - - // clear selection to be able to remove the bufferIds without errors - inView->selectionModel()->clearSelection(); - - /* - Invalidate the BufferViewFilters' configs to get constant add/remove times - even for huge lists. - This can probably be removed whenever BufferViewConfig::bulkAdd or something - like that is available. - */ - qobject_cast(outView->model())->setConfig(0); - qobject_cast(inView->model())->setConfig(0); - - // actually move the ids - foreach (QList list, selectedBuffers) { - foreach (BufferId buffer, list) { - outCfg->addBuffer(buffer,0); - inCfg->removeBuffer(buffer); + + // clear selection to be able to remove the bufferIds without errors + inView->selectionModel()->clearSelection(); + + /* + Invalidate the BufferViewFilters' configs to get constant add/remove times + even for huge lists. + This can probably be removed whenever BufferViewConfig::bulkAdd or something + like that is available. + */ + qobject_cast(outView->model())->setConfig(0); + qobject_cast(inView->model())->setConfig(0); + + // actually move the ids + foreach(QList list, selectedBuffers) { + foreach(BufferId buffer, list) { + outCfg->addBuffer(buffer, 0); + inCfg->removeBuffer(buffer); + } } - } - outView->setFilteredModel(Client::bufferModel(), outCfg); - inView->setFilteredModel(Client::bufferModel(), inCfg); + outView->setFilteredModel(Client::bufferModel(), outCfg); + inView->setFilteredModel(Client::bufferModel(), inCfg); - widgetHasChanged(); + widgetHasChanged(); } -void ChatMonitorSettingsPage::on_activateBuffer_clicked() { - if (ui.availableBuffers->currentIndex().isValid() && ui.availableBuffers->selectionModel()->hasSelection()) { - toggleBuffers(ui.availableBuffers, _configAvailable, ui.activeBuffers, _configActive); - widgetHasChanged(); - } + +void ChatMonitorSettingsPage::on_activateBuffer_clicked() +{ + if (ui.availableBuffers->currentIndex().isValid() && ui.availableBuffers->selectionModel()->hasSelection()) { + toggleBuffers(ui.availableBuffers, _configAvailable, ui.activeBuffers, _configActive); + widgetHasChanged(); + } } -void ChatMonitorSettingsPage::on_deactivateBuffer_clicked() { - if (ui.activeBuffers->currentIndex().isValid() && ui.activeBuffers->selectionModel()->hasSelection()) { - toggleBuffers(ui.activeBuffers, _configActive, ui.availableBuffers, _configAvailable); - widgetHasChanged(); - } + +void ChatMonitorSettingsPage::on_deactivateBuffer_clicked() +{ + if (ui.activeBuffers->currentIndex().isValid() && ui.activeBuffers->selectionModel()->hasSelection()) { + toggleBuffers(ui.activeBuffers, _configActive, ui.availableBuffers, _configAvailable); + widgetHasChanged(); + } } + /* switchOperationMode gets called on combobox signal currentIndexChanged. modeIndex is the row id in combobox itemlist */ -void ChatMonitorSettingsPage::switchOperationMode(int idx) { - ChatViewSettings::OperationMode mode = (ChatViewSettings::OperationMode)(idx + 1); - if(mode == ChatViewSettings::OptIn) { - ui.labelActiveBuffers->setText(tr("Show:")); - } - else if(mode == ChatViewSettings::OptOut) { - ui.labelActiveBuffers->setText(tr("Ignore:")); - } - widgetHasChanged(); +void ChatMonitorSettingsPage::switchOperationMode(int idx) +{ + ChatViewSettings::OperationMode mode = (ChatViewSettings::OperationMode)(idx + 1); + if (mode == ChatViewSettings::OptIn) { + ui.labelActiveBuffers->setText(tr("Show:")); + } + else if (mode == ChatViewSettings::OptOut) { + ui.labelActiveBuffers->setText(tr("Ignore:")); + } + widgetHasChanged(); } diff --git a/src/qtui/settingspages/chatmonitorsettingspage.h b/src/qtui/settingspages/chatmonitorsettingspage.h index 8ee5c0c8..4748aaf1 100644 --- a/src/qtui/settingspages/chatmonitorsettingspage.h +++ b/src/qtui/settingspages/chatmonitorsettingspage.h @@ -28,26 +28,27 @@ class BufferViewConfig; -class ChatMonitorSettingsPage : public SettingsPage { - Q_OBJECT +class ChatMonitorSettingsPage : public SettingsPage +{ + Q_OBJECT - public: +public: ChatMonitorSettingsPage(QWidget *parent = 0); bool hasDefaults() const; - public slots: +public slots: void save(); void load(); void loadSettings(); void defaults(); - private slots: +private slots: void widgetHasChanged(); void on_activateBuffer_clicked(); void on_deactivateBuffer_clicked(); void switchOperationMode(int idx); - private: +private: Ui::ChatMonitorSettingsPage ui; QHash settings; bool testHasChanged(); @@ -56,4 +57,6 @@ class ChatMonitorSettingsPage : public SettingsPage { BufferViewConfig *_configAvailable; BufferViewConfig *_configActive; }; + + #endif diff --git a/src/qtui/settingspages/chatviewsettingspage.cpp b/src/qtui/settingspages/chatviewsettingspage.cpp index fd59024e..fd7b731b 100644 --- a/src/qtui/settingspages/chatviewsettingspage.cpp +++ b/src/qtui/settingspages/chatviewsettingspage.cpp @@ -25,27 +25,29 @@ #include "qtuistyle.h" ChatViewSettingsPage::ChatViewSettingsPage(QWidget *parent) - : SettingsPage(tr("Interface"), tr("Chat View"), parent) + : SettingsPage(tr("Interface"), tr("Chat View"), parent) { - ui.setupUi(this); + ui.setupUi(this); #ifndef HAVE_WEBKIT - ui.showWebPreview->hide(); - ui.showWebPreview->setEnabled(false); + ui.showWebPreview->hide(); + ui.showWebPreview->setEnabled(false); #endif - // FIXME remove with protocol v11 - if(!(Client::coreFeatures() & Quassel::SynchronizedMarkerLine)) { - ui.autoMarkerLine->setEnabled(false); - ui.autoMarkerLine->setChecked(true); - ui.autoMarkerLine->setToolTip(tr("You need at 0.6 quasselcore to use this feature")); - } + // FIXME remove with protocol v11 + if (!(Client::coreFeatures() & Quassel::SynchronizedMarkerLine)) { + ui.autoMarkerLine->setEnabled(false); + ui.autoMarkerLine->setChecked(true); + ui.autoMarkerLine->setToolTip(tr("You need at 0.6 quasselcore to use this feature")); + } - initAutoWidgets(); + initAutoWidgets(); } -void ChatViewSettingsPage::save() { - SettingsPage::save(); - QtUi::style()->generateSettingsQss(); - QtUi::style()->reload(); + +void ChatViewSettingsPage::save() +{ + SettingsPage::save(); + QtUi::style()->generateSettingsQss(); + QtUi::style()->reload(); } diff --git a/src/qtui/settingspages/chatviewsettingspage.h b/src/qtui/settingspages/chatviewsettingspage.h index 70de7f9a..b555d850 100644 --- a/src/qtui/settingspages/chatviewsettingspage.h +++ b/src/qtui/settingspages/chatviewsettingspage.h @@ -26,21 +26,23 @@ class ColorButton; -class ChatViewSettingsPage : public SettingsPage { - Q_OBJECT +class ChatViewSettingsPage : public SettingsPage +{ + Q_OBJECT public: - ChatViewSettingsPage(QWidget *parent = 0); + ChatViewSettingsPage(QWidget *parent = 0); - inline bool hasDefaults() const { return true; } + inline bool hasDefaults() const { return true; } public slots: - void save(); + void save(); private: - Ui::ChatViewSettingsPage ui; + Ui::ChatViewSettingsPage ui; - inline QString settingsKey() const { return QString("QtUi/ChatView/__default__"); } + inline QString settingsKey() const { return QString("QtUi/ChatView/__default__"); } }; + #endif diff --git a/src/qtui/settingspages/connectionsettingspage.cpp b/src/qtui/settingspages/connectionsettingspage.cpp index 969ccd8c..c42e7053 100644 --- a/src/qtui/settingspages/connectionsettingspage.cpp +++ b/src/qtui/settingspages/connectionsettingspage.cpp @@ -24,81 +24,92 @@ #include "networkconfig.h" ConnectionSettingsPage::ConnectionSettingsPage(QWidget *parent) - : SettingsPage(tr("IRC"), QString(), parent) { + : SettingsPage(tr("IRC"), QString(), parent) +{ + ui.setupUi(this); + initAutoWidgets(); - ui.setupUi(this); - initAutoWidgets(); + connect(Client::instance(), SIGNAL(connected()), this, SLOT(clientConnected())); + connect(Client::instance(), SIGNAL(disconnected()), this, SLOT(clientDisconnected())); - connect(Client::instance(), SIGNAL(connected()), this, SLOT(clientConnected())); - connect(Client::instance(), SIGNAL(disconnected()), this, SLOT(clientDisconnected())); - - setEnabled(false); - if(Client::isConnected()) - clientConnected(); + setEnabled(false); + if (Client::isConnected()) + clientConnected(); } -void ConnectionSettingsPage::clientConnected() { - if(Client::networkConfig()->isInitialized()) - initDone(); - else - connect(Client::networkConfig(), SIGNAL(initDone()), SLOT(initDone())); -} -void ConnectionSettingsPage::clientDisconnected() { - setEnabled(false); - setChangedState(false); +void ConnectionSettingsPage::clientConnected() +{ + if (Client::networkConfig()->isInitialized()) + initDone(); + else + connect(Client::networkConfig(), SIGNAL(initDone()), SLOT(initDone())); } -void ConnectionSettingsPage::initDone() { - setEnabled(true); + +void ConnectionSettingsPage::clientDisconnected() +{ + setEnabled(false); + setChangedState(false); } -bool ConnectionSettingsPage::hasDefaults() const { - return true; + +void ConnectionSettingsPage::initDone() +{ + setEnabled(true); } -QVariant ConnectionSettingsPage::loadAutoWidgetValue(const QString &widgetName) { - if(!isEnabled()) - return QVariant(); - NetworkConfig *config = Client::networkConfig(); - if(widgetName == "pingTimeoutEnabled") - return config->pingTimeoutEnabled(); - if(widgetName == "pingInterval") - return config->pingInterval(); - if(widgetName == "maxPingCount") - return config->maxPingCount(); - if(widgetName == "autoWhoEnabled") - return config->autoWhoEnabled(); - if(widgetName == "autoWhoInterval") - return config->autoWhoInterval(); - if(widgetName == "autoWhoNickLimit") - return config->autoWhoNickLimit(); - if(widgetName == "autoWhoDelay") - return config->autoWhoDelay(); - - return SettingsPage::loadAutoWidgetValue(widgetName); + +bool ConnectionSettingsPage::hasDefaults() const +{ + return true; } -void ConnectionSettingsPage::saveAutoWidgetValue(const QString &widgetName, const QVariant &value) { - if(!isEnabled()) - return; - NetworkConfig *config = Client::networkConfig(); - if(widgetName == "pingTimeoutEnabled") - config->requestSetPingTimeoutEnabled(value.toBool()); - else if(widgetName == "pingInterval") - config->requestSetPingInterval(value.toInt()); - else if(widgetName == "maxPingCount") - config->requestSetMaxPingCount(value.toInt()); - else if(widgetName == "autoWhoEnabled") - config->requestSetAutoWhoEnabled(value.toBool()); - else if(widgetName == "autoWhoInterval") - config->requestSetAutoWhoInterval(value.toInt()); - else if(widgetName == "autoWhoNickLimit") - config->requestSetAutoWhoNickLimit(value.toInt()); - else if(widgetName == "autoWhoDelay") - config->requestSetAutoWhoDelay(value.toInt()); - - else - SettingsPage::saveAutoWidgetValue(widgetName, value); + +QVariant ConnectionSettingsPage::loadAutoWidgetValue(const QString &widgetName) +{ + if (!isEnabled()) + return QVariant(); + NetworkConfig *config = Client::networkConfig(); + if (widgetName == "pingTimeoutEnabled") + return config->pingTimeoutEnabled(); + if (widgetName == "pingInterval") + return config->pingInterval(); + if (widgetName == "maxPingCount") + return config->maxPingCount(); + if (widgetName == "autoWhoEnabled") + return config->autoWhoEnabled(); + if (widgetName == "autoWhoInterval") + return config->autoWhoInterval(); + if (widgetName == "autoWhoNickLimit") + return config->autoWhoNickLimit(); + if (widgetName == "autoWhoDelay") + return config->autoWhoDelay(); + + return SettingsPage::loadAutoWidgetValue(widgetName); } + +void ConnectionSettingsPage::saveAutoWidgetValue(const QString &widgetName, const QVariant &value) +{ + if (!isEnabled()) + return; + NetworkConfig *config = Client::networkConfig(); + if (widgetName == "pingTimeoutEnabled") + config->requestSetPingTimeoutEnabled(value.toBool()); + else if (widgetName == "pingInterval") + config->requestSetPingInterval(value.toInt()); + else if (widgetName == "maxPingCount") + config->requestSetMaxPingCount(value.toInt()); + else if (widgetName == "autoWhoEnabled") + config->requestSetAutoWhoEnabled(value.toBool()); + else if (widgetName == "autoWhoInterval") + config->requestSetAutoWhoInterval(value.toInt()); + else if (widgetName == "autoWhoNickLimit") + config->requestSetAutoWhoNickLimit(value.toInt()); + else if (widgetName == "autoWhoDelay") + config->requestSetAutoWhoDelay(value.toInt()); + + else + SettingsPage::saveAutoWidgetValue(widgetName, value); +} diff --git a/src/qtui/settingspages/connectionsettingspage.h b/src/qtui/settingspages/connectionsettingspage.h index 4c86599e..db1ab3e8 100644 --- a/src/qtui/settingspages/connectionsettingspage.h +++ b/src/qtui/settingspages/connectionsettingspage.h @@ -26,27 +26,29 @@ #include "ui_connectionsettingspage.h" -class ConnectionSettingsPage : public SettingsPage { - Q_OBJECT +class ConnectionSettingsPage : public SettingsPage +{ + Q_OBJECT - public: +public: ConnectionSettingsPage(QWidget *parent = 0); bool hasDefaults() const; bool needsCoreConnection() const { return true; } - public slots: +public slots: - private slots: +private slots: void clientConnected(); void clientDisconnected(); void initDone(); - private: +private: QVariant loadAutoWidgetValue(const QString &widgetName); void saveAutoWidgetValue(const QString &widgetName, const QVariant &value); Ui::ConnectionSettingsPage ui; }; + #endif diff --git a/src/qtui/settingspages/coreaccountsettingspage.cpp b/src/qtui/settingspages/coreaccountsettingspage.cpp index 11188ac2..359681f2 100644 --- a/src/qtui/settingspages/coreaccountsettingspage.cpp +++ b/src/qtui/settingspages/coreaccountsettingspage.cpp @@ -26,264 +26,309 @@ #include "iconloader.h" CoreAccountSettingsPage::CoreAccountSettingsPage(QWidget *parent) -: SettingsPage(tr("Remote Cores"), QString(), parent), -_lastAccountId(0), -_lastAutoConnectId(0), -_standalone(false) + : SettingsPage(tr("Remote Cores"), QString(), parent), + _lastAccountId(0), + _lastAutoConnectId(0), + _standalone(false) { - ui.setupUi(this); - initAutoWidgets(); - ui.addAccountButton->setIcon(SmallIcon("list-add")); - ui.editAccountButton->setIcon(SmallIcon("document-edit")); - ui.deleteAccountButton->setIcon(SmallIcon("edit-delete")); + ui.setupUi(this); + initAutoWidgets(); + ui.addAccountButton->setIcon(SmallIcon("list-add")); + ui.editAccountButton->setIcon(SmallIcon("document-edit")); + ui.deleteAccountButton->setIcon(SmallIcon("edit-delete")); - _model = new CoreAccountModel(Client::coreAccountModel(), this); - _filteredModel = new FilteredCoreAccountModel(_model, this); + _model = new CoreAccountModel(Client::coreAccountModel(), this); + _filteredModel = new FilteredCoreAccountModel(_model, this); - ui.accountView->setModel(filteredModel()); - ui.autoConnectAccount->setModel(filteredModel()); + ui.accountView->setModel(filteredModel()); + ui.autoConnectAccount->setModel(filteredModel()); - connect(filteredModel(), SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)), SLOT(rowsAboutToBeRemoved(QModelIndex, int, int))); - connect(filteredModel(), SIGNAL(rowsInserted(QModelIndex, int, int)), SLOT(rowsInserted(QModelIndex, int, int))); + connect(filteredModel(), SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)), SLOT(rowsAboutToBeRemoved(QModelIndex, int, int))); + connect(filteredModel(), SIGNAL(rowsInserted(QModelIndex, int, int)), SLOT(rowsInserted(QModelIndex, int, int))); - connect(ui.accountView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(setWidgetStates())); - connect(ui.autoConnectAccount, SIGNAL(currentIndexChanged(int)), SLOT(widgetHasChanged())); - setWidgetStates(); + connect(ui.accountView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(setWidgetStates())); + connect(ui.autoConnectAccount, SIGNAL(currentIndexChanged(int)), SLOT(widgetHasChanged())); + setWidgetStates(); } -void CoreAccountSettingsPage::setStandAlone(bool standalone) { - _standalone = standalone; + +void CoreAccountSettingsPage::setStandAlone(bool standalone) +{ + _standalone = standalone; } -void CoreAccountSettingsPage::load() { - model()->update(Client::coreAccountModel()); - SettingsPage::load(); - CoreAccountSettings s; +void CoreAccountSettingsPage::load() +{ + model()->update(Client::coreAccountModel()); + SettingsPage::load(); + + CoreAccountSettings s; - if(Quassel::runMode() != Quassel::Monolithic) { - // make sure we don't have selected the internal account as autoconnect account + if (Quassel::runMode() != Quassel::Monolithic) { + // make sure we don't have selected the internal account as autoconnect account - if(s.autoConnectOnStartup() && s.autoConnectToFixedAccount()) { - CoreAccount acc = model()->account(s.autoConnectAccount()); - if(acc.isInternal()) - ui.autoConnectOnStartup->setChecked(false); + if (s.autoConnectOnStartup() && s.autoConnectToFixedAccount()) { + CoreAccount acc = model()->account(s.autoConnectAccount()); + if (acc.isInternal()) + ui.autoConnectOnStartup->setChecked(false); + } } - } - ui.accountView->setCurrentIndex(filteredModel()->index(0, 0)); - ui.accountView->selectionModel()->select(filteredModel()->index(0, 0), QItemSelectionModel::Select); - - QModelIndex idx = filteredModel()->mapFromSource(model()->accountIndex(s.autoConnectAccount())); - ui.autoConnectAccount->setCurrentIndex(idx.isValid() ? idx.row() : 0); - ui.autoConnectAccount->setProperty("storedValue", ui.autoConnectAccount->currentIndex()); - setWidgetStates(); + ui.accountView->setCurrentIndex(filteredModel()->index(0, 0)); + ui.accountView->selectionModel()->select(filteredModel()->index(0, 0), QItemSelectionModel::Select); + + QModelIndex idx = filteredModel()->mapFromSource(model()->accountIndex(s.autoConnectAccount())); + ui.autoConnectAccount->setCurrentIndex(idx.isValid() ? idx.row() : 0); + ui.autoConnectAccount->setProperty("storedValue", ui.autoConnectAccount->currentIndex()); + setWidgetStates(); } -void CoreAccountSettingsPage::save() { - SettingsPage::save(); - Client::coreAccountModel()->update(model()); - Client::coreAccountModel()->save(); - CoreAccountSettings s; - AccountId id = filteredModel()->index(ui.autoConnectAccount->currentIndex(), 0).data(CoreAccountModel::AccountIdRole).value(); - s.setAutoConnectAccount(id); - ui.autoConnectAccount->setProperty("storedValue", ui.autoConnectAccount->currentIndex()); + +void CoreAccountSettingsPage::save() +{ + SettingsPage::save(); + Client::coreAccountModel()->update(model()); + Client::coreAccountModel()->save(); + CoreAccountSettings s; + AccountId id = filteredModel()->index(ui.autoConnectAccount->currentIndex(), 0).data(CoreAccountModel::AccountIdRole).value(); + s.setAutoConnectAccount(id); + ui.autoConnectAccount->setProperty("storedValue", ui.autoConnectAccount->currentIndex()); } + // TODO: Qt 4.6 - replace by proper rowsMoved() semantics // NOTE: This is the filtered model -void CoreAccountSettingsPage::rowsAboutToBeRemoved(const QModelIndex &index, int start, int end) { - _lastAutoConnectId = _lastAccountId = 0; - if(index.isValid() || start != end) - return; - - // the current index is removed, so remember it in case it's reinserted immediately afterwards - AccountId id = filteredModel()->index(start, 0).data(CoreAccountModel::AccountIdRole).value(); - if(start == ui.accountView->currentIndex().row()) - _lastAccountId = id; - if(start == ui.autoConnectAccount->currentIndex()) - _lastAutoConnectId = id; +void CoreAccountSettingsPage::rowsAboutToBeRemoved(const QModelIndex &index, int start, int end) +{ + _lastAutoConnectId = _lastAccountId = 0; + if (index.isValid() || start != end) + return; + + // the current index is removed, so remember it in case it's reinserted immediately afterwards + AccountId id = filteredModel()->index(start, 0).data(CoreAccountModel::AccountIdRole).value(); + if (start == ui.accountView->currentIndex().row()) + _lastAccountId = id; + if (start == ui.autoConnectAccount->currentIndex()) + _lastAutoConnectId = id; } -void CoreAccountSettingsPage::rowsInserted(const QModelIndex &index, int start, int end) { - if(index.isValid() || start != end) - return; - - // check if the inserted index was just removed and select it in that case - AccountId id = filteredModel()->index(start, 0).data(CoreAccountModel::AccountIdRole).value(); - if(id == _lastAccountId) - ui.accountView->setCurrentIndex(filteredModel()->index(start, 0)); - if(id == _lastAutoConnectId) - ui.autoConnectAccount->setCurrentIndex(start); - _lastAccountId = _lastAutoConnectId = 0; + +void CoreAccountSettingsPage::rowsInserted(const QModelIndex &index, int start, int end) +{ + if (index.isValid() || start != end) + return; + + // check if the inserted index was just removed and select it in that case + AccountId id = filteredModel()->index(start, 0).data(CoreAccountModel::AccountIdRole).value(); + if (id == _lastAccountId) + ui.accountView->setCurrentIndex(filteredModel()->index(start, 0)); + if (id == _lastAutoConnectId) + ui.autoConnectAccount->setCurrentIndex(start); + _lastAccountId = _lastAutoConnectId = 0; } -AccountId CoreAccountSettingsPage::selectedAccount() const { - QModelIndex index = ui.accountView->currentIndex(); - if(!index.isValid()) - return 0; - return index.data(CoreAccountModel::AccountIdRole).value(); + +AccountId CoreAccountSettingsPage::selectedAccount() const +{ + QModelIndex index = ui.accountView->currentIndex(); + if (!index.isValid()) + return 0; + return index.data(CoreAccountModel::AccountIdRole).value(); } -void CoreAccountSettingsPage::setSelectedAccount(AccountId accId) { - QModelIndex index = filteredModel()->mapFromSource(model()->accountIndex(accId)); - if(index.isValid()) - ui.accountView->setCurrentIndex(index); + +void CoreAccountSettingsPage::setSelectedAccount(AccountId accId) +{ + QModelIndex index = filteredModel()->mapFromSource(model()->accountIndex(accId)); + if (index.isValid()) + ui.accountView->setCurrentIndex(index); } -void CoreAccountSettingsPage::on_addAccountButton_clicked() { - CoreAccountEditDlg dlg(CoreAccount(), this); - if(dlg.exec() == QDialog::Accepted) { - AccountId id =model()->createOrUpdateAccount(dlg.account()); - ui.accountView->setCurrentIndex(filteredModel()->mapFromSource(model()->accountIndex(id))); - widgetHasChanged(); - } + +void CoreAccountSettingsPage::on_addAccountButton_clicked() +{ + CoreAccountEditDlg dlg(CoreAccount(), this); + if (dlg.exec() == QDialog::Accepted) { + AccountId id = model()->createOrUpdateAccount(dlg.account()); + ui.accountView->setCurrentIndex(filteredModel()->mapFromSource(model()->accountIndex(id))); + widgetHasChanged(); + } } -void CoreAccountSettingsPage::on_editAccountButton_clicked() { - QModelIndex idx = ui.accountView->selectionModel()->currentIndex(); - if(!idx.isValid()) - return; - editAccount(idx); +void CoreAccountSettingsPage::on_editAccountButton_clicked() +{ + QModelIndex idx = ui.accountView->selectionModel()->currentIndex(); + if (!idx.isValid()) + return; + + editAccount(idx); } -void CoreAccountSettingsPage::editAccount(const QModelIndex &index) { - if(!index.isValid()) - return; - CoreAccountEditDlg dlg(model()->account(filteredModel()->mapToSource(index)), this); - if(dlg.exec() == QDialog::Accepted) { - AccountId id = model()->createOrUpdateAccount(dlg.account()); - ui.accountView->setCurrentIndex(filteredModel()->mapFromSource(model()->accountIndex(id))); - widgetHasChanged(); - } +void CoreAccountSettingsPage::editAccount(const QModelIndex &index) +{ + if (!index.isValid()) + return; + + CoreAccountEditDlg dlg(model()->account(filteredModel()->mapToSource(index)), this); + if (dlg.exec() == QDialog::Accepted) { + AccountId id = model()->createOrUpdateAccount(dlg.account()); + ui.accountView->setCurrentIndex(filteredModel()->mapFromSource(model()->accountIndex(id))); + widgetHasChanged(); + } } -void CoreAccountSettingsPage::on_deleteAccountButton_clicked() { - if(!ui.accountView->selectionModel()->selectedIndexes().count()) - return; - AccountId id = ui.accountView->selectionModel()->selectedIndexes().at(0).data(CoreAccountModel::AccountIdRole).value(); - if(id.isValid()) { - model()->removeAccount(id); - widgetHasChanged(); - } +void CoreAccountSettingsPage::on_deleteAccountButton_clicked() +{ + if (!ui.accountView->selectionModel()->selectedIndexes().count()) + return; + + AccountId id = ui.accountView->selectionModel()->selectedIndexes().at(0).data(CoreAccountModel::AccountIdRole).value(); + if (id.isValid()) { + model()->removeAccount(id); + widgetHasChanged(); + } } -void CoreAccountSettingsPage::on_accountView_doubleClicked(const QModelIndex &index) { - if(!index.isValid()) - return; - if(isStandAlone()) - emit connectToCore(index.data(CoreAccountModel::AccountIdRole).value()); - else - editAccount(index); +void CoreAccountSettingsPage::on_accountView_doubleClicked(const QModelIndex &index) +{ + if (!index.isValid()) + return; + + if (isStandAlone()) + emit connectToCore(index.data(CoreAccountModel::AccountIdRole).value()); + else + editAccount(index); } -void CoreAccountSettingsPage::setWidgetStates() { - AccountId accId = selectedAccount(); - bool editable = accId.isValid() && accId != model()->internalAccount(); - ui.editAccountButton->setEnabled(editable); - ui.deleteAccountButton->setEnabled(editable); +void CoreAccountSettingsPage::setWidgetStates() +{ + AccountId accId = selectedAccount(); + bool editable = accId.isValid() && accId != model()->internalAccount(); + + ui.editAccountButton->setEnabled(editable); + ui.deleteAccountButton->setEnabled(editable); } -void CoreAccountSettingsPage::widgetHasChanged() { - setChangedState(testHasChanged()); - setWidgetStates(); + +void CoreAccountSettingsPage::widgetHasChanged() +{ + setChangedState(testHasChanged()); + setWidgetStates(); } -bool CoreAccountSettingsPage::testHasChanged() { - if(ui.autoConnectAccount->currentIndex() != ui.autoConnectAccount->property("storedValue").toInt()) - return true; - if(!(*model() == *Client::coreAccountModel())) - return true; - return false; +bool CoreAccountSettingsPage::testHasChanged() +{ + if (ui.autoConnectAccount->currentIndex() != ui.autoConnectAccount->property("storedValue").toInt()) + return true; + if (!(*model() == *Client::coreAccountModel())) + return true; + + return false; } + /***************************************************************************************** * CoreAccountEditDlg *****************************************************************************************/ CoreAccountEditDlg::CoreAccountEditDlg(const CoreAccount &acct, QWidget *parent) - : QDialog(parent) + : QDialog(parent) { - ui.setupUi(this); - - _account = acct; - - ui.hostName->setText(acct.hostName()); - ui.port->setValue(acct.port()); - ui.accountName->setText(acct.accountName()); - ui.user->setText(acct.user()); - ui.password->setText(acct.password()); - ui.rememberPassword->setChecked(acct.storePassword()); - ui.useProxy->setChecked(acct.useProxy()); - ui.proxyHostName->setText(acct.proxyHostName()); - ui.proxyPort->setValue(acct.proxyPort()); - ui.proxyType->setCurrentIndex(acct.proxyType() == QNetworkProxy::Socks5Proxy ? 0 : 1); - ui.proxyUser->setText(acct.proxyUser()); - ui.proxyPassword->setText(acct.proxyPassword()); - - if(acct.accountId().isValid()) - setWindowTitle(tr("Edit Core Account")); - else - setWindowTitle(tr("Add Core Account")); + ui.setupUi(this); + + _account = acct; + + ui.hostName->setText(acct.hostName()); + ui.port->setValue(acct.port()); + ui.accountName->setText(acct.accountName()); + ui.user->setText(acct.user()); + ui.password->setText(acct.password()); + ui.rememberPassword->setChecked(acct.storePassword()); + ui.useProxy->setChecked(acct.useProxy()); + ui.proxyHostName->setText(acct.proxyHostName()); + ui.proxyPort->setValue(acct.proxyPort()); + ui.proxyType->setCurrentIndex(acct.proxyType() == QNetworkProxy::Socks5Proxy ? 0 : 1); + ui.proxyUser->setText(acct.proxyUser()); + ui.proxyPassword->setText(acct.proxyPassword()); + + if (acct.accountId().isValid()) + setWindowTitle(tr("Edit Core Account")); + else + setWindowTitle(tr("Add Core Account")); } -CoreAccount CoreAccountEditDlg::account() { - _account.setAccountName(ui.accountName->text().trimmed()); - _account.setHostName(ui.hostName->text().trimmed()); - _account.setPort(ui.port->value()); - _account.setUser(ui.user->text().trimmed()); - _account.setPassword(ui.password->text()); - _account.setStorePassword(ui.rememberPassword->isChecked()); - _account.setUseProxy(ui.useProxy->isChecked()); - _account.setProxyHostName(ui.proxyHostName->text().trimmed()); - _account.setProxyPort(ui.proxyPort->value()); - _account.setProxyType(ui.proxyType->currentIndex() == 0 ? QNetworkProxy::Socks5Proxy : QNetworkProxy::HttpProxy); - _account.setProxyUser(ui.proxyUser->text().trimmed()); - _account.setProxyPassword(ui.proxyPassword->text()); - return _account; + +CoreAccount CoreAccountEditDlg::account() +{ + _account.setAccountName(ui.accountName->text().trimmed()); + _account.setHostName(ui.hostName->text().trimmed()); + _account.setPort(ui.port->value()); + _account.setUser(ui.user->text().trimmed()); + _account.setPassword(ui.password->text()); + _account.setStorePassword(ui.rememberPassword->isChecked()); + _account.setUseProxy(ui.useProxy->isChecked()); + _account.setProxyHostName(ui.proxyHostName->text().trimmed()); + _account.setProxyPort(ui.proxyPort->value()); + _account.setProxyType(ui.proxyType->currentIndex() == 0 ? QNetworkProxy::Socks5Proxy : QNetworkProxy::HttpProxy); + _account.setProxyUser(ui.proxyUser->text().trimmed()); + _account.setProxyPassword(ui.proxyPassword->text()); + return _account; } -void CoreAccountEditDlg::setWidgetStates() { - bool ok = !ui.accountName->text().trimmed().isEmpty() - && !ui.user->text().trimmed().isEmpty() - && !ui.hostName->text().isEmpty(); - ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ok); + +void CoreAccountEditDlg::setWidgetStates() +{ + bool ok = !ui.accountName->text().trimmed().isEmpty() + && !ui.user->text().trimmed().isEmpty() + && !ui.hostName->text().isEmpty(); + ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ok); } -void CoreAccountEditDlg::on_hostName_textChanged(const QString &text) { - Q_UNUSED(text); - setWidgetStates(); + +void CoreAccountEditDlg::on_hostName_textChanged(const QString &text) +{ + Q_UNUSED(text); + setWidgetStates(); } -void CoreAccountEditDlg::on_accountName_textChanged(const QString &text) { - Q_UNUSED(text); - setWidgetStates(); + +void CoreAccountEditDlg::on_accountName_textChanged(const QString &text) +{ + Q_UNUSED(text); + setWidgetStates(); } -void CoreAccountEditDlg::on_user_textChanged(const QString &text) { - Q_UNUSED(text) - setWidgetStates(); + +void CoreAccountEditDlg::on_user_textChanged(const QString &text) +{ + Q_UNUSED(text) + setWidgetStates(); } + /***************************************************************************************** * FilteredCoreAccountModel *****************************************************************************************/ -FilteredCoreAccountModel::FilteredCoreAccountModel(CoreAccountModel *model, QObject *parent) : QSortFilterProxyModel(parent) { - _internalAccount = model->internalAccount(); - setSourceModel(model); +FilteredCoreAccountModel::FilteredCoreAccountModel(CoreAccountModel *model, QObject *parent) : QSortFilterProxyModel(parent) +{ + _internalAccount = model->internalAccount(); + setSourceModel(model); } -bool FilteredCoreAccountModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { - if(Quassel::runMode() == Quassel::Monolithic) - return true; - if(!_internalAccount.isValid()) - return true; +bool FilteredCoreAccountModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const +{ + if (Quassel::runMode() == Quassel::Monolithic) + return true; + + if (!_internalAccount.isValid()) + return true; - return _internalAccount != sourceModel()->index(source_row, 0, source_parent).data(CoreAccountModel::AccountIdRole).value(); + return _internalAccount != sourceModel()->index(source_row, 0, source_parent).data(CoreAccountModel::AccountIdRole).value(); } diff --git a/src/qtui/settingspages/coreaccountsettingspage.h b/src/qtui/settingspages/coreaccountsettingspage.h index f28e01f0..591ed0d6 100644 --- a/src/qtui/settingspages/coreaccountsettingspage.h +++ b/src/qtui/settingspages/coreaccountsettingspage.h @@ -33,10 +33,11 @@ class CoreAccountModel; class FilteredCoreAccountModel; -class CoreAccountSettingsPage : public SettingsPage { - Q_OBJECT +class CoreAccountSettingsPage : public SettingsPage +{ + Q_OBJECT - public: +public: CoreAccountSettingsPage(QWidget *parent = 0); inline bool hasDefaults() const { return false; } @@ -44,7 +45,7 @@ class CoreAccountSettingsPage : public SettingsPage { AccountId selectedAccount() const; - public slots: +public slots: void save(); void load(); @@ -54,7 +55,7 @@ class CoreAccountSettingsPage : public SettingsPage { signals: void connectToCore(AccountId accId); - private slots: +private slots: void on_addAccountButton_clicked(); void on_editAccountButton_clicked(); void on_deleteAccountButton_clicked(); @@ -66,7 +67,7 @@ signals: void rowsAboutToBeRemoved(const QModelIndex &index, int start, int end); void rowsInserted(const QModelIndex &index, int start, int end); - private: +private: Ui::CoreAccountSettingsPage ui; CoreAccountModel *_model; @@ -84,45 +85,50 @@ signals: inline QString settingsKey() const { return QString("CoreAccounts"); } }; + // ======================================== // CoreAccountEditDlg // ======================================== -class CoreAccountEditDlg : public QDialog { - Q_OBJECT +class CoreAccountEditDlg : public QDialog +{ + Q_OBJECT public: - CoreAccountEditDlg(const CoreAccount &account, QWidget *parent = 0); + CoreAccountEditDlg(const CoreAccount &account, QWidget *parent = 0); - CoreAccount account(); + CoreAccount account(); private slots: - void on_hostName_textChanged(const QString &); - void on_accountName_textChanged(const QString &); - void on_user_textChanged(const QString &); + void on_hostName_textChanged(const QString &); + void on_accountName_textChanged(const QString &); + void on_user_textChanged(const QString &); - void setWidgetStates(); + void setWidgetStates(); private: - Ui::CoreAccountEditDlg ui; - CoreAccount _account; + Ui::CoreAccountEditDlg ui; + CoreAccount _account; }; + // ======================================== // FilteredCoreAccountModel // ======================================== //! This filters out the internal account from the non-monolithic client's UI -class FilteredCoreAccountModel : public QSortFilterProxyModel { - Q_OBJECT +class FilteredCoreAccountModel : public QSortFilterProxyModel +{ + Q_OBJECT public: - FilteredCoreAccountModel(CoreAccountModel *model, QObject *parent = 0); + FilteredCoreAccountModel(CoreAccountModel *model, QObject *parent = 0); protected: - virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; + virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; private: - AccountId _internalAccount; + AccountId _internalAccount; }; + #endif diff --git a/src/qtui/settingspages/coreconnectionsettingspage.cpp b/src/qtui/settingspages/coreconnectionsettingspage.cpp index c3b78059..be48d28d 100644 --- a/src/qtui/settingspages/coreconnectionsettingspage.cpp +++ b/src/qtui/settingspages/coreconnectionsettingspage.cpp @@ -21,74 +21,87 @@ #include "coreconnectionsettingspage.h" CoreConnectionSettingsPage::CoreConnectionSettingsPage(QWidget *parent) - : SettingsPage(tr("Remote Cores"), tr("Connection"), parent) { - ui.setupUi(this); + : SettingsPage(tr("Remote Cores"), tr("Connection"), parent) +{ + ui.setupUi(this); #ifndef HAVE_KDE - ui.useSolid->hide(); + ui.useSolid->hide(); #endif - initAutoWidgets(); + initAutoWidgets(); - connect(ui.useSolid, SIGNAL(toggled(bool)), SLOT(widgetHasChanged())); - connect(ui.usePingTimeout, SIGNAL(toggled(bool)), SLOT(widgetHasChanged())); - connect(ui.useNoTimeout, SIGNAL(toggled(bool)), SLOT(widgetHasChanged())); + connect(ui.useSolid, SIGNAL(toggled(bool)), SLOT(widgetHasChanged())); + connect(ui.usePingTimeout, SIGNAL(toggled(bool)), SLOT(widgetHasChanged())); + connect(ui.useNoTimeout, SIGNAL(toggled(bool)), SLOT(widgetHasChanged())); } -void CoreConnectionSettingsPage::widgetHasChanged() { - bool hasChanged = false; - CoreConnectionSettings::NetworkDetectionMode mode = modeFromRadioButtons(); - if(mode != _detectionMode) - hasChanged = true; - setChangedState(hasChanged); +void CoreConnectionSettingsPage::widgetHasChanged() +{ + bool hasChanged = false; + CoreConnectionSettings::NetworkDetectionMode mode = modeFromRadioButtons(); + if (mode != _detectionMode) + hasChanged = true; + + setChangedState(hasChanged); } -void CoreConnectionSettingsPage::defaults() { + +void CoreConnectionSettingsPage::defaults() +{ #ifdef HAVE_KDE - setRadioButtons(CoreConnectionSettings::UseSolid); + setRadioButtons(CoreConnectionSettings::UseSolid); #else - setRadioButtons(CoreConnectionSettings::UsePingTimeout); + setRadioButtons(CoreConnectionSettings::UsePingTimeout); #endif - SettingsPage::defaults(); + SettingsPage::defaults(); } -void CoreConnectionSettingsPage::load() { - CoreConnectionSettings s; - _detectionMode = s.networkDetectionMode(); - setRadioButtons(_detectionMode); - SettingsPage::load(); + +void CoreConnectionSettingsPage::load() +{ + CoreConnectionSettings s; + _detectionMode = s.networkDetectionMode(); + setRadioButtons(_detectionMode); + SettingsPage::load(); } -void CoreConnectionSettingsPage::save() { - _detectionMode = modeFromRadioButtons(); - CoreConnectionSettings s; - s.setNetworkDetectionMode(_detectionMode); - SettingsPage::save(); + +void CoreConnectionSettingsPage::save() +{ + _detectionMode = modeFromRadioButtons(); + CoreConnectionSettings s; + s.setNetworkDetectionMode(_detectionMode); + SettingsPage::save(); } -void CoreConnectionSettingsPage::setRadioButtons(CoreConnectionSettings::NetworkDetectionMode mode) { - switch(mode) { + +void CoreConnectionSettingsPage::setRadioButtons(CoreConnectionSettings::NetworkDetectionMode mode) +{ + switch (mode) { #ifdef HAVE_KDE - case CoreConnectionSettings::UseSolid: - ui.useSolid->setChecked(true); - break; + case CoreConnectionSettings::UseSolid: + ui.useSolid->setChecked(true); + break; #endif - case CoreConnectionSettings::UsePingTimeout: - ui.usePingTimeout->setChecked(true); - break; - default: - ui.useNoTimeout->setChecked(true); - } + case CoreConnectionSettings::UsePingTimeout: + ui.usePingTimeout->setChecked(true); + break; + default: + ui.useNoTimeout->setChecked(true); + } } -CoreConnectionSettings::NetworkDetectionMode CoreConnectionSettingsPage::modeFromRadioButtons() const { + +CoreConnectionSettings::NetworkDetectionMode CoreConnectionSettingsPage::modeFromRadioButtons() const +{ #ifdef HAVE_KDE - if(ui.useSolid->isChecked()) - return CoreConnectionSettings::UseSolid; + if (ui.useSolid->isChecked()) + return CoreConnectionSettings::UseSolid; #endif - if(ui.usePingTimeout->isChecked()) - return CoreConnectionSettings::UsePingTimeout; + if (ui.usePingTimeout->isChecked()) + return CoreConnectionSettings::UsePingTimeout; - return CoreConnectionSettings::NoActiveDetection; + return CoreConnectionSettings::NoActiveDetection; } diff --git a/src/qtui/settingspages/coreconnectionsettingspage.h b/src/qtui/settingspages/coreconnectionsettingspage.h index 58d2966d..771876f1 100644 --- a/src/qtui/settingspages/coreconnectionsettingspage.h +++ b/src/qtui/settingspages/coreconnectionsettingspage.h @@ -26,32 +26,34 @@ #include "ui_coreconnectionsettingspage.h" -class CoreConnectionSettingsPage : public SettingsPage { - Q_OBJECT +class CoreConnectionSettingsPage : public SettingsPage +{ + Q_OBJECT public: - CoreConnectionSettingsPage(QWidget *parent = 0); + CoreConnectionSettingsPage(QWidget *parent = 0); - inline bool hasDefaults() const { return true; } + inline bool hasDefaults() const { return true; } public slots: - void save(); - void load(); - void defaults(); + void save(); + void load(); + void defaults(); signals: private slots: - void widgetHasChanged(); + void widgetHasChanged(); private: - Ui::CoreConnectionSettingsPage ui; - CoreConnectionSettings::NetworkDetectionMode _detectionMode; + Ui::CoreConnectionSettingsPage ui; + CoreConnectionSettings::NetworkDetectionMode _detectionMode; - void setRadioButtons(CoreConnectionSettings::NetworkDetectionMode mode); - CoreConnectionSettings::NetworkDetectionMode modeFromRadioButtons() const; + void setRadioButtons(CoreConnectionSettings::NetworkDetectionMode mode); + CoreConnectionSettings::NetworkDetectionMode modeFromRadioButtons() const; - inline QString settingsKey() const { return QString("CoreConnection"); } + inline QString settingsKey() const { return QString("CoreConnection"); } }; + #endif diff --git a/src/qtui/settingspages/highlightsettingspage.cpp b/src/qtui/settingspages/highlightsettingspage.cpp index 5005b3d4..cbd43d24 100644 --- a/src/qtui/settingspages/highlightsettingspage.cpp +++ b/src/qtui/settingspages/highlightsettingspage.cpp @@ -25,242 +25,264 @@ #include - HighlightSettingsPage::HighlightSettingsPage(QWidget *parent) - : SettingsPage(tr("Interface"), tr("Highlight"), parent) { - ui.setupUi(this); - ui.highlightTable->verticalHeader()->hide(); - ui.highlightTable->setShowGrid(false); - - ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::RegExColumn)->setToolTip("RegEx: This option determines if the highlight rule should be interpreted as a regular expression or just as a keyword."); - ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::RegExColumn)->setWhatsThis("RegEx: This option determines if the highlight rule should be interpreted as a regular expression or just as a keyword."); - - ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::CsColumn)->setToolTip("CS: This option determines if the highlight rule should be interpreted case sensitive."); - ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::CsColumn)->setWhatsThis("CS: This option determines if the highlight rule should be interpreted case sensitive."); - - ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::ChanColumn)->setToolTip("Channel: This regular expression determines for which channels the highlight rule works. Leave blank to match any channel. Put ! in the beginning to negate. Case insensitive."); - ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::ChanColumn)->setWhatsThis("Channel: This regular expression determines for which channels the highlight rule works. Leave blank to match any channel. Put ! in the beginning to negate. Case insensitive."); - - ui.highlightTable->horizontalHeader()->setResizeMode(HighlightSettingsPage::NameColumn, QHeaderView::Stretch); - ui.highlightTable->horizontalHeader()->setResizeMode(HighlightSettingsPage::RegExColumn, QHeaderView::ResizeToContents); - ui.highlightTable->horizontalHeader()->setResizeMode(HighlightSettingsPage::CsColumn, QHeaderView::ResizeToContents); - ui.highlightTable->horizontalHeader()->setResizeMode(HighlightSettingsPage::EnableColumn, QHeaderView::ResizeToContents); - ui.highlightTable->horizontalHeader()->setResizeMode(HighlightSettingsPage::ChanColumn, QHeaderView::ResizeToContents); - - connect(ui.add, SIGNAL(clicked(bool)), this, SLOT(addNewRow())); - connect(ui.remove, SIGNAL(clicked(bool)), this, SLOT(removeSelectedRows())); - //TODO: search for a better signal (one that emits everytime a selection has been changed for one item) - connect(ui.highlightTable, SIGNAL(itemClicked(QTableWidgetItem *)), this, SLOT(selectRow(QTableWidgetItem *))); - - connect(ui.highlightAllNicks, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.highlightCurrentNick, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.highlightNoNick, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.nicksCaseSensitive, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.add, SIGNAL(clicked()), this, SLOT(widgetHasChanged())); - connect(ui.remove, SIGNAL(clicked()), this, SLOT(widgetHasChanged())); - connect(ui.highlightTable, SIGNAL(itemChanged(QTableWidgetItem *)), this, SLOT(tableChanged(QTableWidgetItem *))); + : SettingsPage(tr("Interface"), tr("Highlight"), parent) +{ + ui.setupUi(this); + ui.highlightTable->verticalHeader()->hide(); + ui.highlightTable->setShowGrid(false); + + ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::RegExColumn)->setToolTip("RegEx: This option determines if the highlight rule should be interpreted as a regular expression or just as a keyword."); + ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::RegExColumn)->setWhatsThis("RegEx: This option determines if the highlight rule should be interpreted as a regular expression or just as a keyword."); + + ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::CsColumn)->setToolTip("CS: This option determines if the highlight rule should be interpreted case sensitive."); + ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::CsColumn)->setWhatsThis("CS: This option determines if the highlight rule should be interpreted case sensitive."); + + ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::ChanColumn)->setToolTip("Channel: This regular expression determines for which channels the highlight rule works. Leave blank to match any channel. Put ! in the beginning to negate. Case insensitive."); + ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::ChanColumn)->setWhatsThis("Channel: This regular expression determines for which channels the highlight rule works. Leave blank to match any channel. Put ! in the beginning to negate. Case insensitive."); + + ui.highlightTable->horizontalHeader()->setResizeMode(HighlightSettingsPage::NameColumn, QHeaderView::Stretch); + ui.highlightTable->horizontalHeader()->setResizeMode(HighlightSettingsPage::RegExColumn, QHeaderView::ResizeToContents); + ui.highlightTable->horizontalHeader()->setResizeMode(HighlightSettingsPage::CsColumn, QHeaderView::ResizeToContents); + ui.highlightTable->horizontalHeader()->setResizeMode(HighlightSettingsPage::EnableColumn, QHeaderView::ResizeToContents); + ui.highlightTable->horizontalHeader()->setResizeMode(HighlightSettingsPage::ChanColumn, QHeaderView::ResizeToContents); + + connect(ui.add, SIGNAL(clicked(bool)), this, SLOT(addNewRow())); + connect(ui.remove, SIGNAL(clicked(bool)), this, SLOT(removeSelectedRows())); + //TODO: search for a better signal (one that emits everytime a selection has been changed for one item) + connect(ui.highlightTable, SIGNAL(itemClicked(QTableWidgetItem *)), this, SLOT(selectRow(QTableWidgetItem *))); + + connect(ui.highlightAllNicks, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.highlightCurrentNick, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.highlightNoNick, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.nicksCaseSensitive, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.add, SIGNAL(clicked()), this, SLOT(widgetHasChanged())); + connect(ui.remove, SIGNAL(clicked()), this, SLOT(widgetHasChanged())); + connect(ui.highlightTable, SIGNAL(itemChanged(QTableWidgetItem *)), this, SLOT(tableChanged(QTableWidgetItem *))); } -bool HighlightSettingsPage::hasDefaults() const { - return true; + +bool HighlightSettingsPage::hasDefaults() const +{ + return true; } -void HighlightSettingsPage::defaults() { - ui.highlightCurrentNick->setChecked(true); - ui.nicksCaseSensitive->setChecked(false); - emptyTable(); - widgetHasChanged(); +void HighlightSettingsPage::defaults() +{ + ui.highlightCurrentNick->setChecked(true); + ui.nicksCaseSensitive->setChecked(false); + emptyTable(); + + widgetHasChanged(); } -void HighlightSettingsPage::addNewRow(QString name, bool regex, bool cs, bool enable, QString chanName, bool self) { - ui.highlightTable->setRowCount(ui.highlightTable->rowCount()+1); - - QTableWidgetItem *nameItem = new QTableWidgetItem(name); - - QTableWidgetItem *regexItem = new QTableWidgetItem(""); - if(regex) - regexItem->setCheckState(Qt::Checked); - else - regexItem->setCheckState(Qt::Unchecked); - regexItem->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable); - - QTableWidgetItem *csItem = new QTableWidgetItem(""); - if(cs) - csItem->setCheckState(Qt::Checked); - else - csItem->setCheckState(Qt::Unchecked); - csItem->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable); - - QTableWidgetItem *enableItem = new QTableWidgetItem(""); - if(enable) - enableItem->setCheckState(Qt::Checked); - else - enableItem->setCheckState(Qt::Unchecked); - enableItem->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable); - - QTableWidgetItem *chanNameItem = new QTableWidgetItem(chanName); - - int lastRow = ui.highlightTable->rowCount()-1; - ui.highlightTable->setItem(lastRow, HighlightSettingsPage::NameColumn, nameItem); - ui.highlightTable->setItem(lastRow, HighlightSettingsPage::RegExColumn, regexItem); - ui.highlightTable->setItem(lastRow, HighlightSettingsPage::CsColumn, csItem); - ui.highlightTable->setItem(lastRow, HighlightSettingsPage::EnableColumn, enableItem); - ui.highlightTable->setItem(lastRow, HighlightSettingsPage::ChanColumn, chanNameItem); - - if(!self) - ui.highlightTable->setCurrentItem(nameItem); - - QVariantMap highlightRule; - highlightRule["Name"] = name; - highlightRule["RegEx"] = regex; - highlightRule["CS"] = cs; - highlightRule["Enable"] = enable; - highlightRule["Channel"] = chanName; - - highlightList.append(highlightRule); + +void HighlightSettingsPage::addNewRow(QString name, bool regex, bool cs, bool enable, QString chanName, bool self) +{ + ui.highlightTable->setRowCount(ui.highlightTable->rowCount()+1); + + QTableWidgetItem *nameItem = new QTableWidgetItem(name); + + QTableWidgetItem *regexItem = new QTableWidgetItem(""); + if (regex) + regexItem->setCheckState(Qt::Checked); + else + regexItem->setCheckState(Qt::Unchecked); + regexItem->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable); + + QTableWidgetItem *csItem = new QTableWidgetItem(""); + if (cs) + csItem->setCheckState(Qt::Checked); + else + csItem->setCheckState(Qt::Unchecked); + csItem->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable); + + QTableWidgetItem *enableItem = new QTableWidgetItem(""); + if (enable) + enableItem->setCheckState(Qt::Checked); + else + enableItem->setCheckState(Qt::Unchecked); + enableItem->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable); + + QTableWidgetItem *chanNameItem = new QTableWidgetItem(chanName); + + int lastRow = ui.highlightTable->rowCount()-1; + ui.highlightTable->setItem(lastRow, HighlightSettingsPage::NameColumn, nameItem); + ui.highlightTable->setItem(lastRow, HighlightSettingsPage::RegExColumn, regexItem); + ui.highlightTable->setItem(lastRow, HighlightSettingsPage::CsColumn, csItem); + ui.highlightTable->setItem(lastRow, HighlightSettingsPage::EnableColumn, enableItem); + ui.highlightTable->setItem(lastRow, HighlightSettingsPage::ChanColumn, chanNameItem); + + if (!self) + ui.highlightTable->setCurrentItem(nameItem); + + QVariantMap highlightRule; + highlightRule["Name"] = name; + highlightRule["RegEx"] = regex; + highlightRule["CS"] = cs; + highlightRule["Enable"] = enable; + highlightRule["Channel"] = chanName; + + highlightList.append(highlightRule); } -void HighlightSettingsPage::removeSelectedRows() { - QList selectedRows; - QList selectedItemList = ui.highlightTable->selectedItems(); - foreach(QTableWidgetItem *selectedItem, selectedItemList) { - selectedRows.append(selectedItem->row()); - } - qSort(selectedRows.begin(), selectedRows.end(), qGreater()); - int lastRow = -1; - foreach(int row, selectedRows) { - if(row != lastRow) { - ui.highlightTable->removeRow(row); - highlightList.removeAt(row); + +void HighlightSettingsPage::removeSelectedRows() +{ + QList selectedRows; + QList selectedItemList = ui.highlightTable->selectedItems(); + foreach(QTableWidgetItem *selectedItem, selectedItemList) { + selectedRows.append(selectedItem->row()); + } + qSort(selectedRows.begin(), selectedRows.end(), qGreater()); + int lastRow = -1; + foreach(int row, selectedRows) { + if (row != lastRow) { + ui.highlightTable->removeRow(row); + highlightList.removeAt(row); + } + lastRow = row; } - lastRow = row; - } } -void HighlightSettingsPage::selectRow(QTableWidgetItem *item) { - int row = item->row(); - bool selected = item->isSelected(); - ui.highlightTable->setRangeSelected(QTableWidgetSelectionRange(row, 0, row, HighlightSettingsPage::ColumnCount-1), selected); + +void HighlightSettingsPage::selectRow(QTableWidgetItem *item) +{ + int row = item->row(); + bool selected = item->isSelected(); + ui.highlightTable->setRangeSelected(QTableWidgetSelectionRange(row, 0, row, HighlightSettingsPage::ColumnCount-1), selected); } -void HighlightSettingsPage::emptyTable() { - // ui.highlight and highlightList should have the same size, but just to make sure. - if(ui.highlightTable->rowCount() != highlightList.size()) { - qDebug() << "something is wrong: ui.highlight and highlightList don't have the same size!"; - } - while(ui.highlightTable->rowCount()) { - ui.highlightTable->removeRow(0); - } - while(highlightList.size()) { + +void HighlightSettingsPage::emptyTable() +{ + // ui.highlight and highlightList should have the same size, but just to make sure. + if (ui.highlightTable->rowCount() != highlightList.size()) { + qDebug() << "something is wrong: ui.highlight and highlightList don't have the same size!"; + } + while (ui.highlightTable->rowCount()) { + ui.highlightTable->removeRow(0); + } + while (highlightList.size()) { highlightList.removeLast(); - } + } } -void HighlightSettingsPage::tableChanged(QTableWidgetItem *item) { - if(item->row()+1 > highlightList.size()) - return; - QVariantMap highlightRule = highlightList.value(item->row()).toMap(); +void HighlightSettingsPage::tableChanged(QTableWidgetItem *item) +{ + if (item->row()+1 > highlightList.size()) + return; + + QVariantMap highlightRule = highlightList.value(item->row()).toMap(); - switch(item->column()) - { + switch (item->column()) + { case HighlightSettingsPage::NameColumn: - if(item->text() == "") - item->setText(tr("this shouldn't be empty")); - highlightRule["Name"] = item->text(); - break; + if (item->text() == "") + item->setText(tr("this shouldn't be empty")); + highlightRule["Name"] = item->text(); + break; case HighlightSettingsPage::RegExColumn: - highlightRule["RegEx"] = (item->checkState() == Qt::Checked); - break; + highlightRule["RegEx"] = (item->checkState() == Qt::Checked); + break; case HighlightSettingsPage::CsColumn: - highlightRule["CS"] = (item->checkState() == Qt::Checked); - break; + highlightRule["CS"] = (item->checkState() == Qt::Checked); + break; case HighlightSettingsPage::EnableColumn: - highlightRule["Enable"] = (item->checkState() == Qt::Checked); - break; + highlightRule["Enable"] = (item->checkState() == Qt::Checked); + break; case HighlightSettingsPage::ChanColumn: - if(!item->text().isEmpty() && item->text().trimmed().isEmpty()) - item->setText(""); - highlightRule["Channel"] = item->text(); - break; - } - highlightList[item->row()] = highlightRule; - emit widgetHasChanged(); + if (!item->text().isEmpty() && item->text().trimmed().isEmpty()) + item->setText(""); + highlightRule["Channel"] = item->text(); + break; + } + highlightList[item->row()] = highlightRule; + emit widgetHasChanged(); } -void HighlightSettingsPage::load() { - NotificationSettings notificationSettings; - emptyTable(); +void HighlightSettingsPage::load() +{ + NotificationSettings notificationSettings; - foreach(QVariant highlight, notificationSettings.highlightList()) { - QVariantMap highlightRule = highlight.toMap(); - QString name = highlightRule["Name"].toString(); - bool regex = highlightRule["RegEx"].toBool(); - bool cs = highlightRule["CS"].toBool(); - bool enable = highlightRule["Enable"].toBool(); - QString chanName = highlightRule["Channel"].toString(); + emptyTable(); - addNewRow(name, regex, cs, enable, chanName, true); - } + foreach(QVariant highlight, notificationSettings.highlightList()) { + QVariantMap highlightRule = highlight.toMap(); + QString name = highlightRule["Name"].toString(); + bool regex = highlightRule["RegEx"].toBool(); + bool cs = highlightRule["CS"].toBool(); + bool enable = highlightRule["Enable"].toBool(); + QString chanName = highlightRule["Channel"].toString(); + + addNewRow(name, regex, cs, enable, chanName, true); + } - switch(notificationSettings.highlightNick()) - { + switch (notificationSettings.highlightNick()) + { case NotificationSettings::NoNick: - ui.highlightNoNick->setChecked(true); - break; + ui.highlightNoNick->setChecked(true); + break; case NotificationSettings::CurrentNick: - ui.highlightCurrentNick->setChecked(true); - break; + ui.highlightCurrentNick->setChecked(true); + break; case NotificationSettings::AllNicks: - ui.highlightAllNicks->setChecked(true); - break; - } - ui.nicksCaseSensitive->setChecked(notificationSettings.nicksCaseSensitive()); + ui.highlightAllNicks->setChecked(true); + break; + } + ui.nicksCaseSensitive->setChecked(notificationSettings.nicksCaseSensitive()); - setChangedState(false); + setChangedState(false); } -void HighlightSettingsPage::save() { - NotificationSettings notificationSettings; - notificationSettings.setHighlightList(highlightList); - NotificationSettings::HighlightNickType highlightNickType; - if(ui.highlightNoNick->isChecked()) - highlightNickType = NotificationSettings::NoNick; - if(ui.highlightCurrentNick->isChecked()) - highlightNickType = NotificationSettings::CurrentNick; - if(ui.highlightAllNicks->isChecked()) - highlightNickType = NotificationSettings::AllNicks; +void HighlightSettingsPage::save() +{ + NotificationSettings notificationSettings; + notificationSettings.setHighlightList(highlightList); + + NotificationSettings::HighlightNickType highlightNickType; + if (ui.highlightNoNick->isChecked()) + highlightNickType = NotificationSettings::NoNick; + if (ui.highlightCurrentNick->isChecked()) + highlightNickType = NotificationSettings::CurrentNick; + if (ui.highlightAllNicks->isChecked()) + highlightNickType = NotificationSettings::AllNicks; - notificationSettings.setHighlightNick(highlightNickType); - notificationSettings.setNicksCaseSensitive(ui.nicksCaseSensitive->isChecked()); + notificationSettings.setHighlightNick(highlightNickType); + notificationSettings.setNicksCaseSensitive(ui.nicksCaseSensitive->isChecked()); - load(); - setChangedState(false); + load(); + setChangedState(false); } -void HighlightSettingsPage::widgetHasChanged() { - bool changed = testHasChanged(); - if(changed != hasChanged()) setChangedState(changed); + +void HighlightSettingsPage::widgetHasChanged() +{ + bool changed = testHasChanged(); + if (changed != hasChanged()) setChangedState(changed); } -bool HighlightSettingsPage::testHasChanged() { - NotificationSettings notificationSettings; - NotificationSettings::HighlightNickType highlightNickType; - if(ui.highlightNoNick->isChecked()) - highlightNickType = NotificationSettings::NoNick; - if(ui.highlightCurrentNick->isChecked()) - highlightNickType = NotificationSettings::CurrentNick; - if(ui.highlightAllNicks->isChecked()) - highlightNickType = NotificationSettings::AllNicks; +bool HighlightSettingsPage::testHasChanged() +{ + NotificationSettings notificationSettings; + + NotificationSettings::HighlightNickType highlightNickType; + if (ui.highlightNoNick->isChecked()) + highlightNickType = NotificationSettings::NoNick; + if (ui.highlightCurrentNick->isChecked()) + highlightNickType = NotificationSettings::CurrentNick; + if (ui.highlightAllNicks->isChecked()) + highlightNickType = NotificationSettings::AllNicks; - if(notificationSettings.highlightNick() != highlightNickType) return true; - if(notificationSettings.nicksCaseSensitive() != ui.nicksCaseSensitive->isChecked()) return true; + if (notificationSettings.highlightNick() != highlightNickType) return true; + if (notificationSettings.nicksCaseSensitive() != ui.nicksCaseSensitive->isChecked()) return true; - if(notificationSettings.highlightList() != highlightList) return true; + if (notificationSettings.highlightList() != highlightList) return true; - return false; + return false; } diff --git a/src/qtui/settingspages/highlightsettingspage.h b/src/qtui/settingspages/highlightsettingspage.h index d4fd3d3a..29d8c1f8 100644 --- a/src/qtui/settingspages/highlightsettingspage.h +++ b/src/qtui/settingspages/highlightsettingspage.h @@ -27,40 +27,41 @@ #include "settingspage.h" #include "ui_highlightsettingspage.h" -class HighlightSettingsPage : public SettingsPage { - Q_OBJECT +class HighlightSettingsPage : public SettingsPage +{ + Q_OBJECT - public: +public: HighlightSettingsPage(QWidget *parent = 0); bool hasDefaults() const; - public slots: +public slots: void save(); void load(); void defaults(); - private slots: +private slots: void widgetHasChanged(); void addNewRow(QString name = tr("highlight rule"), bool regex = false, bool cs = true, bool enable = true, QString chanName = "", bool self = false); void removeSelectedRows(); void selectRow(QTableWidgetItem *item); void tableChanged(QTableWidgetItem *item); - private: +private: Ui::HighlightSettingsPage ui; - QVariantList highlightList; + QVariantList highlightList; // QVariant -> QHash: // regex: bool // name: QString // enable: bool enum column { - NameColumn = 0, - RegExColumn = 1, - CsColumn = 2, - EnableColumn = 3, - ChanColumn = 4, - ColumnCount = 5 + NameColumn = 0, + RegExColumn = 1, + CsColumn = 2, + EnableColumn = 3, + ChanColumn = 4, + ColumnCount = 5 }; void emptyTable(); @@ -68,4 +69,5 @@ class HighlightSettingsPage : public SettingsPage { bool testHasChanged(); }; + #endif diff --git a/src/qtui/settingspages/identitiessettingspage.cpp b/src/qtui/settingspages/identitiessettingspage.cpp index 55be6917..3e61f478 100644 --- a/src/qtui/settingspages/identitiessettingspage.cpp +++ b/src/qtui/settingspages/identitiessettingspage.cpp @@ -28,408 +28,463 @@ #include "signalproxy.h" IdentitiesSettingsPage::IdentitiesSettingsPage(QWidget *parent) - : SettingsPage(tr("IRC"), tr("Identities"), parent), + : SettingsPage(tr("IRC"), tr("Identities"), parent), _editSsl(false) { - ui.setupUi(this); - ui.renameIdentity->setIcon(BarIcon("edit-rename")); - ui.addIdentity->setIcon(BarIcon("list-add-user")); - ui.deleteIdentity->setIcon(BarIcon("list-remove-user")); + ui.setupUi(this); + ui.renameIdentity->setIcon(BarIcon("edit-rename")); + ui.addIdentity->setIcon(BarIcon("list-add-user")); + ui.deleteIdentity->setIcon(BarIcon("list-remove-user")); - coreConnectionStateChanged(Client::isConnected()); // need a core connection! - connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), this, SLOT(coreConnectionStateChanged(bool))); + coreConnectionStateChanged(Client::isConnected()); // need a core connection! + connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), this, SLOT(coreConnectionStateChanged(bool))); - connect(Client::instance(), SIGNAL(identityCreated(IdentityId)), this, SLOT(clientIdentityCreated(IdentityId))); - connect(Client::instance(), SIGNAL(identityRemoved(IdentityId)), this, SLOT(clientIdentityRemoved(IdentityId))); + connect(Client::instance(), SIGNAL(identityCreated(IdentityId)), this, SLOT(clientIdentityCreated(IdentityId))); + connect(Client::instance(), SIGNAL(identityRemoved(IdentityId)), this, SLOT(clientIdentityRemoved(IdentityId))); - connect(ui.identityEditor, SIGNAL(widgetHasChanged()), this, SLOT(widgetHasChanged())); + connect(ui.identityEditor, SIGNAL(widgetHasChanged()), this, SLOT(widgetHasChanged())); #ifdef HAVE_SSL - connect(ui.identityEditor, SIGNAL(requestEditSsl()), this, SLOT(continueUnsecured())); + connect(ui.identityEditor, SIGNAL(requestEditSsl()), this, SLOT(continueUnsecured())); #endif - currentId = 0; + currentId = 0; - //connect(ui.identityList, SIGNAL(editTextChanged(const QString &)), this, SLOT(widgetHasChanged())); + //connect(ui.identityList, SIGNAL(editTextChanged(const QString &)), this, SLOT(widgetHasChanged())); } -void IdentitiesSettingsPage::coreConnectionStateChanged(bool connected) { - setEnabled(connected); - if(connected) { + +void IdentitiesSettingsPage::coreConnectionStateChanged(bool connected) +{ + setEnabled(connected); + if (connected) { #ifdef HAVE_SSL - if(Client::signalProxy()->isSecure()) { - ui.identityEditor->setSslState(IdentityEditWidget::AllowSsl); - _editSsl = true; - } else { - ui.identityEditor->setSslState(IdentityEditWidget::UnsecureSsl); - _editSsl = false; - } + if (Client::signalProxy()->isSecure()) { + ui.identityEditor->setSslState(IdentityEditWidget::AllowSsl); + _editSsl = true; + } + else { + ui.identityEditor->setSslState(IdentityEditWidget::UnsecureSsl); + _editSsl = false; + } #else - ui.identityEditor->setSslState(IdentityEditWidget::NoSsl); + ui.identityEditor->setSslState(IdentityEditWidget::NoSsl); #endif - load(); - } else { - // reset - currentId = 0; - } + load(); + } + else { + // reset + currentId = 0; + } } + #ifdef HAVE_SSL -void IdentitiesSettingsPage::continueUnsecured() { - _editSsl = true; +void IdentitiesSettingsPage::continueUnsecured() +{ + _editSsl = true; - QHash::iterator idIter; - for(idIter = identities.begin(); idIter != identities.end(); idIter++) { - idIter.value()->enableEditSsl(); - } + QHash::iterator idIter; + for (idIter = identities.begin(); idIter != identities.end(); idIter++) { + idIter.value()->enableEditSsl(); + } - ui.identityEditor->setSslState(IdentityEditWidget::AllowSsl); + ui.identityEditor->setSslState(IdentityEditWidget::AllowSsl); } + + #endif -void IdentitiesSettingsPage::save() { - setEnabled(false); - QList toCreate, toUpdate; - // we need to remove our temporarily created identities. - // these are going to be re-added after the core has propagated them back... - QHash::iterator i = identities.begin(); - while(i != identities.end()) { - if((*i)->id() < 0) { - CertIdentity *temp = *i; - i = identities.erase(i); - toCreate.append(temp); - ui.identityList->removeItem(ui.identityList->findData(temp->id().toInt())); - } else { - if(**i != *Client::identity((*i)->id()) || (*i)->isDirty()) { - toUpdate.append(*i); - } - ++i; +void IdentitiesSettingsPage::save() +{ + setEnabled(false); + QList toCreate, toUpdate; + // we need to remove our temporarily created identities. + // these are going to be re-added after the core has propagated them back... + QHash::iterator i = identities.begin(); + while (i != identities.end()) { + if ((*i)->id() < 0) { + CertIdentity *temp = *i; + i = identities.erase(i); + toCreate.append(temp); + ui.identityList->removeItem(ui.identityList->findData(temp->id().toInt())); + } + else { + if (**i != *Client::identity((*i)->id()) || (*i)->isDirty()) { + toUpdate.append(*i); + } + ++i; + } } - } - SaveIdentitiesDlg dlg(toCreate, toUpdate, deletedIdentities, this); - int ret = dlg.exec(); - if(ret == QDialog::Rejected) { - // canceled -> reload everything to be safe - load(); - } - foreach(Identity *id, toCreate) { - id->deleteLater(); - } - changedIdentities.clear(); - deletedIdentities.clear(); - setChangedState(false); - setEnabled(true); + SaveIdentitiesDlg dlg(toCreate, toUpdate, deletedIdentities, this); + int ret = dlg.exec(); + if (ret == QDialog::Rejected) { + // canceled -> reload everything to be safe + load(); + } + foreach(Identity *id, toCreate) { + id->deleteLater(); + } + changedIdentities.clear(); + deletedIdentities.clear(); + setChangedState(false); + setEnabled(true); } -void IdentitiesSettingsPage::load() { - currentId = 0; - foreach(Identity *identity, identities.values()) { - identity->deleteLater(); - } - identities.clear(); - deletedIdentities.clear(); - changedIdentities.clear(); - ui.identityList->clear(); - setWidgetStates(); - foreach(IdentityId id, Client::identityIds()) { - clientIdentityCreated(id); - } - setChangedState(false); + +void IdentitiesSettingsPage::load() +{ + currentId = 0; + foreach(Identity *identity, identities.values()) { + identity->deleteLater(); + } + identities.clear(); + deletedIdentities.clear(); + changedIdentities.clear(); + ui.identityList->clear(); + setWidgetStates(); + foreach(IdentityId id, Client::identityIds()) { + clientIdentityCreated(id); + } + setChangedState(false); } -void IdentitiesSettingsPage::widgetHasChanged() { - bool changed = testHasChanged(); - if(changed != hasChanged()) setChangedState(changed); + +void IdentitiesSettingsPage::widgetHasChanged() +{ + bool changed = testHasChanged(); + if (changed != hasChanged()) setChangedState(changed); } -void IdentitiesSettingsPage::setWidgetStates() { - bool enabled = (ui.identityList->count() > 0); - ui.identityEditor->setEnabled(enabled); - ui.renameIdentity->setEnabled(enabled); - ui.deleteIdentity->setEnabled(ui.identityList->count() > 1); + +void IdentitiesSettingsPage::setWidgetStates() +{ + bool enabled = (ui.identityList->count() > 0); + ui.identityEditor->setEnabled(enabled); + ui.renameIdentity->setEnabled(enabled); + ui.deleteIdentity->setEnabled(ui.identityList->count() > 1); } -bool IdentitiesSettingsPage::testHasChanged() { - if(deletedIdentities.count()) return true; - if(currentId < 0) { - return true; // new identity - } else { - if(currentId != 0) { - changedIdentities.removeAll(currentId); - CertIdentity temp(currentId, this); - ui.identityEditor->saveToIdentity(&temp); - temp.setIdentityName(identities[currentId]->identityName()); - if(temp != *Client::identity(currentId) || temp.isDirty()) - changedIdentities.append(currentId); + +bool IdentitiesSettingsPage::testHasChanged() +{ + if (deletedIdentities.count()) return true; + if (currentId < 0) { + return true; // new identity + } + else { + if (currentId != 0) { + changedIdentities.removeAll(currentId); + CertIdentity temp(currentId, this); + ui.identityEditor->saveToIdentity(&temp); + temp.setIdentityName(identities[currentId]->identityName()); + if (temp != *Client::identity(currentId) || temp.isDirty()) + changedIdentities.append(currentId); + } + return changedIdentities.count(); } - return changedIdentities.count(); - } } -bool IdentitiesSettingsPage::aboutToSave() { - ui.identityEditor->saveToIdentity(identities[currentId]); - QList errors; - foreach(Identity *id, identities.values()) { - if(id->identityName().isEmpty()) errors.append(1); - if(!id->nicks().count()) errors.append(2); - if(id->realName().isEmpty()) errors.append(3); - if(id->ident().isEmpty()) errors.append(4); - } - if(!errors.count()) return true; - QString error(tr("The following problems need to be corrected before your changes can be applied:
    ")); - if(errors.contains(1)) error += tr("
  • All identities need an identity name set
  • "); - if(errors.contains(2)) error += tr("
  • Every identity needs at least one nickname defined
  • "); - if(errors.contains(3)) error += tr("
  • You need to specify a real name for every identity
  • "); - if(errors.contains(4)) error += tr("
  • You need to specify an ident for every identity
  • "); - error += tr("
"); - QMessageBox::warning(this, tr("One or more identities are invalid"), error); - return false; + +bool IdentitiesSettingsPage::aboutToSave() +{ + ui.identityEditor->saveToIdentity(identities[currentId]); + QList errors; + foreach(Identity *id, identities.values()) { + if (id->identityName().isEmpty()) errors.append(1); + if (!id->nicks().count()) errors.append(2); + if (id->realName().isEmpty()) errors.append(3); + if (id->ident().isEmpty()) errors.append(4); + } + if (!errors.count()) return true; + QString error(tr("The following problems need to be corrected before your changes can be applied:
    ")); + if (errors.contains(1)) error += tr("
  • All identities need an identity name set
  • "); + if (errors.contains(2)) error += tr("
  • Every identity needs at least one nickname defined
  • "); + if (errors.contains(3)) error += tr("
  • You need to specify a real name for every identity
  • "); + if (errors.contains(4)) error += tr("
  • You need to specify an ident for every identity
  • "); + error += tr("
"); + QMessageBox::warning(this, tr("One or more identities are invalid"), error); + return false; } -void IdentitiesSettingsPage::clientIdentityCreated(IdentityId id) { - CertIdentity *identity = new CertIdentity(*Client::identity(id), this); + +void IdentitiesSettingsPage::clientIdentityCreated(IdentityId id) +{ + CertIdentity *identity = new CertIdentity(*Client::identity(id), this); #ifdef HAVE_SSL - identity->enableEditSsl(_editSsl); + identity->enableEditSsl(_editSsl); #endif - insertIdentity(identity); + insertIdentity(identity); #ifdef HAVE_SSL - connect(identity, SIGNAL(sslSettingsUpdated()), this, SLOT(clientIdentityUpdated())); + connect(identity, SIGNAL(sslSettingsUpdated()), this, SLOT(clientIdentityUpdated())); #endif - connect(Client::identity(id), SIGNAL(updatedRemotely()), this, SLOT(clientIdentityUpdated())); + connect(Client::identity(id), SIGNAL(updatedRemotely()), this, SLOT(clientIdentityUpdated())); } -void IdentitiesSettingsPage::clientIdentityUpdated() { - const Identity *clientIdentity = qobject_cast(sender()); - if(!clientIdentity) { - qWarning() << "Invalid identity to update!"; - return; - } - if(!identities.contains(clientIdentity->id())) { - qWarning() << "Unknown identity to update:" << clientIdentity->identityName(); - return; - } - CertIdentity *identity = identities[clientIdentity->id()]; +void IdentitiesSettingsPage::clientIdentityUpdated() +{ + const Identity *clientIdentity = qobject_cast(sender()); + if (!clientIdentity) { + qWarning() << "Invalid identity to update!"; + return; + } + if (!identities.contains(clientIdentity->id())) { + qWarning() << "Unknown identity to update:" << clientIdentity->identityName(); + return; + } - if(identity->identityName() != clientIdentity->identityName()) - renameIdentity(identity->id(), clientIdentity->identityName()); + CertIdentity *identity = identities[clientIdentity->id()]; - identity->copyFrom(*clientIdentity); + if (identity->identityName() != clientIdentity->identityName()) + renameIdentity(identity->id(), clientIdentity->identityName()); - if(identity->id() == currentId) - ui.identityEditor->displayIdentity(identity); + identity->copyFrom(*clientIdentity); + + if (identity->id() == currentId) + ui.identityEditor->displayIdentity(identity); } -void IdentitiesSettingsPage::clientIdentityRemoved(IdentityId id) { - if(identities.contains(id)) { - removeIdentity(identities[id]); - changedIdentities.removeAll(id); - deletedIdentities.removeAll(id); - } + +void IdentitiesSettingsPage::clientIdentityRemoved(IdentityId id) +{ + if (identities.contains(id)) { + removeIdentity(identities[id]); + changedIdentities.removeAll(id); + deletedIdentities.removeAll(id); + } } -void IdentitiesSettingsPage::insertIdentity(CertIdentity *identity) { - IdentityId id = identity->id(); - identities[id] = identity; - QString name = identity->identityName(); - for(int j = 0; j < ui.identityList->count(); j++) { - if((j>0 || ui.identityList->itemData(0).toInt() != 1) && name.localeAwareCompare(ui.identityList->itemText(j)) < 0) { - ui.identityList->insertItem(j, name, id.toInt()); - widgetHasChanged(); - return; +void IdentitiesSettingsPage::insertIdentity(CertIdentity *identity) +{ + IdentityId id = identity->id(); + identities[id] = identity; + + QString name = identity->identityName(); + for (int j = 0; j < ui.identityList->count(); j++) { + if ((j > 0 || ui.identityList->itemData(0).toInt() != 1) && name.localeAwareCompare(ui.identityList->itemText(j)) < 0) { + ui.identityList->insertItem(j, name, id.toInt()); + widgetHasChanged(); + return; + } } - } - // append - ui.identityList->insertItem(ui.identityList->count(), name, id.toInt()); - setWidgetStates(); - widgetHasChanged(); + // append + ui.identityList->insertItem(ui.identityList->count(), name, id.toInt()); + setWidgetStates(); + widgetHasChanged(); } -void IdentitiesSettingsPage::renameIdentity(IdentityId id, const QString &newName) { - Identity *identity = identities[id]; - ui.identityList->setItemText(ui.identityList->findData(identity->id().toInt()), newName); - identity->setIdentityName(newName); + +void IdentitiesSettingsPage::renameIdentity(IdentityId id, const QString &newName) +{ + Identity *identity = identities[id]; + ui.identityList->setItemText(ui.identityList->findData(identity->id().toInt()), newName); + identity->setIdentityName(newName); } -void IdentitiesSettingsPage::removeIdentity(Identity *id) { - identities.remove(id->id()); - ui.identityList->removeItem(ui.identityList->findData(id->id().toInt())); - changedIdentities.removeAll(id->id()); - if(currentId == id->id()) currentId = 0; - id->deleteLater(); - setWidgetStates(); - widgetHasChanged(); + +void IdentitiesSettingsPage::removeIdentity(Identity *id) +{ + identities.remove(id->id()); + ui.identityList->removeItem(ui.identityList->findData(id->id().toInt())); + changedIdentities.removeAll(id->id()); + if (currentId == id->id()) currentId = 0; + id->deleteLater(); + setWidgetStates(); + widgetHasChanged(); } -void IdentitiesSettingsPage::on_identityList_currentIndexChanged(int index) { - CertIdentity *previousIdentity = 0; - if(currentId != 0 && identities.contains(currentId)) - previousIdentity = identities[currentId]; - if(index < 0) { - //ui.identityList->setEditable(false); - ui.identityEditor->displayIdentity(0, previousIdentity); - currentId = 0; - } else { - IdentityId id = ui.identityList->itemData(index).toInt(); - if(identities.contains(id)) { - ui.identityEditor->displayIdentity(identities[id], previousIdentity); - currentId = id; +void IdentitiesSettingsPage::on_identityList_currentIndexChanged(int index) +{ + CertIdentity *previousIdentity = 0; + if (currentId != 0 && identities.contains(currentId)) + previousIdentity = identities[currentId]; + + if (index < 0) { + //ui.identityList->setEditable(false); + ui.identityEditor->displayIdentity(0, previousIdentity); + currentId = 0; + } + else { + IdentityId id = ui.identityList->itemData(index).toInt(); + if (identities.contains(id)) { + ui.identityEditor->displayIdentity(identities[id], previousIdentity); + currentId = id; + } } - } } -void IdentitiesSettingsPage::on_addIdentity_clicked() { - CreateIdentityDlg dlg(ui.identityList->model(), this); - if(dlg.exec() == QDialog::Accepted) { - // find a free (negative) ID - IdentityId id; - for(id = 1; id <= identities.count(); id++) { - if(!identities.keys().contains(-id.toInt())) break; - } - id = -id.toInt(); - CertIdentity *newId = new CertIdentity(id, this); + +void IdentitiesSettingsPage::on_addIdentity_clicked() +{ + CreateIdentityDlg dlg(ui.identityList->model(), this); + if (dlg.exec() == QDialog::Accepted) { + // find a free (negative) ID + IdentityId id; + for (id = 1; id <= identities.count(); id++) { + if (!identities.keys().contains(-id.toInt())) break; + } + id = -id.toInt(); + CertIdentity *newId = new CertIdentity(id, this); #ifdef HAVE_SSL - newId->enableEditSsl(_editSsl); + newId->enableEditSsl(_editSsl); #endif - if(dlg.duplicateId() != 0) { - // duplicate - newId->copyFrom(*identities[dlg.duplicateId()]); - newId->setId(id); + if (dlg.duplicateId() != 0) { + // duplicate + newId->copyFrom(*identities[dlg.duplicateId()]); + newId->setId(id); + } + newId->setIdentityName(dlg.identityName()); + identities[id] = newId; + insertIdentity(newId); + ui.identityList->setCurrentIndex(ui.identityList->findData(id.toInt())); + widgetHasChanged(); } - newId->setIdentityName(dlg.identityName()); - identities[id] = newId; - insertIdentity(newId); - ui.identityList->setCurrentIndex(ui.identityList->findData(id.toInt())); - widgetHasChanged(); - } } -void IdentitiesSettingsPage::on_deleteIdentity_clicked() { - Identity *id = identities[currentId]; - int ret = QMessageBox::question(this, tr("Delete Identity?"), - tr("Do you really want to delete identity \"%1\"?").arg(id->identityName()), - QMessageBox::Yes|QMessageBox::No, QMessageBox::No); - if(ret != QMessageBox::Yes) return; - if(id->id() > 0) deletedIdentities.append(id->id()); - currentId = 0; - removeIdentity(id); + +void IdentitiesSettingsPage::on_deleteIdentity_clicked() +{ + Identity *id = identities[currentId]; + int ret = QMessageBox::question(this, tr("Delete Identity?"), + tr("Do you really want to delete identity \"%1\"?").arg(id->identityName()), + QMessageBox::Yes|QMessageBox::No, QMessageBox::No); + if (ret != QMessageBox::Yes) return; + if (id->id() > 0) deletedIdentities.append(id->id()); + currentId = 0; + removeIdentity(id); } -void IdentitiesSettingsPage::on_renameIdentity_clicked() { - QString oldName = identities[currentId]->identityName(); - bool ok = false; - QString name = QInputDialog::getText(this, tr("Rename Identity"), - tr("Please enter a new name for the identity \"%1\"!").arg(oldName), - QLineEdit::Normal, oldName, &ok); - if(ok && !name.isEmpty()) { - renameIdentity(currentId, name); - widgetHasChanged(); - } + +void IdentitiesSettingsPage::on_renameIdentity_clicked() +{ + QString oldName = identities[currentId]->identityName(); + bool ok = false; + QString name = QInputDialog::getText(this, tr("Rename Identity"), + tr("Please enter a new name for the identity \"%1\"!").arg(oldName), + QLineEdit::Normal, oldName, &ok); + if (ok && !name.isEmpty()) { + renameIdentity(currentId, name); + widgetHasChanged(); + } } + /*****************************************************************************************/ CreateIdentityDlg::CreateIdentityDlg(QAbstractItemModel *model, QWidget *parent) - : QDialog(parent) + : QDialog(parent) { - ui.setupUi(this); + ui.setupUi(this); - ui.identityList->setModel(model); // now we use the identity list of the main page... Trolltech <3 - on_identityName_textChanged(""); // disable ok button :) + ui.identityList->setModel(model); // now we use the identity list of the main page... Trolltech <3 + on_identityName_textChanged(""); // disable ok button :) } -QString CreateIdentityDlg::identityName() const { - return ui.identityName->text(); -} -IdentityId CreateIdentityDlg::duplicateId() const { - if(!ui.duplicateIdentity->isChecked()) return 0; - if(ui.identityList->currentIndex() >= 0) { - return ui.identityList->itemData(ui.identityList->currentIndex()).toInt(); - } - return 0; +QString CreateIdentityDlg::identityName() const +{ + return ui.identityName->text(); } -void CreateIdentityDlg::on_identityName_textChanged(const QString &text) { - ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(text.count()); +IdentityId CreateIdentityDlg::duplicateId() const +{ + if (!ui.duplicateIdentity->isChecked()) return 0; + if (ui.identityList->currentIndex() >= 0) { + return ui.identityList->itemData(ui.identityList->currentIndex()).toInt(); + } + return 0; } -/*********************************************************************************************/ -SaveIdentitiesDlg::SaveIdentitiesDlg(const QList &toCreate, const QList &toUpdate, const QList &toRemove, QWidget *parent) - : QDialog(parent) +void CreateIdentityDlg::on_identityName_textChanged(const QString &text) { - ui.setupUi(this); - ui.abort->setIcon(SmallIcon("dialog-cancel")); + ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(text.count()); +} - numevents = toCreate.count() + toUpdate.count() + toRemove.count(); - rcvevents = 0; - if(numevents) { - ui.progressBar->setMaximum(numevents); - ui.progressBar->setValue(0); - connect(Client::instance(), SIGNAL(identityCreated(IdentityId)), this, SLOT(clientEvent())); - connect(Client::instance(), SIGNAL(identityRemoved(IdentityId)), this, SLOT(clientEvent())); +/*********************************************************************************************/ - foreach(CertIdentity *id, toCreate) { - Client::createIdentity(*id); - } - foreach(CertIdentity *id, toUpdate) { - const Identity *cid = Client::identity(id->id()); - if(!cid) { - qWarning() << "Invalid client identity!"; - numevents--; - continue; - } - connect(cid, SIGNAL(updatedRemotely()), this, SLOT(clientEvent())); - Client::updateIdentity(id->id(), id->toVariantMap()); +SaveIdentitiesDlg::SaveIdentitiesDlg(const QList &toCreate, const QList &toUpdate, const QList &toRemove, QWidget *parent) + : QDialog(parent) +{ + ui.setupUi(this); + ui.abort->setIcon(SmallIcon("dialog-cancel")); + + numevents = toCreate.count() + toUpdate.count() + toRemove.count(); + rcvevents = 0; + if (numevents) { + ui.progressBar->setMaximum(numevents); + ui.progressBar->setValue(0); + + connect(Client::instance(), SIGNAL(identityCreated(IdentityId)), this, SLOT(clientEvent())); + connect(Client::instance(), SIGNAL(identityRemoved(IdentityId)), this, SLOT(clientEvent())); + + foreach(CertIdentity *id, toCreate) { + Client::createIdentity(*id); + } + foreach(CertIdentity *id, toUpdate) { + const Identity *cid = Client::identity(id->id()); + if (!cid) { + qWarning() << "Invalid client identity!"; + numevents--; + continue; + } + connect(cid, SIGNAL(updatedRemotely()), this, SLOT(clientEvent())); + Client::updateIdentity(id->id(), id->toVariantMap()); #ifdef HAVE_SSL - id->requestUpdateSslSettings(); + id->requestUpdateSslSettings(); #endif + } + foreach(IdentityId id, toRemove) { + Client::removeIdentity(id); + } } - foreach(IdentityId id, toRemove) { - Client::removeIdentity(id); + else { + qWarning() << "Sync dialog called without stuff to change!"; + accept(); } - } else { - qWarning() << "Sync dialog called without stuff to change!"; - accept(); - } } -void SaveIdentitiesDlg::clientEvent() { - ui.progressBar->setValue(++rcvevents); - if(rcvevents >= numevents) accept(); + +void SaveIdentitiesDlg::clientEvent() +{ + ui.progressBar->setValue(++rcvevents); + if (rcvevents >= numevents) accept(); } + /*************************************************************************************************/ NickEditDlg::NickEditDlg(const QString &old, const QStringList &exist, QWidget *parent) - : QDialog(parent), oldNick(old), existing(exist) { - ui.setupUi(this); - - // define a regexp for valid nicknames - // TODO: add max nicklength according to ISUPPORT - QString letter = "A-Za-z"; - QString special = "\x5b-\x60\x7b-\x7d"; - QRegExp rx(QString("[%1%2][%1%2\\d-]*").arg(letter, special)); - ui.nickEdit->setValidator(new QRegExpValidator(rx, ui.nickEdit)); - if(old.isEmpty()) { - // new nick - setWindowTitle(tr("Add Nickname")); - on_nickEdit_textChanged(""); // disable ok button - } else ui.nickEdit->setText(old); + : QDialog(parent), oldNick(old), existing(exist) +{ + ui.setupUi(this); + + // define a regexp for valid nicknames + // TODO: add max nicklength according to ISUPPORT + QString letter = "A-Za-z"; + QString special = "\x5b-\x60\x7b-\x7d"; + QRegExp rx(QString("[%1%2][%1%2\\d-]*").arg(letter, special)); + ui.nickEdit->setValidator(new QRegExpValidator(rx, ui.nickEdit)); + if (old.isEmpty()) { + // new nick + setWindowTitle(tr("Add Nickname")); + on_nickEdit_textChanged(""); // disable ok button + } + else ui.nickEdit->setText(old); } -QString NickEditDlg::nick() const { - return ui.nickEdit->text(); - -} -void NickEditDlg::on_nickEdit_textChanged(const QString &text) { - ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(text.isEmpty() || existing.contains(text)); +QString NickEditDlg::nick() const +{ + return ui.nickEdit->text(); } - +void NickEditDlg::on_nickEdit_textChanged(const QString &text) +{ + ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(text.isEmpty() || existing.contains(text)); +} diff --git a/src/qtui/settingspages/identitiessettingspage.h b/src/qtui/settingspages/identitiessettingspage.h index 277cee87..fd89631f 100644 --- a/src/qtui/settingspages/identitiessettingspage.h +++ b/src/qtui/settingspages/identitiessettingspage.h @@ -32,99 +32,101 @@ class QAbstractItemModel; -class IdentitiesSettingsPage : public SettingsPage { - Q_OBJECT +class IdentitiesSettingsPage : public SettingsPage +{ + Q_OBJECT public: - IdentitiesSettingsPage(QWidget *parent = 0); + IdentitiesSettingsPage(QWidget *parent = 0); - virtual inline bool needsCoreConnection() const { return true; } + virtual inline bool needsCoreConnection() const { return true; } - bool aboutToSave(); + bool aboutToSave(); public slots: - void save(); - void load(); + void save(); + void load(); private slots: - void coreConnectionStateChanged(bool); - void clientIdentityCreated(IdentityId); - void clientIdentityUpdated(); - void clientIdentityRemoved(IdentityId); + void coreConnectionStateChanged(bool); + void clientIdentityCreated(IdentityId); + void clientIdentityUpdated(); + void clientIdentityRemoved(IdentityId); - void on_identityList_currentIndexChanged(int index); + void on_identityList_currentIndexChanged(int index); - void on_addIdentity_clicked(); - void on_deleteIdentity_clicked(); - void on_renameIdentity_clicked(); + void on_addIdentity_clicked(); + void on_deleteIdentity_clicked(); + void on_renameIdentity_clicked(); #ifdef HAVE_SSL - void continueUnsecured(); + void continueUnsecured(); #endif - void widgetHasChanged(); - void setWidgetStates(); + void widgetHasChanged(); + void setWidgetStates(); private: - Ui::IdentitiesSettingsPage ui; + Ui::IdentitiesSettingsPage ui; - QHash identities; - IdentityId currentId; + QHash identities; + IdentityId currentId; - QList changedIdentities; // for setting the widget changed state - QList deletedIdentities; + QList changedIdentities; // for setting the widget changed state + QList deletedIdentities; - bool _editSsl; + bool _editSsl; - void insertIdentity(CertIdentity *identity); - void removeIdentity(Identity *identity); - void renameIdentity(IdentityId id, const QString &newName); + void insertIdentity(CertIdentity *identity); + void removeIdentity(Identity *identity); + void renameIdentity(IdentityId id, const QString &newName); #ifdef HAVE_SSL - QSslKey keyByFilename(const QString &filename); - void showKeyState(const QSslKey &key); - QSslCertificate certByFilename(const QString &filename); - void showCertState(const QSslCertificate &cert); + QSslKey keyByFilename(const QString &filename); + void showKeyState(const QSslKey &key); + QSslCertificate certByFilename(const QString &filename); + void showCertState(const QSslCertificate &cert); #endif - bool testHasChanged(); + bool testHasChanged(); }; + // ============================== // Various Dialogs // ============================== -class CreateIdentityDlg : public QDialog { - Q_OBJECT +class CreateIdentityDlg : public QDialog +{ + Q_OBJECT public: - CreateIdentityDlg(QAbstractItemModel *model, QWidget *parent = 0); + CreateIdentityDlg(QAbstractItemModel *model, QWidget *parent = 0); - QString identityName() const; - IdentityId duplicateId() const; + QString identityName() const; + IdentityId duplicateId() const; private slots: - void on_identityName_textChanged(const QString &text); + void on_identityName_textChanged(const QString &text); private: - Ui::CreateIdentityDlg ui; + Ui::CreateIdentityDlg ui; }; - -class SaveIdentitiesDlg : public QDialog { - Q_OBJECT +class SaveIdentitiesDlg : public QDialog +{ + Q_OBJECT public: - SaveIdentitiesDlg(const QList &toCreate, const QList &toUpdate, const QList &toRemove, QWidget *parent = 0); + SaveIdentitiesDlg(const QList &toCreate, const QList &toUpdate, const QList &toRemove, QWidget *parent = 0); private slots: - void clientEvent(); + void clientEvent(); private: - Ui::SaveIdentitiesDlg ui; + Ui::SaveIdentitiesDlg ui; - int numevents, rcvevents; + int numevents, rcvevents; }; - #endif diff --git a/src/qtui/settingspages/identityeditwidget.cpp b/src/qtui/settingspages/identityeditwidget.cpp index 47345256..e685b1ef 100644 --- a/src/qtui/settingspages/identityeditwidget.cpp +++ b/src/qtui/settingspages/identityeditwidget.cpp @@ -30,344 +30,387 @@ #include "iconloader.h" IdentityEditWidget::IdentityEditWidget(QWidget *parent) - : QWidget(parent) + : QWidget(parent) { - ui.setupUi(this); - - ui.addNick->setIcon(SmallIcon("list-add")); - ui.deleteNick->setIcon(SmallIcon("edit-delete")); - ui.renameNick->setIcon(SmallIcon("edit-rename")); - ui.nickUp->setIcon(SmallIcon("go-up")); - ui.nickDown->setIcon(SmallIcon("go-down")); - - // We need to know whenever the state of input widgets changes... - connect(ui.realName, SIGNAL(textEdited(const QString &)), this, SIGNAL(widgetHasChanged())); - connect(ui.nicknameList, SIGNAL(itemChanged(QListWidgetItem *)), this, SIGNAL(widgetHasChanged())); - connect(ui.awayNick, SIGNAL(textEdited(const QString &)), this, SIGNAL(widgetHasChanged())); - connect(ui.awayReason, SIGNAL(textEdited(const QString &)), this, SIGNAL(widgetHasChanged())); - connect(ui.autoAwayEnabled, SIGNAL(clicked(bool)), this, SIGNAL(widgetHasChanged())); - connect(ui.autoAwayTime, SIGNAL(valueChanged(int)), this, SIGNAL(widgetHasChanged())); - connect(ui.autoAwayReason, SIGNAL(textEdited(const QString &)), this, SIGNAL(widgetHasChanged())); - connect(ui.autoAwayReasonEnabled, SIGNAL(clicked(bool)), this, SIGNAL(widgetHasChanged())); - connect(ui.detachAwayEnabled, SIGNAL(clicked(bool)), this, SIGNAL(widgetHasChanged())); - connect(ui.detachAwayReason, SIGNAL(textEdited(const QString &)), this, SIGNAL(widgetHasChanged())); - connect(ui.ident, SIGNAL(textEdited(const QString &)), this, SIGNAL(widgetHasChanged())); - connect(ui.kickReason, SIGNAL(textEdited(const QString &)), this, SIGNAL(widgetHasChanged())); - connect(ui.partReason, SIGNAL(textEdited(const QString &)), this, SIGNAL(widgetHasChanged())); - connect(ui.quitReason, SIGNAL(textEdited(const QString &)), this, SIGNAL(widgetHasChanged())); - - setWidgetStates(); - connect(ui.nicknameList, SIGNAL(itemSelectionChanged()), this, SLOT(setWidgetStates())); - - connect(ui.continueUnsecured, SIGNAL(clicked()), this, SIGNAL(requestEditSsl())); - - // we would need this if we enabled drag and drop in the nicklist... - //connect(ui.nicknameList, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(setWidgetStates())); - //connect(ui.nicknameList->model(), SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(nicklistHasChanged())); - - // disabling unused stuff - ui.autoAwayEnabled->hide(); - ui.awayNick->hide(); - ui.awayNickLabel->hide(); - - ui.detachAwayEnabled->setVisible(!Client::internalCore()); + ui.setupUi(this); + + ui.addNick->setIcon(SmallIcon("list-add")); + ui.deleteNick->setIcon(SmallIcon("edit-delete")); + ui.renameNick->setIcon(SmallIcon("edit-rename")); + ui.nickUp->setIcon(SmallIcon("go-up")); + ui.nickDown->setIcon(SmallIcon("go-down")); + + // We need to know whenever the state of input widgets changes... + connect(ui.realName, SIGNAL(textEdited(const QString &)), this, SIGNAL(widgetHasChanged())); + connect(ui.nicknameList, SIGNAL(itemChanged(QListWidgetItem *)), this, SIGNAL(widgetHasChanged())); + connect(ui.awayNick, SIGNAL(textEdited(const QString &)), this, SIGNAL(widgetHasChanged())); + connect(ui.awayReason, SIGNAL(textEdited(const QString &)), this, SIGNAL(widgetHasChanged())); + connect(ui.autoAwayEnabled, SIGNAL(clicked(bool)), this, SIGNAL(widgetHasChanged())); + connect(ui.autoAwayTime, SIGNAL(valueChanged(int)), this, SIGNAL(widgetHasChanged())); + connect(ui.autoAwayReason, SIGNAL(textEdited(const QString &)), this, SIGNAL(widgetHasChanged())); + connect(ui.autoAwayReasonEnabled, SIGNAL(clicked(bool)), this, SIGNAL(widgetHasChanged())); + connect(ui.detachAwayEnabled, SIGNAL(clicked(bool)), this, SIGNAL(widgetHasChanged())); + connect(ui.detachAwayReason, SIGNAL(textEdited(const QString &)), this, SIGNAL(widgetHasChanged())); + connect(ui.ident, SIGNAL(textEdited(const QString &)), this, SIGNAL(widgetHasChanged())); + connect(ui.kickReason, SIGNAL(textEdited(const QString &)), this, SIGNAL(widgetHasChanged())); + connect(ui.partReason, SIGNAL(textEdited(const QString &)), this, SIGNAL(widgetHasChanged())); + connect(ui.quitReason, SIGNAL(textEdited(const QString &)), this, SIGNAL(widgetHasChanged())); + + setWidgetStates(); + connect(ui.nicknameList, SIGNAL(itemSelectionChanged()), this, SLOT(setWidgetStates())); + + connect(ui.continueUnsecured, SIGNAL(clicked()), this, SIGNAL(requestEditSsl())); + + // we would need this if we enabled drag and drop in the nicklist... + //connect(ui.nicknameList, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(setWidgetStates())); + //connect(ui.nicknameList->model(), SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(nicklistHasChanged())); + + // disabling unused stuff + ui.autoAwayEnabled->hide(); + ui.awayNick->hide(); + ui.awayNickLabel->hide(); + + ui.detachAwayEnabled->setVisible(!Client::internalCore()); #ifdef HAVE_SSL - ui.sslKeyGroupBox->setAcceptDrops(true); - ui.sslKeyGroupBox->installEventFilter(this); - ui.sslCertGroupBox->setAcceptDrops(true); - ui.sslCertGroupBox->installEventFilter(this); + ui.sslKeyGroupBox->setAcceptDrops(true); + ui.sslKeyGroupBox->installEventFilter(this); + ui.sslCertGroupBox->setAcceptDrops(true); + ui.sslCertGroupBox->installEventFilter(this); #endif } -void IdentityEditWidget::setWidgetStates() { - if(ui.nicknameList->selectedItems().count()) { - ui.renameNick->setEnabled(true); - ui.nickUp->setEnabled(ui.nicknameList->row(ui.nicknameList->selectedItems()[0]) > 0); - ui.nickDown->setEnabled(ui.nicknameList->row(ui.nicknameList->selectedItems()[0]) < ui.nicknameList->count()-1); - } else { - ui.renameNick->setDisabled(true); - ui.nickUp->setDisabled(true); - ui.nickDown->setDisabled(true); - } - ui.deleteNick->setEnabled(ui.nicknameList->count() > 1); + +void IdentityEditWidget::setWidgetStates() +{ + if (ui.nicknameList->selectedItems().count()) { + ui.renameNick->setEnabled(true); + ui.nickUp->setEnabled(ui.nicknameList->row(ui.nicknameList->selectedItems()[0]) > 0); + ui.nickDown->setEnabled(ui.nicknameList->row(ui.nicknameList->selectedItems()[0]) < ui.nicknameList->count()-1); + } + else { + ui.renameNick->setDisabled(true); + ui.nickUp->setDisabled(true); + ui.nickDown->setDisabled(true); + } + ui.deleteNick->setEnabled(ui.nicknameList->count() > 1); } -void IdentityEditWidget::displayIdentity(CertIdentity *id, CertIdentity *saveId) { - if(saveId) { - saveToIdentity(saveId); - } - - if(!id) - return; - - ui.realName->setText(id->realName()); - ui.nicknameList->clear(); - ui.nicknameList->addItems(id->nicks()); - //for(int i = 0; i < ui.nicknameList->count(); i++) { - // ui.nicknameList->item(i)->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEditable|Qt::ItemIsEnabled); - //} - if(ui.nicknameList->count()) ui.nicknameList->setCurrentRow(0); - ui.awayNick->setText(id->awayNick()); - ui.awayReason->setText(id->awayReason()); - ui.autoAwayEnabled->setChecked(id->autoAwayEnabled()); - ui.autoAwayTime->setValue(id->autoAwayTime()); - ui.autoAwayReason->setText(id->autoAwayReason()); - ui.autoAwayReasonEnabled->setChecked(id->autoAwayReasonEnabled()); - ui.detachAwayEnabled->setChecked(id->detachAwayEnabled()); - ui.detachAwayReason->setText(id->detachAwayReason()); - ui.ident->setText(id->ident()); - ui.kickReason->setText(id->kickReason()); - ui.partReason->setText(id->partReason()); - ui.quitReason->setText(id->quitReason()); + +void IdentityEditWidget::displayIdentity(CertIdentity *id, CertIdentity *saveId) +{ + if (saveId) { + saveToIdentity(saveId); + } + + if (!id) + return; + + ui.realName->setText(id->realName()); + ui.nicknameList->clear(); + ui.nicknameList->addItems(id->nicks()); + //for(int i = 0; i < ui.nicknameList->count(); i++) { + // ui.nicknameList->item(i)->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEditable|Qt::ItemIsEnabled); + //} + if (ui.nicknameList->count()) ui.nicknameList->setCurrentRow(0); + ui.awayNick->setText(id->awayNick()); + ui.awayReason->setText(id->awayReason()); + ui.autoAwayEnabled->setChecked(id->autoAwayEnabled()); + ui.autoAwayTime->setValue(id->autoAwayTime()); + ui.autoAwayReason->setText(id->autoAwayReason()); + ui.autoAwayReasonEnabled->setChecked(id->autoAwayReasonEnabled()); + ui.detachAwayEnabled->setChecked(id->detachAwayEnabled()); + ui.detachAwayReason->setText(id->detachAwayReason()); + ui.ident->setText(id->ident()); + ui.kickReason->setText(id->kickReason()); + ui.partReason->setText(id->partReason()); + ui.quitReason->setText(id->quitReason()); #ifdef HAVE_SSL - showKeyState(id->sslKey()); - showCertState(id->sslCert()); + showKeyState(id->sslKey()); + showCertState(id->sslCert()); #endif - } -void IdentityEditWidget::saveToIdentity(CertIdentity *id) { - id->setRealName(ui.realName->text()); - QStringList nicks; - for(int i = 0; i < ui.nicknameList->count(); i++) { - nicks << ui.nicknameList->item(i)->text(); - } - id->setNicks(nicks); - id->setAwayNick(ui.awayNick->text()); - id->setAwayNickEnabled(true); - id->setAwayReason(ui.awayReason->text()); - id->setAwayReasonEnabled(true); - id->setAutoAwayEnabled(ui.autoAwayEnabled->isChecked()); - id->setAutoAwayTime(ui.autoAwayTime->value()); - id->setAutoAwayReason(ui.autoAwayReason->text()); - id->setAutoAwayReasonEnabled(ui.autoAwayReasonEnabled->isChecked()); - id->setDetachAwayEnabled(ui.detachAwayEnabled->isChecked()); - id->setDetachAwayReason(ui.detachAwayReason->text()); - id->setDetachAwayReasonEnabled(true); - id->setIdent(ui.ident->text()); - id->setKickReason(ui.kickReason->text()); - id->setPartReason(ui.partReason->text()); - id->setQuitReason(ui.quitReason->text()); + +void IdentityEditWidget::saveToIdentity(CertIdentity *id) +{ + id->setRealName(ui.realName->text()); + QStringList nicks; + for (int i = 0; i < ui.nicknameList->count(); i++) { + nicks << ui.nicknameList->item(i)->text(); + } + id->setNicks(nicks); + id->setAwayNick(ui.awayNick->text()); + id->setAwayNickEnabled(true); + id->setAwayReason(ui.awayReason->text()); + id->setAwayReasonEnabled(true); + id->setAutoAwayEnabled(ui.autoAwayEnabled->isChecked()); + id->setAutoAwayTime(ui.autoAwayTime->value()); + id->setAutoAwayReason(ui.autoAwayReason->text()); + id->setAutoAwayReasonEnabled(ui.autoAwayReasonEnabled->isChecked()); + id->setDetachAwayEnabled(ui.detachAwayEnabled->isChecked()); + id->setDetachAwayReason(ui.detachAwayReason->text()); + id->setDetachAwayReasonEnabled(true); + id->setIdent(ui.ident->text()); + id->setKickReason(ui.kickReason->text()); + id->setPartReason(ui.partReason->text()); + id->setQuitReason(ui.quitReason->text()); #ifdef HAVE_SSL - id->setSslKey(QSslKey(ui.keyTypeLabel->property("sslKey").toByteArray(), (QSsl::KeyAlgorithm)(ui.keyTypeLabel->property("sslKeyType").toInt()))); - id->setSslCert(QSslCertificate(ui.certOrgLabel->property("sslCert").toByteArray())); + id->setSslKey(QSslKey(ui.keyTypeLabel->property("sslKey").toByteArray(), (QSsl::KeyAlgorithm)(ui.keyTypeLabel->property("sslKeyType").toInt()))); + id->setSslCert(QSslCertificate(ui.certOrgLabel->property("sslCert").toByteArray())); #endif } -void IdentityEditWidget::on_addNick_clicked() { - QStringList existing; - for(int i = 0; i < ui.nicknameList->count(); i++) existing << ui.nicknameList->item(i)->text(); - NickEditDlg dlg(QString(), existing, this); - if(dlg.exec() == QDialog::Accepted) { - ui.nicknameList->addItem(dlg.nick()); - ui.nicknameList->setCurrentRow(ui.nicknameList->count()-1); - setWidgetStates(); - emit widgetHasChanged(); - } + +void IdentityEditWidget::on_addNick_clicked() +{ + QStringList existing; + for (int i = 0; i < ui.nicknameList->count(); i++) existing << ui.nicknameList->item(i)->text(); + NickEditDlg dlg(QString(), existing, this); + if (dlg.exec() == QDialog::Accepted) { + ui.nicknameList->addItem(dlg.nick()); + ui.nicknameList->setCurrentRow(ui.nicknameList->count()-1); + setWidgetStates(); + emit widgetHasChanged(); + } } -void IdentityEditWidget::on_deleteNick_clicked() { - // no confirmation, since a nickname is really nothing hard to recreate - if(ui.nicknameList->selectedItems().count()) { - delete ui.nicknameList->takeItem(ui.nicknameList->row(ui.nicknameList->selectedItems()[0])); - ui.nicknameList->setCurrentRow(qMin(ui.nicknameList->currentRow()+1, ui.nicknameList->count()-1)); - setWidgetStates(); - emit widgetHasChanged(); - } + +void IdentityEditWidget::on_deleteNick_clicked() +{ + // no confirmation, since a nickname is really nothing hard to recreate + if (ui.nicknameList->selectedItems().count()) { + delete ui.nicknameList->takeItem(ui.nicknameList->row(ui.nicknameList->selectedItems()[0])); + ui.nicknameList->setCurrentRow(qMin(ui.nicknameList->currentRow()+1, ui.nicknameList->count()-1)); + setWidgetStates(); + emit widgetHasChanged(); + } } -void IdentityEditWidget::on_renameNick_clicked() { - if(!ui.nicknameList->selectedItems().count()) return; - QString old = ui.nicknameList->selectedItems()[0]->text(); - QStringList existing; - for(int i = 0; i < ui.nicknameList->count(); i++) existing << ui.nicknameList->item(i)->text(); - NickEditDlg dlg(old, existing, this); - if(dlg.exec() == QDialog::Accepted) { - ui.nicknameList->selectedItems()[0]->setText(dlg.nick()); - } +void IdentityEditWidget::on_renameNick_clicked() +{ + if (!ui.nicknameList->selectedItems().count()) return; + QString old = ui.nicknameList->selectedItems()[0]->text(); + QStringList existing; + for (int i = 0; i < ui.nicknameList->count(); i++) existing << ui.nicknameList->item(i)->text(); + NickEditDlg dlg(old, existing, this); + if (dlg.exec() == QDialog::Accepted) { + ui.nicknameList->selectedItems()[0]->setText(dlg.nick()); + } } -void IdentityEditWidget::on_nickUp_clicked() { - if(!ui.nicknameList->selectedItems().count()) return; - int row = ui.nicknameList->row(ui.nicknameList->selectedItems()[0]); - if(row > 0) { - ui.nicknameList->insertItem(row-1, ui.nicknameList->takeItem(row)); - ui.nicknameList->setCurrentRow(row-1); - setWidgetStates(); - emit widgetHasChanged(); - } + +void IdentityEditWidget::on_nickUp_clicked() +{ + if (!ui.nicknameList->selectedItems().count()) return; + int row = ui.nicknameList->row(ui.nicknameList->selectedItems()[0]); + if (row > 0) { + ui.nicknameList->insertItem(row-1, ui.nicknameList->takeItem(row)); + ui.nicknameList->setCurrentRow(row-1); + setWidgetStates(); + emit widgetHasChanged(); + } } -void IdentityEditWidget::on_nickDown_clicked() { - if(!ui.nicknameList->selectedItems().count()) return; - int row = ui.nicknameList->row(ui.nicknameList->selectedItems()[0]); - if(row < ui.nicknameList->count()-1) { - ui.nicknameList->insertItem(row+1, ui.nicknameList->takeItem(row)); - ui.nicknameList->setCurrentRow(row+1); - setWidgetStates(); - emit widgetHasChanged(); - } + +void IdentityEditWidget::on_nickDown_clicked() +{ + if (!ui.nicknameList->selectedItems().count()) return; + int row = ui.nicknameList->row(ui.nicknameList->selectedItems()[0]); + if (row < ui.nicknameList->count()-1) { + ui.nicknameList->insertItem(row+1, ui.nicknameList->takeItem(row)); + ui.nicknameList->setCurrentRow(row+1); + setWidgetStates(); + emit widgetHasChanged(); + } } -void IdentityEditWidget::showAdvanced(bool advanced) { - int idx = ui.tabWidget->indexOf(ui.advancedTab); - if(advanced) { - if(idx != -1) - return; // already added - ui.tabWidget->addTab(ui.advancedTab, tr("Advanced")); - } else { - if(idx == -1) - return; // already removed - ui.tabWidget->removeTab(idx); - } + +void IdentityEditWidget::showAdvanced(bool advanced) +{ + int idx = ui.tabWidget->indexOf(ui.advancedTab); + if (advanced) { + if (idx != -1) + return; // already added + ui.tabWidget->addTab(ui.advancedTab, tr("Advanced")); + } + else { + if (idx == -1) + return; // already removed + ui.tabWidget->removeTab(idx); + } } -void IdentityEditWidget::setSslState(SslState state) { - switch(state) { - case NoSsl: - ui.keyAndCertSettings->setCurrentIndex(0); - break; - case UnsecureSsl: - ui.keyAndCertSettings->setCurrentIndex(1); - break; - case AllowSsl: - ui.keyAndCertSettings->setCurrentIndex(2); - break; - } + +void IdentityEditWidget::setSslState(SslState state) +{ + switch (state) { + case NoSsl: + ui.keyAndCertSettings->setCurrentIndex(0); + break; + case UnsecureSsl: + ui.keyAndCertSettings->setCurrentIndex(1); + break; + case AllowSsl: + ui.keyAndCertSettings->setCurrentIndex(2); + break; + } } + #ifdef HAVE_SSL -bool IdentityEditWidget::eventFilter(QObject *watched, QEvent *event) { - bool isCert = (watched == ui.sslCertGroupBox); - switch(event->type()) { - case QEvent::DragEnter: - sslDragEnterEvent(static_cast(event)); - return true; - case QEvent::Drop: - sslDropEvent(static_cast(event), isCert); - return true; - default: - return false; - } +bool IdentityEditWidget::eventFilter(QObject *watched, QEvent *event) +{ + bool isCert = (watched == ui.sslCertGroupBox); + switch (event->type()) { + case QEvent::DragEnter: + sslDragEnterEvent(static_cast(event)); + return true; + case QEvent::Drop: + sslDropEvent(static_cast(event), isCert); + return true; + default: + return false; + } } -void IdentityEditWidget::sslDragEnterEvent(QDragEnterEvent *event) { - if(event->mimeData()->hasFormat("text/uri-list") || event->mimeData()->hasFormat("text/uri")) { - event->setDropAction(Qt::CopyAction); - event->accept(); - } + +void IdentityEditWidget::sslDragEnterEvent(QDragEnterEvent *event) +{ + if (event->mimeData()->hasFormat("text/uri-list") || event->mimeData()->hasFormat("text/uri")) { + event->setDropAction(Qt::CopyAction); + event->accept(); + } } -void IdentityEditWidget::sslDropEvent(QDropEvent *event, bool isCert) { - QByteArray rawUris; - if(event->mimeData()->hasFormat("text/uri-list")) - rawUris = event->mimeData()->data("text/uri-list"); - else - rawUris = event->mimeData()->data("text/uri"); - - QTextStream uriStream(rawUris); - QString filename = QUrl(uriStream.readLine()).toLocalFile(); - - if(isCert) { - QSslCertificate cert = certByFilename(filename); - if(cert.isValid()) - showCertState(cert); - } else { - QSslKey key = keyByFilename(filename); - if(!key.isNull()) - showKeyState(key); - } - event->accept(); - emit widgetHasChanged(); + +void IdentityEditWidget::sslDropEvent(QDropEvent *event, bool isCert) +{ + QByteArray rawUris; + if (event->mimeData()->hasFormat("text/uri-list")) + rawUris = event->mimeData()->data("text/uri-list"); + else + rawUris = event->mimeData()->data("text/uri"); + + QTextStream uriStream(rawUris); + QString filename = QUrl(uriStream.readLine()).toLocalFile(); + + if (isCert) { + QSslCertificate cert = certByFilename(filename); + if (cert.isValid()) + showCertState(cert); + } + else { + QSslKey key = keyByFilename(filename); + if (!key.isNull()) + showKeyState(key); + } + event->accept(); + emit widgetHasChanged(); } -void IdentityEditWidget::on_clearOrLoadKeyButton_clicked() { - QSslKey key; - if(ui.keyTypeLabel->property("sslKey").toByteArray().isEmpty()) - key = keyByFilename(QFileDialog::getOpenFileName(this, tr("Load a Key"), QDesktopServices::storageLocation(QDesktopServices::HomeLocation))); +void IdentityEditWidget::on_clearOrLoadKeyButton_clicked() +{ + QSslKey key; - showKeyState(key); - emit widgetHasChanged(); -} + if (ui.keyTypeLabel->property("sslKey").toByteArray().isEmpty()) + key = keyByFilename(QFileDialog::getOpenFileName(this, tr("Load a Key"), QDesktopServices::storageLocation(QDesktopServices::HomeLocation))); -QSslKey IdentityEditWidget::keyByFilename(const QString &filename) { - QSslKey key; + showKeyState(key); + emit widgetHasChanged(); +} - QFile keyFile(filename); - keyFile.open(QIODevice::ReadOnly); - QByteArray keyRaw = keyFile.read(2 << 20); - keyFile.close(); - for(int i = 0; i < 2; i++) { - for(int j = 0; j < 2; j++) { - key = QSslKey(keyRaw, (QSsl::KeyAlgorithm)j, (QSsl::EncodingFormat)i); - if(!key.isNull()) - goto returnKey; +QSslKey IdentityEditWidget::keyByFilename(const QString &filename) +{ + QSslKey key; + + QFile keyFile(filename); + keyFile.open(QIODevice::ReadOnly); + QByteArray keyRaw = keyFile.read(2 << 20); + keyFile.close(); + + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + key = QSslKey(keyRaw, (QSsl::KeyAlgorithm)j, (QSsl::EncodingFormat)i); + if (!key.isNull()) + goto returnKey; + } } - } - returnKey: - return key; +returnKey: + return key; } -void IdentityEditWidget::showKeyState(const QSslKey &key) { - if(key.isNull()) { - ui.keyTypeLabel->setText(tr("No Key loaded")); - ui.clearOrLoadKeyButton->setText(tr("Load")); - } else { - switch(key.algorithm()) { - case QSsl::Rsa: - ui.keyTypeLabel->setText(tr("RSA")); - break; - case QSsl::Dsa: - ui.keyTypeLabel->setText(tr("DSA")); - break; - default: - ui.keyTypeLabel->setText(tr("No Key loaded")); + +void IdentityEditWidget::showKeyState(const QSslKey &key) +{ + if (key.isNull()) { + ui.keyTypeLabel->setText(tr("No Key loaded")); + ui.clearOrLoadKeyButton->setText(tr("Load")); + } + else { + switch (key.algorithm()) { + case QSsl::Rsa: + ui.keyTypeLabel->setText(tr("RSA")); + break; + case QSsl::Dsa: + ui.keyTypeLabel->setText(tr("DSA")); + break; + default: + ui.keyTypeLabel->setText(tr("No Key loaded")); + } + ui.clearOrLoadKeyButton->setText(tr("Clear")); } - ui.clearOrLoadKeyButton->setText(tr("Clear")); - } - ui.keyTypeLabel->setProperty("sslKey", key.toPem()); - ui.keyTypeLabel->setProperty("sslKeyType", (int)key.algorithm()); + ui.keyTypeLabel->setProperty("sslKey", key.toPem()); + ui.keyTypeLabel->setProperty("sslKeyType", (int)key.algorithm()); } -void IdentityEditWidget::on_clearOrLoadCertButton_clicked() { - QSslCertificate cert; - if(ui.certOrgLabel->property("sslCert").toByteArray().isEmpty()) - cert = certByFilename(QFileDialog::getOpenFileName(this, tr("Load a Certificate"), QDesktopServices::storageLocation(QDesktopServices::HomeLocation))); +void IdentityEditWidget::on_clearOrLoadCertButton_clicked() +{ + QSslCertificate cert; + + if (ui.certOrgLabel->property("sslCert").toByteArray().isEmpty()) + cert = certByFilename(QFileDialog::getOpenFileName(this, tr("Load a Certificate"), QDesktopServices::storageLocation(QDesktopServices::HomeLocation))); + + showCertState(cert); + emit widgetHasChanged(); +} + - showCertState(cert); - emit widgetHasChanged(); +QSslCertificate IdentityEditWidget::certByFilename(const QString &filename) +{ + QSslCertificate cert; + QFile certFile(filename); + certFile.open(QIODevice::ReadOnly); + QByteArray certRaw = certFile.read(2 << 20); + certFile.close(); + + for (int i = 0; i < 2; i++) { + cert = QSslCertificate(certRaw, (QSsl::EncodingFormat)i); + if (cert.isValid()) + break; + } + return cert; } -QSslCertificate IdentityEditWidget::certByFilename(const QString &filename) { - QSslCertificate cert; - QFile certFile(filename); - certFile.open(QIODevice::ReadOnly); - QByteArray certRaw = certFile.read(2 << 20); - certFile.close(); - - for(int i = 0; i < 2; i++) { - cert = QSslCertificate(certRaw, (QSsl::EncodingFormat)i); - if(cert.isValid()) - break; - } - return cert; + +void IdentityEditWidget::showCertState(const QSslCertificate &cert) +{ + if (!cert.isValid()) { + ui.certOrgLabel->setText(tr("No Certificate loaded")); + ui.certCNameLabel->setText(tr("No Certificate loaded")); + ui.clearOrLoadCertButton->setText(tr("Load")); + } + else { + ui.certOrgLabel->setText(cert.subjectInfo(QSslCertificate::Organization)); + ui.certCNameLabel->setText(cert.subjectInfo(QSslCertificate::CommonName)); + ui.clearOrLoadCertButton->setText(tr("Clear")); + } + ui.certOrgLabel->setProperty("sslCert", cert.toPem()); } -void IdentityEditWidget::showCertState(const QSslCertificate &cert) { - if(!cert.isValid()) { - ui.certOrgLabel->setText(tr("No Certificate loaded")); - ui.certCNameLabel->setText(tr("No Certificate loaded")); - ui.clearOrLoadCertButton->setText(tr("Load")); - } else { - ui.certOrgLabel->setText(cert.subjectInfo(QSslCertificate::Organization)); - ui.certCNameLabel->setText(cert.subjectInfo(QSslCertificate::CommonName)); - ui.clearOrLoadCertButton->setText(tr("Clear")); - } - ui.certOrgLabel->setProperty("sslCert", cert.toPem()); - } + #endif //HAVE_SSL diff --git a/src/qtui/settingspages/identityeditwidget.h b/src/qtui/settingspages/identityeditwidget.h index 6516c577..1f83b0ba 100644 --- a/src/qtui/settingspages/identityeditwidget.h +++ b/src/qtui/settingspages/identityeditwidget.h @@ -31,83 +31,86 @@ #include "clientidentity.h" -class IdentityEditWidget : public QWidget { - Q_OBJECT +class IdentityEditWidget : public QWidget +{ + Q_OBJECT public: - IdentityEditWidget(QWidget *parent = 0); + IdentityEditWidget(QWidget *parent = 0); - enum SslState { - NoSsl, - UnsecureSsl, - AllowSsl - }; + enum SslState { + NoSsl, + UnsecureSsl, + AllowSsl + }; - void displayIdentity(CertIdentity *id, CertIdentity *saveId = 0); - void saveToIdentity(CertIdentity *id); + void displayIdentity(CertIdentity *id, CertIdentity *saveId = 0); + void saveToIdentity(CertIdentity *id); public slots: - void setSslState(SslState state); - void showAdvanced(bool advanced); + void setSslState(SslState state); + void showAdvanced(bool advanced); protected: #ifdef HAVE_SSL - virtual bool eventFilter(QObject *watched, QEvent *event); + virtual bool eventFilter(QObject *watched, QEvent *event); #endif signals: - void requestEditSsl(); - void widgetHasChanged(); + void requestEditSsl(); + void widgetHasChanged(); private slots: - void on_addNick_clicked(); - void on_deleteNick_clicked(); - void on_renameNick_clicked(); - void on_nickUp_clicked(); - void on_nickDown_clicked(); + void on_addNick_clicked(); + void on_deleteNick_clicked(); + void on_renameNick_clicked(); + void on_nickUp_clicked(); + void on_nickDown_clicked(); #ifdef HAVE_SSL - void on_clearOrLoadKeyButton_clicked(); - void on_clearOrLoadCertButton_clicked(); + void on_clearOrLoadKeyButton_clicked(); + void on_clearOrLoadCertButton_clicked(); #endif - void setWidgetStates(); + void setWidgetStates(); #ifdef HAVE_SSL - void sslDragEnterEvent(QDragEnterEvent *event); - void sslDropEvent(QDropEvent *event, bool isCert); + void sslDragEnterEvent(QDragEnterEvent *event); + void sslDropEvent(QDropEvent *event, bool isCert); #endif private: - Ui::IdentityEditWidget ui; - bool _editSsl; + Ui::IdentityEditWidget ui; + bool _editSsl; #ifdef HAVE_SSL - QSslKey keyByFilename(const QString &filename); - void showKeyState(const QSslKey &key); - QSslCertificate certByFilename(const QString &filename); - void showCertState(const QSslCertificate &cert); + QSslKey keyByFilename(const QString &filename); + void showKeyState(const QSslKey &key); + QSslCertificate certByFilename(const QString &filename); + void showCertState(const QSslCertificate &cert); #endif - bool testHasChanged(); + bool testHasChanged(); }; -class NickEditDlg : public QDialog { - Q_OBJECT + +class NickEditDlg : public QDialog +{ + Q_OBJECT public: - NickEditDlg(const QString &oldnick, const QStringList &existing = QStringList(), QWidget *parent = 0); + NickEditDlg(const QString &oldnick, const QStringList &existing = QStringList(), QWidget *parent = 0); - QString nick() const; + QString nick() const; private slots: - void on_nickEdit_textChanged(const QString &); + void on_nickEdit_textChanged(const QString &); private: - Ui::NickEditDlg ui; - - QString oldNick; - QStringList existing; + Ui::NickEditDlg ui; + QString oldNick; + QStringList existing; }; + #endif //IDENTITYEDITWIDGET_H diff --git a/src/qtui/settingspages/ignorelistmodel.cpp b/src/qtui/settingspages/ignorelistmodel.cpp index b6b44bf3..99d6231b 100644 --- a/src/qtui/settingspages/ignorelistmodel.cpp +++ b/src/qtui/settingspages/ignorelistmodel.cpp @@ -28,258 +28,297 @@ #include "signalproxy.h" IgnoreListModel::IgnoreListModel(QObject *parent) - : QAbstractItemModel(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); + // 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 "Type:
" - "BySender:
" - "The ignore rule is matched against the nick!ident@host.mask sender-string.
" - "ByMessage:
" - "The ignore rule is matched against the message content."; - case 1: - return "Strictness:
" - "Dynamic:
" - "Messages are hidden but still get stored in the database.
Deactivate or delete an ignore rule to show the messages again
" - "Permanent:
" - "Messages are never stored or shown anywhere."; - */ - case 0: - return tr("Enable / Disable:
" - "Only enabled rules are filtered.
" - "For dynamic rules, disabling actually shows the filtered messages again"); - case 2: - return tr("Ignore rule:
" - "Depending on the type of the rule, the text is matched against either:

" - "- the message content:
" - "Example:
" - " \"*foobar*\" matches any text containing the word \"foobar\"

" - "- the sender string nick!ident@host.name
" - "Example:
" - " \"*@foobar.com\" matches any sender from host foobar.com
" - " \"stupid!.+\" (RegEx) matches any sender with nickname \"stupid\" from any host
"); +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 "Type:
" + "BySender:
" + "The ignore rule is matched against the nick!ident@host.mask sender-string.
" + "ByMessage:
" + "The ignore rule is matched against the message content."; + case 1: + return "Strictness:
" + "Dynamic:
" + "Messages are hidden but still get stored in the database.
Deactivate or delete an ignore rule to show the messages again
" + "Permanent:
" + "Messages are never stored or shown anywhere."; + */ + case 0: + return tr("Enable / Disable:
" + "Only enabled rules are filtered.
" + "For dynamic rules, disabling actually shows the filtered messages again"); + case 2: + return tr("Ignore rule:
" + "Depending on the type of the rule, the text is matched against either:

" + "- the message content:
" + "Example:
" + " \"*foobar*\" matches any text containing the word \"foobar\"

" + "- the sender string nick!ident@host.name
" + "Example:
" + " \"*@foobar.com\" matches any sender from host foobar.com
" + " \"stupid!.+\" (RegEx) matches any sender with nickname \"stupid\" from any host
"); + 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(); - } - case Qt::DisplayRole: - switch(index.column()) { - case 1: - if(ignoreListManager()[index.row()].type == IgnoreListManager::SenderIgnore) - return tr("By Sender"); - else - return tr("By Message"); + return QVariant(); } - case Qt::EditRole: - switch(index.column()) { +} + + +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: - return ignoreListManager()[index.row()].isActive; + cloneIgnoreListManager()[index.row()].isActive = newValue.toBool(); + return true; case 1: - return ignoreListManager()[index.row()].type; + cloneIgnoreListManager()[index.row()].type = (IgnoreListManager::IgnoreType)newValue.toInt(); + return true; case 2: - return ignoreListManager()[index.row()].ignoreRule; + if (ignoreListManager().contains(newValue.toString())) { + return false; + } + else { + cloneIgnoreListManager()[index.row()].ignoreRule = newValue.toString(); + return true; + } default: - return QVariant(); + return false; } - 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; +bool IgnoreListModel::newIgnoreRule(const IgnoreListManager::IgnoreListItem &item) +{ + IgnoreListManager &manager = cloneIgnoreListManager(); + if (manager.contains(item.ignoreRule)) + return false; + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + // manager.addIgnoreListItem(item); + manager.addIgnoreListItem(item.type, item.ignoreRule, item.isRegEx, item.strictness, item.scope, + item.scopeRule, item.isActive); + endInsertRows(); + return true; +} - 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; +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(); } - 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); - manager.addIgnoreListItem(item.type, item.ignoreRule, item.isRegEx, item.strictness, item.scope, - item.scopeRule, item.isActive); - endInsertRows(); - return true; + 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::loadDefaults() { - /*if(!_modelReady) - return; - IgnoreListManager &manager = cloneIgnoreListManager(); +void IgnoreListModel::removeIgnoreRule(int index) +{ + if (index < 0 || index >= rowCount()) + return; - if(!manager.isEmpty()) { - beginRemoveRows(QModelIndex(), 0, rowCount() - 1); - for(int i = rowCount() - 1; i >= 0; i--) - manager.removeAt(i); + IgnoreListManager &manager = cloneIgnoreListManager(); + beginRemoveRows(QModelIndex(), index, index); + manager.removeAt(index); 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; + } } -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]; -QVariant IgnoreListModel::headerData(int section, Qt::Orientation orientation, int role) const { - QStringList header; - header << tr("Enabled") - << tr("Type") - << tr("Ignore Rule"); + return QVariant(); +} - 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); } -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(); } -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::ignoreListManager() { - if(_configChanged) + +IgnoreListManager &IgnoreListModel::cloneIgnoreListManager() +{ + if (!_configChanged) { + _clonedIgnoreListManager = *Client::ignoreListManager(); + _configChanged = true; + emit configChanged(true); + } 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; +void IgnoreListModel::revert() +{ + if (!_configChanged) + return; - _configChanged = false; - emit configChanged(false); - reset(); + _configChanged = false; + emit configChanged(false); + reset(); } -void IgnoreListModel::commit() { - if(!_configChanged) - return; - Client::ignoreListManager()->requestUpdate(_clonedIgnoreListManager.toVariantMap()); - revert(); +void IgnoreListModel::commit() +{ + if (!_configChanged) + return; + + Client::ignoreListManager()->requestUpdate(_clonedIgnoreListManager.toVariantMap()); + revert(); } -void IgnoreListModel::initDone() { - _modelReady = true; - reset(); - emit modelReady(true); + +void IgnoreListModel::initDone() +{ + _modelReady = true; + reset(); + emit modelReady(true); } -void IgnoreListModel::clientConnected() { - connect(Client::ignoreListManager(), SIGNAL(updated()), SLOT(revert())); - if(Client::ignoreListManager()->isInitialized()) - initDone(); - else - connect(Client::ignoreListManager(), SIGNAL(initDone()), SLOT(initDone())); + +void IgnoreListModel::clientConnected() +{ + connect(Client::ignoreListManager(), SIGNAL(updated()), 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); + +void IgnoreListModel::clientDisconnected() +{ + // clear + _clonedIgnoreListManager = ClientIgnoreListManager(); + _modelReady = false; + reset(); + emit modelReady(false); } -const IgnoreListManager::IgnoreListItem &IgnoreListModel::ignoreListItemAt(int row) const { - return ignoreListManager()[row]; + +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)); +void IgnoreListModel::setIgnoreListItemAt(int row, const IgnoreListManager::IgnoreListItem &item) +{ + cloneIgnoreListManager()[row] = item; + emit dataChanged(createIndex(row, 0), createIndex(row, 2)); } -const QModelIndex IgnoreListModel::indexOf(const QString &rule) { - return createIndex(ignoreListManager().indexOf(rule), 2); + +const QModelIndex IgnoreListModel::indexOf(const QString &rule) +{ + return createIndex(ignoreListManager().indexOf(rule), 2); } diff --git a/src/qtui/settingspages/ignorelistmodel.h b/src/qtui/settingspages/ignorelistmodel.h index f6a3eadf..31c658a0 100644 --- a/src/qtui/settingspages/ignorelistmodel.h +++ b/src/qtui/settingspages/ignorelistmodel.h @@ -26,68 +26,74 @@ #include "clientignorelistmanager.h" -class IgnoreListModel : public QAbstractItemModel { - Q_OBJECT +class IgnoreListModel : public QAbstractItemModel +{ + Q_OBJECT public: - IgnoreListModel(QObject *parent = 0); + 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 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; + virtual Qt::ItemFlags flags(const QModelIndex &index) const; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; - inline QModelIndex parent(const QModelIndex &) const { return QModelIndex(); } + 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 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; } + 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); - const QModelIndex indexOf(const QString &rule); + const IgnoreListManager::IgnoreListItem &ignoreListItemAt(int row) const; + void setIgnoreListItemAt(int row, const IgnoreListManager::IgnoreListItem &item); + bool newIgnoreRule(const IgnoreListManager::IgnoreListItem &item); + const QModelIndex indexOf(const QString &rule); public slots: - void loadDefaults(); - void removeIgnoreRule(int index); - void revert(); - void commit(); + void loadDefaults(); + void removeIgnoreRule(int index); + void revert(); + void commit(); signals: - void configChanged(bool); - void modelReady(bool); + void configChanged(bool); + void modelReady(bool); private: - ClientIgnoreListManager _clonedIgnoreListManager; - bool _configChanged; - bool _modelReady; + ClientIgnoreListManager _clonedIgnoreListManager; + bool _configChanged; + bool _modelReady; - const IgnoreListManager &ignoreListManager() const; - IgnoreListManager &ignoreListManager(); - IgnoreListManager &cloneIgnoreListManager(); + const IgnoreListManager &ignoreListManager() const; + IgnoreListManager &ignoreListManager(); + IgnoreListManager &cloneIgnoreListManager(); private slots: - void clientConnected(); - void clientDisconnected(); - void initDone(); + void clientConnected(); + void clientDisconnected(); + void initDone(); }; + // Inlines -int IgnoreListModel::rowCount(const QModelIndex &parent) const { - Q_UNUSED(parent); - return isReady() ? ignoreListManager().count() : 0; +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; + +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 index 90ea712e..f1b56028 100644 --- a/src/qtui/settingspages/ignorelistsettingspage.cpp +++ b/src/qtui/settingspages/ignorelistsettingspage.cpp @@ -31,297 +31,327 @@ #include "iconloader.h" IgnoreListSettingsPage::IgnoreListSettingsPage(QWidget *parent) - : SettingsPage(tr("IRC"), tr("Ignore List"), parent) + : SettingsPage(tr("IRC"), tr("Ignore List"), 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()); + 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; + +IgnoreListSettingsPage::~IgnoreListSettingsPage() +{ + delete _delegate; } -void IgnoreListSettingsPage::load() { - if(_ignoreListModel.configChanged()) - _ignoreListModel.revert(); - ui.ignoreListView->selectionModel()->reset(); - ui.editIgnoreRuleButton->setEnabled(false); + +void IgnoreListSettingsPage::load() +{ + if (_ignoreListModel.configChanged()) + _ignoreListModel.revert(); + ui.ignoreListView->selectionModel()->reset(); + ui.editIgnoreRuleButton->setEnabled(false); } -void IgnoreListSettingsPage::defaults() { - _ignoreListModel.loadDefaults(); + +void IgnoreListSettingsPage::defaults() +{ + _ignoreListModel.loadDefaults(); } -void IgnoreListSettingsPage::save() { - if(_ignoreListModel.configChanged()) { - _ignoreListModel.commit(); - } - ui.ignoreListView->selectionModel()->reset(); - ui.editIgnoreRuleButton->setEnabled(false); + +void IgnoreListSettingsPage::save() +{ + if (_ignoreListModel.configChanged()) { + _ignoreListModel.commit(); + } + ui.ignoreListView->selectionModel()->reset(); + ui.editIgnoreRuleButton->setEnabled(false); } -void IgnoreListSettingsPage::enableDialog(bool enabled) { - ui.newIgnoreRuleButton->setEnabled(enabled); - setEnabled(enabled); + +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::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::deleteSelectedIgnoreRule() +{ + if (!ui.ignoreListView->selectionModel()->hasSelection()) + return; + + _ignoreListModel.removeIgnoreRule(ui.ignoreListView->selectionModel()->selectedIndexes()[0].row()); } -void IgnoreListSettingsPage::newIgnoreRule(QString rule) { - IgnoreListManager::IgnoreListItem newItem = IgnoreListManager::IgnoreListItem(); - newItem.strictness = IgnoreListManager::SoftStrictness; - newItem.scope = IgnoreListManager::GlobalScope; - newItem.isRegEx = false; - newItem.isActive = true; - - bool enableOkButton = false; - if(!rule.isEmpty()) { - // we're called from contextmenu - newItem.ignoreRule = rule; - enableOkButton = true; - } - - IgnoreListEditDlg *dlg = new IgnoreListEditDlg(newItem, this, enableOkButton); - dlg->enableOkButton(enableOkButton); - 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(item, this); +void IgnoreListSettingsPage::newIgnoreRule(QString rule) +{ + IgnoreListManager::IgnoreListItem newItem = IgnoreListManager::IgnoreListItem(); + newItem.strictness = IgnoreListManager::SoftStrictness; + newItem.scope = IgnoreListManager::GlobalScope; + newItem.isRegEx = false; + newItem.isActive = true; + + bool enableOkButton = false; + if (!rule.isEmpty()) { + // we're called from contextmenu + newItem.ignoreRule = rule; + enableOkButton = true; } - else { - break; + + IgnoreListEditDlg *dlg = new IgnoreListEditDlg(newItem, this, enableOkButton); + dlg->enableOkButton(enableOkButton); + 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(item, this); + } + else { + break; + } } - } - dlg->deleteLater(); + dlg->deleteLater(); } -void IgnoreListSettingsPage::editSelectedIgnoreRule() { - if(!ui.ignoreListView->selectionModel()->hasSelection()) - return; - int row = ui.ignoreListView->selectionModel()->selectedIndexes()[0].row(); - IgnoreListEditDlg dlg(_ignoreListModel.ignoreListItemAt(row), this); - dlg.setAttribute(Qt::WA_DeleteOnClose, false); - if(dlg.exec() == QDialog::Accepted) { - _ignoreListModel.setIgnoreListItemAt(row, dlg.ignoreListItem()); - } + +void IgnoreListSettingsPage::editSelectedIgnoreRule() +{ + if (!ui.ignoreListView->selectionModel()->hasSelection()) + return; + int row = ui.ignoreListView->selectionModel()->selectedIndexes()[0].row(); + IgnoreListEditDlg dlg(_ignoreListModel.ignoreListItemAt(row), this); + dlg.setAttribute(Qt::WA_DeleteOnClose, false); + if (dlg.exec() == QDialog::Accepted) { + _ignoreListModel.setIgnoreListItemAt(row, dlg.ignoreListItem()); + } } -void IgnoreListSettingsPage::editIgnoreRule(const QString &ignoreRule) { - ui.ignoreListView->selectionModel()->select(_ignoreListModel.indexOf(ignoreRule), QItemSelectionModel::Select); - if(ui.ignoreListView->selectionModel()->hasSelection())// && ui.ignoreListView->selectionModel()->selectedIndexes()[0].row() != -1) - editSelectedIgnoreRule(); - else - newIgnoreRule(ignoreRule); + +void IgnoreListSettingsPage::editIgnoreRule(const QString &ignoreRule) +{ + ui.ignoreListView->selectionModel()->select(_ignoreListModel.indexOf(ignoreRule), QItemSelectionModel::Select); + if (ui.ignoreListView->selectionModel()->hasSelection()) // && ui.ignoreListView->selectionModel()->selectedIndexes()[0].row() != -1) + editSelectedIgnoreRule(); + else + newIgnoreRule(ignoreRule); } + /* IgnoreListDelegate */ -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); +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); } + // provide interactivity for the checkboxes bool IgnoreListDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, - const QStyleOptionViewItem &option, const QModelIndex &index) { - Q_UNUSED(option) - switch(event->type()) { + 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 + model->setData(index, !index.data().toBool()); + return true; + // don't show the default editor for the column case QEvent::MouseButtonDblClick: - return true; + return true; default: - return false; - } + return false; + } } + /* IgnoreListEditDlg */ IgnoreListEditDlg::IgnoreListEditDlg(const IgnoreListManager::IgnoreListItem &item, QWidget *parent, bool enabled) - : QDialog(parent), _ignoreListItem(item), _hasChanged(enabled) { - ui.setupUi(this); - setAttribute(Qt::WA_DeleteOnClose, false); - setModal(true); - // FIXME patch out the bugger completely if it's good without it - ui.isActiveCheckBox->hide(); - - // setup buttongroups - // this could be moved to .ui file with qt4.5 - _typeButtonGroup.addButton(ui.senderTypeButton, 0); - _typeButtonGroup.addButton(ui.messageTypeButton, 1); - _typeButtonGroup.addButton(ui.ctcpTypeButton, 2); - _strictnessButtonGroup.addButton(ui.dynamicStrictnessButton, 0); - _strictnessButtonGroup.addButton(ui.permanentStrictnessButton, 1); - _scopeButtonGroup.addButton(ui.globalScopeButton, 0); - _scopeButtonGroup.addButton(ui.networkScopeButton, 1); - _scopeButtonGroup.addButton(ui.channelScopeButton, 2); - - ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - - ui.ignoreRuleLineEdit->setText(item.ignoreRule); - - if(item.type == IgnoreListManager::MessageIgnore) - ui.messageTypeButton->setChecked(true); - else if(item.type == IgnoreListManager::CtcpIgnore) - ui.ctcpTypeButton->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) { + : QDialog(parent), _ignoreListItem(item), _hasChanged(enabled) +{ + ui.setupUi(this); + setAttribute(Qt::WA_DeleteOnClose, false); + setModal(true); + // FIXME patch out the bugger completely if it's good without it + ui.isActiveCheckBox->hide(); + + // setup buttongroups + // this could be moved to .ui file with qt4.5 + _typeButtonGroup.addButton(ui.senderTypeButton, 0); + _typeButtonGroup.addButton(ui.messageTypeButton, 1); + _typeButtonGroup.addButton(ui.ctcpTypeButton, 2); + _strictnessButtonGroup.addButton(ui.dynamicStrictnessButton, 0); + _strictnessButtonGroup.addButton(ui.permanentStrictnessButton, 1); + _scopeButtonGroup.addButton(ui.globalScopeButton, 0); + _scopeButtonGroup.addButton(ui.networkScopeButton, 1); + _scopeButtonGroup.addButton(ui.channelScopeButton, 2); + + ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + + ui.ignoreRuleLineEdit->setText(item.ignoreRule); + + if (item.type == IgnoreListManager::MessageIgnore) + ui.messageTypeButton->setChecked(true); + else if (item.type == IgnoreListManager::CtcpIgnore) + ui.ctcpTypeButton->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; + ui.networkScopeButton->setChecked(true); + ui.scopeRuleTextEdit->setEnabled(true); + break; case IgnoreListManager::ChannelScope: - ui.channelScopeButton->setChecked(true); - ui.scopeRuleTextEdit->setEnabled(true); - break; + 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(&_typeButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(widgetHasChanged())); - connect(&_strictnessButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(widgetHasChanged())); - connect(&_scopeButtonGroup, SIGNAL(buttonClicked(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())); - widgetHasChanged(); + 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(&_typeButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(widgetHasChanged())); + connect(&_strictnessButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(widgetHasChanged())); + connect(&_scopeButtonGroup, SIGNAL(buttonClicked(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())); + widgetHasChanged(); } -void IgnoreListEditDlg::widgetHasChanged() { - if(ui.messageTypeButton->isChecked()) - _clonedIgnoreListItem.type = IgnoreListManager::MessageIgnore; - else if(ui.ctcpTypeButton->isChecked()) - _clonedIgnoreListItem.type = IgnoreListManager::CtcpIgnore; - 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 = it->trimmed(); - ++it; + +void IgnoreListEditDlg::widgetHasChanged() +{ + if (ui.messageTypeButton->isChecked()) + _clonedIgnoreListItem.type = IgnoreListManager::MessageIgnore; + else if (ui.ctcpTypeButton->isChecked()) + _clonedIgnoreListItem.type = IgnoreListManager::CtcpIgnore; + 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); } - _clonedIgnoreListItem.scopeRule = text.join("; "); - } + 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 = it->trimmed(); + ++it; + } + + _clonedIgnoreListItem.scopeRule = text.join("; "); + } - _clonedIgnoreListItem.ignoreRule = ui.ignoreRuleLineEdit->text(); - _clonedIgnoreListItem.isRegEx = ui.isRegExCheckBox->isChecked(); - _clonedIgnoreListItem.isActive = ui.isActiveCheckBox->isChecked(); + _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); + if (!_clonedIgnoreListItem.ignoreRule.isEmpty() && _clonedIgnoreListItem != _ignoreListItem) + _hasChanged = true; + else + _hasChanged = false; + ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(_hasChanged); } -void IgnoreListEditDlg::enableOkButton(bool state) { - ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(state); + +void IgnoreListEditDlg::enableOkButton(bool state) +{ + ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(state); } diff --git a/src/qtui/settingspages/ignorelistsettingspage.h b/src/qtui/settingspages/ignorelistsettingspage.h index 2313ba9f..bdfc737c 100644 --- a/src/qtui/settingspages/ignorelistsettingspage.h +++ b/src/qtui/settingspages/ignorelistsettingspage.h @@ -35,65 +35,70 @@ class QPainter; class QAbstractItemModel; // the delegate is used to draw the checkbox in column 0 -class IgnoreListDelegate : public QStyledItemDelegate { - Q_OBJECT +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); + 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 + +class IgnoreListEditDlg : public QDialog +{ + Q_OBJECT public: - IgnoreListEditDlg(const IgnoreListManager::IgnoreListItem &item, QWidget *parent = 0, bool enabled = false); - inline IgnoreListManager::IgnoreListItem ignoreListItem() { return _ignoreListItem; } - void enableOkButton(bool state); + IgnoreListEditDlg(const IgnoreListManager::IgnoreListItem &item, QWidget *parent = 0, bool enabled = false); + inline IgnoreListManager::IgnoreListItem ignoreListItem() { return _ignoreListItem; } + void enableOkButton(bool state); private slots: - void widgetHasChanged(); - void aboutToAccept() { _ignoreListItem = _clonedIgnoreListItem; } + void widgetHasChanged(); + void aboutToAccept() { _ignoreListItem = _clonedIgnoreListItem; } private: - IgnoreListManager::IgnoreListItem _ignoreListItem; - IgnoreListManager::IgnoreListItem _clonedIgnoreListItem; - bool _hasChanged; - Ui::IgnoreListEditDlg ui; - QButtonGroup _typeButtonGroup; - QButtonGroup _strictnessButtonGroup; - QButtonGroup _scopeButtonGroup; + IgnoreListManager::IgnoreListItem _ignoreListItem; + IgnoreListManager::IgnoreListItem _clonedIgnoreListItem; + bool _hasChanged; + Ui::IgnoreListEditDlg ui; + QButtonGroup _typeButtonGroup; + QButtonGroup _strictnessButtonGroup; + QButtonGroup _scopeButtonGroup; }; -class IgnoreListSettingsPage : public SettingsPage { - Q_OBJECT + +class IgnoreListSettingsPage : public SettingsPage +{ + Q_OBJECT public: - IgnoreListSettingsPage(QWidget *parent = 0); - ~IgnoreListSettingsPage(); - virtual inline bool hasDefaults() const { return false; } - virtual inline bool needsCoreConnection() const { return true; } - void editIgnoreRule(const QString &ignoreRule); + IgnoreListSettingsPage(QWidget *parent = 0); + ~IgnoreListSettingsPage(); + virtual inline bool hasDefaults() const { return false; } + virtual inline bool needsCoreConnection() const { return true; } + void editIgnoreRule(const QString &ignoreRule); public slots: - void save(); - void load(); - void defaults(); - void newIgnoreRule(QString rule = QString()); + void save(); + void load(); + void defaults(); + void newIgnoreRule(QString rule = QString()); private slots: - void enableDialog(bool); - void deleteSelectedIgnoreRule(); - void editSelectedIgnoreRule(); - void selectionChanged(const QItemSelection &selection, const QItemSelection &); + void enableDialog(bool); + void deleteSelectedIgnoreRule(); + void editSelectedIgnoreRule(); + void selectionChanged(const QItemSelection &selection, const QItemSelection &); private: - IgnoreListDelegate *_delegate; - Ui::IgnoreListSettingsPage ui; - IgnoreListModel _ignoreListModel; + IgnoreListDelegate *_delegate; + Ui::IgnoreListSettingsPage ui; + IgnoreListModel _ignoreListModel; }; diff --git a/src/qtui/settingspages/inputwidgetsettingspage.cpp b/src/qtui/settingspages/inputwidgetsettingspage.cpp index 02f4c250..7f5a7dff 100644 --- a/src/qtui/settingspages/inputwidgetsettingspage.cpp +++ b/src/qtui/settingspages/inputwidgetsettingspage.cpp @@ -20,13 +20,13 @@ #include "inputwidgetsettingspage.h" InputWidgetSettingsPage::InputWidgetSettingsPage(QWidget *parent) - : SettingsPage(tr("Interface"), tr("Input Widget"), parent) + : SettingsPage(tr("Interface"), tr("Input Widget"), parent) { - ui.setupUi(this); + ui.setupUi(this); #ifndef HAVE_KDE - ui.enableSpellCheck->hide(); + ui.enableSpellCheck->hide(); #endif - initAutoWidgets(); + initAutoWidgets(); } diff --git a/src/qtui/settingspages/inputwidgetsettingspage.h b/src/qtui/settingspages/inputwidgetsettingspage.h index a42a591e..c7f84d0a 100644 --- a/src/qtui/settingspages/inputwidgetsettingspage.h +++ b/src/qtui/settingspages/inputwidgetsettingspage.h @@ -24,18 +24,20 @@ #include "settingspage.h" #include "ui_inputwidgetsettingspage.h" -class InputWidgetSettingsPage : public SettingsPage { - Q_OBJECT +class InputWidgetSettingsPage : public SettingsPage +{ + Q_OBJECT public: - InputWidgetSettingsPage(QWidget *parent = 0); + InputWidgetSettingsPage(QWidget *parent = 0); - inline bool hasDefaults() const { return true; } + inline bool hasDefaults() const { return true; } private: - Ui::InputWidgetSettingsPage ui; + Ui::InputWidgetSettingsPage ui; - inline QString settingsKey() const { return QString("InputWidget"); } + inline QString settingsKey() const { return QString("InputWidget"); } }; + #endif diff --git a/src/qtui/settingspages/itemviewsettingspage.cpp b/src/qtui/settingspages/itemviewsettingspage.cpp index 56ccdf6b..223c0c83 100644 --- a/src/qtui/settingspages/itemviewsettingspage.cpp +++ b/src/qtui/settingspages/itemviewsettingspage.cpp @@ -25,52 +25,57 @@ #include "qtuistyle.h" ItemViewSettingsPage::ItemViewSettingsPage(QWidget *parent) - : SettingsPage(tr("Interface"), tr("Chat & Nick Lists"), parent), - _mapper(new QSignalMapper(this)) + : SettingsPage(tr("Interface"), tr("Chat & Nick Lists"), parent), + _mapper(new QSignalMapper(this)) { - ui.setupUi(this); + ui.setupUi(this); - _networkItem = new QTreeWidgetItem(ui.bufferViewPreview, QStringList(tr("Network"))); - _networkItem->setFlags(Qt::NoItemFlags); + _networkItem = new QTreeWidgetItem(ui.bufferViewPreview, QStringList(tr("Network"))); + _networkItem->setFlags(Qt::NoItemFlags); - _inactiveBufferItem = new QTreeWidgetItem(_networkItem, QStringList(tr("Inactive"))); - _defaultBufferItem = new QTreeWidgetItem(_networkItem, QStringList(tr("Normal"))); - _unreadBufferItem = new QTreeWidgetItem(_networkItem, QStringList(tr("Unread messages"))); - _highlightedBufferItem = new QTreeWidgetItem(_networkItem, QStringList(tr("Highlight"))); - _activeBufferItem = new QTreeWidgetItem(_networkItem, QStringList(tr("Other activity"))); + _inactiveBufferItem = new QTreeWidgetItem(_networkItem, QStringList(tr("Inactive"))); + _defaultBufferItem = new QTreeWidgetItem(_networkItem, QStringList(tr("Normal"))); + _unreadBufferItem = new QTreeWidgetItem(_networkItem, QStringList(tr("Unread messages"))); + _highlightedBufferItem = new QTreeWidgetItem(_networkItem, QStringList(tr("Highlight"))); + _activeBufferItem = new QTreeWidgetItem(_networkItem, QStringList(tr("Other activity"))); - ui.bufferViewPreview->expandAll(); + ui.bufferViewPreview->expandAll(); - foreach(ColorButton *button, findChildren()) { - connect(button, SIGNAL(colorChanged(QColor)), _mapper, SLOT(map())); - _mapper->setMapping(button, button); - } - connect(_mapper, SIGNAL(mapped(QWidget *)), SLOT(updateBufferViewPreview(QWidget *))); + foreach(ColorButton *button, findChildren()) { + connect(button, SIGNAL(colorChanged(QColor)), _mapper, SLOT(map())); + _mapper->setMapping(button, button); + } + connect(_mapper, SIGNAL(mapped(QWidget *)), SLOT(updateBufferViewPreview(QWidget *))); - initAutoWidgets(); + initAutoWidgets(); } -void ItemViewSettingsPage::save() { - SettingsPage::save(); - QtUi::style()->generateSettingsQss(); - QtUi::style()->reload(); + +void ItemViewSettingsPage::save() +{ + SettingsPage::save(); + QtUi::style()->generateSettingsQss(); + QtUi::style()->reload(); } -void ItemViewSettingsPage::updateBufferViewPreview(QWidget *widget) { - ColorButton *button = qobject_cast(widget); - if(!button) - return; - QString objName = button->objectName(); - if(objName == "defaultBufferColor") { - _networkItem->setForeground(0, button->color()); - _defaultBufferItem->setForeground(0, button->color()); - } else if(objName == "inactiveBufferColor") - _inactiveBufferItem->setForeground(0, button->color()); - else if(objName == "activeBufferColor") - _activeBufferItem->setForeground(0, button->color()); - else if(objName == "unreadBufferColor") - _unreadBufferItem->setForeground(0, button->color()); - else if(objName == "highlightedBufferColor") - _highlightedBufferItem->setForeground(0, button->color()); +void ItemViewSettingsPage::updateBufferViewPreview(QWidget *widget) +{ + ColorButton *button = qobject_cast(widget); + if (!button) + return; + + QString objName = button->objectName(); + if (objName == "defaultBufferColor") { + _networkItem->setForeground(0, button->color()); + _defaultBufferItem->setForeground(0, button->color()); + } + else if (objName == "inactiveBufferColor") + _inactiveBufferItem->setForeground(0, button->color()); + else if (objName == "activeBufferColor") + _activeBufferItem->setForeground(0, button->color()); + else if (objName == "unreadBufferColor") + _unreadBufferItem->setForeground(0, button->color()); + else if (objName == "highlightedBufferColor") + _highlightedBufferItem->setForeground(0, button->color()); } diff --git a/src/qtui/settingspages/itemviewsettingspage.h b/src/qtui/settingspages/itemviewsettingspage.h index 4b184c40..1f7d1b3a 100644 --- a/src/qtui/settingspages/itemviewsettingspage.h +++ b/src/qtui/settingspages/itemviewsettingspage.h @@ -28,27 +28,29 @@ class ColorButton; class QSignalMapper; class QTreeWidgetItem; -class ItemViewSettingsPage : public SettingsPage { - Q_OBJECT +class ItemViewSettingsPage : public SettingsPage +{ + Q_OBJECT public: - ItemViewSettingsPage(QWidget *parent = 0); + ItemViewSettingsPage(QWidget *parent = 0); - inline bool hasDefaults() const { return true; } + inline bool hasDefaults() const { return true; } public slots: - void save(); + void save(); private slots: - void updateBufferViewPreview(QWidget *button); + void updateBufferViewPreview(QWidget *button); private: - Ui::ItemViewSettingsPage ui; - QSignalMapper *_mapper; - QTreeWidgetItem *_networkItem, *_defaultBufferItem, *_inactiveBufferItem, - *_activeBufferItem, *_unreadBufferItem, *_highlightedBufferItem; + Ui::ItemViewSettingsPage ui; + QSignalMapper *_mapper; + QTreeWidgetItem *_networkItem, *_defaultBufferItem, *_inactiveBufferItem, + *_activeBufferItem, *_unreadBufferItem, *_highlightedBufferItem; - inline QString settingsKey() const { return QString("ItemViews"); } + inline QString settingsKey() const { return QString("ItemViews"); } }; + #endif diff --git a/src/qtui/settingspages/keysequencewidget.cpp b/src/qtui/settingspages/keysequencewidget.cpp index 745c341a..2dc38d55 100644 --- a/src/qtui/settingspages/keysequencewidget.cpp +++ b/src/qtui/settingspages/keysequencewidget.cpp @@ -43,334 +43,362 @@ #include "keysequencewidget.h" KeySequenceButton::KeySequenceButton(KeySequenceWidget *d_, QWidget *parent) - : QPushButton(parent), - d(d_) + : QPushButton(parent), + d(d_) { - } -bool KeySequenceButton::event(QEvent *e) { - if(d->isRecording() && e->type() == QEvent::KeyPress) { - keyPressEvent(static_cast(e)); - return true; - } - // The shortcut 'alt+c' ( or any other dialog local action shortcut ) - // ended the recording and triggered the action associated with the - // action. In case of 'alt+c' ending the dialog. It seems that those - // ShortcutOverride events get sent even if grabKeyboard() is active. - if(d->isRecording() && e->type() == QEvent::ShortcutOverride) { - e->accept(); - return true; - } +bool KeySequenceButton::event(QEvent *e) +{ + if (d->isRecording() && e->type() == QEvent::KeyPress) { + keyPressEvent(static_cast(e)); + return true; + } + + // The shortcut 'alt+c' ( or any other dialog local action shortcut ) + // ended the recording and triggered the action associated with the + // action. In case of 'alt+c' ending the dialog. It seems that those + // ShortcutOverride events get sent even if grabKeyboard() is active. + if (d->isRecording() && e->type() == QEvent::ShortcutOverride) { + e->accept(); + return true; + } - return QPushButton::event(e); + return QPushButton::event(e); } -void KeySequenceButton::keyPressEvent(QKeyEvent *e) { - int keyQt = e->key(); - if(keyQt == -1) { - // Qt sometimes returns garbage keycodes, I observed -1, if it doesn't know a key. - // We cannot do anything useful with those (several keys have -1, indistinguishable) - // and QKeySequence.toString() will also yield a garbage string. - QMessageBox::information(this, - tr("The key you just pressed is not supported by Qt."), - tr("Unsupported Key")); - return d->cancelRecording(); - } - - uint newModifiers = e->modifiers() & (Qt::SHIFT | Qt::CTRL | Qt::ALT | Qt::META); - - //don't have the return or space key appear as first key of the sequence when they - //were pressed to start editing - catch and them and imitate their effect - if(!d->isRecording() && ((keyQt == Qt::Key_Return || keyQt == Qt::Key_Space))) { - d->startRecording(); - d->_modifierKeys = newModifiers; - d->updateShortcutDisplay(); - return; - } - - // We get events even if recording isn't active. - if(!d->isRecording()) - return QPushButton::keyPressEvent(e); - - e->accept(); - d->_modifierKeys = newModifiers; - - switch(keyQt) { - case Qt::Key_AltGr: //or else we get unicode salad - return; - case Qt::Key_Shift: - case Qt::Key_Control: - case Qt::Key_Alt: - case Qt::Key_Meta: - case Qt::Key_Menu: //unused (yes, but why?) - d->updateShortcutDisplay(); - break; - - default: - if(!(d->_modifierKeys & ~Qt::SHIFT)) { - // It's the first key and no modifier pressed. Check if this is - // allowed - if(!d->isOkWhenModifierless(keyQt)) + +void KeySequenceButton::keyPressEvent(QKeyEvent *e) +{ + int keyQt = e->key(); + if (keyQt == -1) { + // Qt sometimes returns garbage keycodes, I observed -1, if it doesn't know a key. + // We cannot do anything useful with those (several keys have -1, indistinguishable) + // and QKeySequence.toString() will also yield a garbage string. + QMessageBox::information(this, + tr("The key you just pressed is not supported by Qt."), + tr("Unsupported Key")); + return d->cancelRecording(); + } + + uint newModifiers = e->modifiers() & (Qt::SHIFT | Qt::CTRL | Qt::ALT | Qt::META); + + //don't have the return or space key appear as first key of the sequence when they + //were pressed to start editing - catch and them and imitate their effect + if (!d->isRecording() && ((keyQt == Qt::Key_Return || keyQt == Qt::Key_Space))) { + d->startRecording(); + d->_modifierKeys = newModifiers; + d->updateShortcutDisplay(); return; } - // We now have a valid key press. - if(keyQt) { - if((keyQt == Qt::Key_Backtab) && (d->_modifierKeys & Qt::SHIFT)) { - keyQt = Qt::Key_Tab | d->_modifierKeys; - } - else if(d->isShiftAsModifierAllowed(keyQt)) { - keyQt |= d->_modifierKeys; - } else - keyQt |= (d->_modifierKeys & ~Qt::SHIFT); - - d->_keySequence = QKeySequence(keyQt); - d->doneRecording(); + // We get events even if recording isn't active. + if (!d->isRecording()) + return QPushButton::keyPressEvent(e); + + e->accept(); + d->_modifierKeys = newModifiers; + + switch (keyQt) { + case Qt::Key_AltGr: //or else we get unicode salad + return; + case Qt::Key_Shift: + case Qt::Key_Control: + case Qt::Key_Alt: + case Qt::Key_Meta: + case Qt::Key_Menu: //unused (yes, but why?) + d->updateShortcutDisplay(); + break; + + default: + if (!(d->_modifierKeys & ~Qt::SHIFT)) { + // It's the first key and no modifier pressed. Check if this is + // allowed + if (!d->isOkWhenModifierless(keyQt)) + return; + } + + // We now have a valid key press. + if (keyQt) { + if ((keyQt == Qt::Key_Backtab) && (d->_modifierKeys & Qt::SHIFT)) { + keyQt = Qt::Key_Tab | d->_modifierKeys; + } + else if (d->isShiftAsModifierAllowed(keyQt)) { + keyQt |= d->_modifierKeys; + } + else + keyQt |= (d->_modifierKeys & ~Qt::SHIFT); + + d->_keySequence = QKeySequence(keyQt); + d->doneRecording(); + } } - } } -void KeySequenceButton::keyReleaseEvent(QKeyEvent *e) { - if(e->key() == -1) { - // ignore garbage, see keyPressEvent() - return; - } - if(!d->isRecording()) - return QPushButton::keyReleaseEvent(e); +void KeySequenceButton::keyReleaseEvent(QKeyEvent *e) +{ + if (e->key() == -1) { + // ignore garbage, see keyPressEvent() + return; + } - e->accept(); + if (!d->isRecording()) + return QPushButton::keyReleaseEvent(e); - uint newModifiers = e->modifiers() & (Qt::SHIFT | Qt::CTRL | Qt::ALT | Qt::META); + e->accept(); - // if a modifier that belongs to the shortcut was released... - if((newModifiers & d->_modifierKeys) < d->_modifierKeys) { - d->_modifierKeys = newModifiers; - d->updateShortcutDisplay(); - } + uint newModifiers = e->modifiers() & (Qt::SHIFT | Qt::CTRL | Qt::ALT | Qt::META); + + // if a modifier that belongs to the shortcut was released... + if ((newModifiers & d->_modifierKeys) < d->_modifierKeys) { + d->_modifierKeys = newModifiers; + d->updateShortcutDisplay(); + } } + /******************************************************************************/ KeySequenceWidget::KeySequenceWidget(QWidget *parent) - : QWidget(parent), - _shortcutsModel(0), - _isRecording(false), - _modifierKeys(0) + : QWidget(parent), + _shortcutsModel(0), + _isRecording(false), + _modifierKeys(0) { - QHBoxLayout *layout = new QHBoxLayout(this); - layout->setMargin(0); + QHBoxLayout *layout = new QHBoxLayout(this); + layout->setMargin(0); - _keyButton = new KeySequenceButton(this, this); - _keyButton->setFocusPolicy(Qt::StrongFocus); - _keyButton->setIcon(SmallIcon("configure")); - _keyButton->setToolTip(tr("Click on the button, then enter the shortcut like you would in the program.\nExample for Ctrl+a: hold the Ctrl key and press a.")); - layout->addWidget(_keyButton); + _keyButton = new KeySequenceButton(this, this); + _keyButton->setFocusPolicy(Qt::StrongFocus); + _keyButton->setIcon(SmallIcon("configure")); + _keyButton->setToolTip(tr("Click on the button, then enter the shortcut like you would in the program.\nExample for Ctrl+a: hold the Ctrl key and press a.")); + layout->addWidget(_keyButton); - _clearButton = new QToolButton(this); - layout->addWidget(_clearButton); + _clearButton = new QToolButton(this); + layout->addWidget(_clearButton); - if(qApp->isLeftToRight()) - _clearButton->setIcon(SmallIcon("edit-clear-locationbar-rtl")); - else - _clearButton->setIcon(SmallIcon("edit-clear-locationbar-ltr")); + if (qApp->isLeftToRight()) + _clearButton->setIcon(SmallIcon("edit-clear-locationbar-rtl")); + else + _clearButton->setIcon(SmallIcon("edit-clear-locationbar-ltr")); - setLayout(layout); + setLayout(layout); - connect(_keyButton, SIGNAL(clicked()), SLOT(startRecording())); - connect(_keyButton, SIGNAL(clicked()), SIGNAL(clicked())); - connect(_clearButton, SIGNAL(clicked()), SLOT(clear())); - connect(_clearButton, SIGNAL(clicked()), SIGNAL(clicked())); + connect(_keyButton, SIGNAL(clicked()), SLOT(startRecording())); + connect(_keyButton, SIGNAL(clicked()), SIGNAL(clicked())); + connect(_clearButton, SIGNAL(clicked()), SLOT(clear())); + connect(_clearButton, SIGNAL(clicked()), SIGNAL(clicked())); } -void KeySequenceWidget::setModel(ShortcutsModel *model) { - Q_ASSERT(!_shortcutsModel); - _shortcutsModel = model; -} -bool KeySequenceWidget::isOkWhenModifierless(int keyQt) const { - //this whole function is a hack, but especially the first line of code - if(QKeySequence(keyQt).toString().length() == 1) - return false; - - switch(keyQt) { - case Qt::Key_Return: - case Qt::Key_Space: - case Qt::Key_Tab: - case Qt::Key_Backtab: //does this ever happen? - case Qt::Key_Backspace: - case Qt::Key_Delete: - return false; - default: - return true; - } +void KeySequenceWidget::setModel(ShortcutsModel *model) +{ + Q_ASSERT(!_shortcutsModel); + _shortcutsModel = model; } -bool KeySequenceWidget::isShiftAsModifierAllowed(int keyQt) const { - // Shift only works as a modifier with certain keys. It's not possible - // to enter the SHIFT+5 key sequence for me because this is handled as - // '%' by qt on my keyboard. - // The working keys are all hardcoded here :-( - if(keyQt >= Qt::Key_F1 && keyQt <= Qt::Key_F35) - return true; - if(QChar(keyQt).isLetter()) - return true; +bool KeySequenceWidget::isOkWhenModifierless(int keyQt) const +{ + //this whole function is a hack, but especially the first line of code + if (QKeySequence(keyQt).toString().length() == 1) + return false; - switch(keyQt) { - case Qt::Key_Return: - case Qt::Key_Space: - case Qt::Key_Backspace: - case Qt::Key_Escape: - case Qt::Key_Print: - case Qt::Key_ScrollLock: - case Qt::Key_Pause: - case Qt::Key_PageUp: - case Qt::Key_PageDown: - case Qt::Key_Insert: - case Qt::Key_Delete: - case Qt::Key_Home: - case Qt::Key_End: - case Qt::Key_Up: - case Qt::Key_Down: - case Qt::Key_Left: - case Qt::Key_Right: - return true; + switch (keyQt) { + case Qt::Key_Return: + case Qt::Key_Space: + case Qt::Key_Tab: + case Qt::Key_Backtab: //does this ever happen? + case Qt::Key_Backspace: + case Qt::Key_Delete: + return false; + default: + return true; + } +} - default: - return false; - } + +bool KeySequenceWidget::isShiftAsModifierAllowed(int keyQt) const +{ + // Shift only works as a modifier with certain keys. It's not possible + // to enter the SHIFT+5 key sequence for me because this is handled as + // '%' by qt on my keyboard. + // The working keys are all hardcoded here :-( + if (keyQt >= Qt::Key_F1 && keyQt <= Qt::Key_F35) + return true; + + if (QChar(keyQt).isLetter()) + return true; + + switch (keyQt) { + case Qt::Key_Return: + case Qt::Key_Space: + case Qt::Key_Backspace: + case Qt::Key_Escape: + case Qt::Key_Print: + case Qt::Key_ScrollLock: + case Qt::Key_Pause: + case Qt::Key_PageUp: + case Qt::Key_PageDown: + case Qt::Key_Insert: + case Qt::Key_Delete: + case Qt::Key_Home: + case Qt::Key_End: + case Qt::Key_Up: + case Qt::Key_Down: + case Qt::Key_Left: + case Qt::Key_Right: + return true; + + default: + return false; + } } -void KeySequenceWidget::updateShortcutDisplay() { - QString s = _keySequence.toString(QKeySequence::NativeText); - s.replace('&', QLatin1String("&&")); - if(_isRecording) { - if(_modifierKeys) { +void KeySequenceWidget::updateShortcutDisplay() +{ + QString s = _keySequence.toString(QKeySequence::NativeText); + s.replace('&', QLatin1String("&&")); + + if (_isRecording) { + if (_modifierKeys) { #ifdef Q_WS_MAC - if(_modifierKeys & Qt::META) s += QChar(kControlUnicode); - if(_modifierKeys & Qt::ALT) s += QChar(kOptionUnicode); - if(_modifierKeys & Qt::SHIFT) s += QChar(kShiftUnicode); - if(_modifierKeys & Qt::CTRL) s += QChar(kCommandUnicode); + if (_modifierKeys & Qt::META) s += QChar(kControlUnicode); + if (_modifierKeys & Qt::ALT) s += QChar(kOptionUnicode); + if (_modifierKeys & Qt::SHIFT) s += QChar(kShiftUnicode); + if (_modifierKeys & Qt::CTRL) s += QChar(kCommandUnicode); #else - if(_modifierKeys & Qt::META) s += tr("Meta", "Meta key") + '+'; - if(_modifierKeys & Qt::CTRL) s += tr("Ctrl", "Ctrl key") + '+'; - if(_modifierKeys & Qt::ALT) s += tr("Alt", "Alt key") + '+'; - if(_modifierKeys & Qt::SHIFT) s += tr("Shift", "Shift key") + '+'; + if (_modifierKeys & Qt::META) s += tr("Meta", "Meta key") + '+'; + if (_modifierKeys & Qt::CTRL) s += tr("Ctrl", "Ctrl key") + '+'; + if (_modifierKeys & Qt::ALT) s += tr("Alt", "Alt key") + '+'; + if (_modifierKeys & Qt::SHIFT) s += tr("Shift", "Shift key") + '+'; #endif - } else { - s = tr("Input", "What the user inputs now will be taken as the new shortcut"); + } + else { + s = tr("Input", "What the user inputs now will be taken as the new shortcut"); + } + // make it clear that input is still going on + s.append(" ..."); } - // make it clear that input is still going on - s.append(" ..."); - } - if(s.isEmpty()) { - s = tr("None", "No shortcut defined"); - } + if (s.isEmpty()) { + s = tr("None", "No shortcut defined"); + } - s.prepend(' '); - s.append(' '); - _keyButton->setText(s); + s.prepend(' '); + s.append(' '); + _keyButton->setText(s); } -void KeySequenceWidget::startRecording() { - _modifierKeys = 0; - _oldKeySequence = _keySequence; - _keySequence = QKeySequence(); - _conflictingIndex = QModelIndex(); - _isRecording = true; - _keyButton->grabKeyboard(); - if(!QWidget::keyboardGrabber()) { - qWarning() << "Failed to grab the keyboard! Most likely qt's nograb option is active"; - } +void KeySequenceWidget::startRecording() +{ + _modifierKeys = 0; + _oldKeySequence = _keySequence; + _keySequence = QKeySequence(); + _conflictingIndex = QModelIndex(); + _isRecording = true; + _keyButton->grabKeyboard(); + + if (!QWidget::keyboardGrabber()) { + qWarning() << "Failed to grab the keyboard! Most likely qt's nograb option is active"; + } - _keyButton->setDown(true); - updateShortcutDisplay(); + _keyButton->setDown(true); + updateShortcutDisplay(); } -void KeySequenceWidget::doneRecording() { - bool wasRecording = _isRecording; - _isRecording = false; - _keyButton->releaseKeyboard(); - _keyButton->setDown(false); +void KeySequenceWidget::doneRecording() +{ + bool wasRecording = _isRecording; + _isRecording = false; + _keyButton->releaseKeyboard(); + _keyButton->setDown(false); + + if (!wasRecording || _keySequence == _oldKeySequence) { + // The sequence hasn't changed + updateShortcutDisplay(); + return; + } - if(!wasRecording || _keySequence == _oldKeySequence) { - // The sequence hasn't changed + if (!isKeySequenceAvailable(_keySequence)) { + _keySequence = _oldKeySequence; + } + else if (wasRecording) { + emit keySequenceChanged(_keySequence, _conflictingIndex); + } updateShortcutDisplay(); - return; - } - - if(!isKeySequenceAvailable(_keySequence)) { - _keySequence = _oldKeySequence; - } else if(wasRecording) { - emit keySequenceChanged(_keySequence, _conflictingIndex); - } - updateShortcutDisplay(); } -void KeySequenceWidget::cancelRecording() { - _keySequence = _oldKeySequence; - doneRecording(); + +void KeySequenceWidget::cancelRecording() +{ + _keySequence = _oldKeySequence; + doneRecording(); } -void KeySequenceWidget::setKeySequence(const QKeySequence &seq) { - // oldKeySequence holds the key sequence before recording started, if setKeySequence() - // is called while not recording then set oldKeySequence to the existing sequence so - // that the keySequenceChanged() signal is emitted if the new and previous key - // sequences are different - if(!isRecording()) - _oldKeySequence = _keySequence; - _keySequence = seq; - _clearButton->setVisible(!_keySequence.isEmpty()); - doneRecording(); +void KeySequenceWidget::setKeySequence(const QKeySequence &seq) +{ + // oldKeySequence holds the key sequence before recording started, if setKeySequence() + // is called while not recording then set oldKeySequence to the existing sequence so + // that the keySequenceChanged() signal is emitted if the new and previous key + // sequences are different + if (!isRecording()) + _oldKeySequence = _keySequence; + + _keySequence = seq; + _clearButton->setVisible(!_keySequence.isEmpty()); + doneRecording(); } -void KeySequenceWidget::clear() { - setKeySequence(QKeySequence()); - // setKeySequence() won't emit a signal when we're not recording - emit keySequenceChanged(QKeySequence()); -} -bool KeySequenceWidget::isKeySequenceAvailable(const QKeySequence &seq) { - if(seq.isEmpty()) - return true; +void KeySequenceWidget::clear() +{ + setKeySequence(QKeySequence()); + // setKeySequence() won't emit a signal when we're not recording + emit keySequenceChanged(QKeySequence()); +} - // We need to access the root model, not the filtered one - for(int cat = 0; cat < _shortcutsModel->rowCount(); cat++) { - QModelIndex catIdx = _shortcutsModel->index(cat, 0); - for(int r = 0; r < _shortcutsModel->rowCount(catIdx); r++) { - QModelIndex actIdx = _shortcutsModel->index(r, 0, catIdx); - Q_ASSERT(actIdx.isValid()); - if(actIdx.data(ShortcutsModel::ActiveShortcutRole).value() != seq) - continue; - - if(!actIdx.data(ShortcutsModel::IsConfigurableRole).toBool()) { - QMessageBox::warning(this, tr("Shortcut Conflict"), - tr("The \"%1\" shortcut is already in use, and cannot be configured.\nPlease choose another one.").arg(seq.toString(QKeySequence::NativeText)), - QMessageBox::Ok); - return false; - } - - QMessageBox box(QMessageBox::Warning, tr("Shortcut Conflict"), - (tr("The \"%1\" shortcut is ambiguous with the shortcut for the following action:") - + "
  • %2

" - + tr("Do you want to reassign this shortcut to the selected action?") - ).arg(seq.toString(QKeySequence::NativeText), actIdx.data().toString()), - QMessageBox::Cancel, this); - box.addButton(tr("Reassign"), QMessageBox::AcceptRole); - if(box.exec() == QMessageBox::Cancel) - return false; - _conflictingIndex = actIdx; - return true; +bool KeySequenceWidget::isKeySequenceAvailable(const QKeySequence &seq) +{ + if (seq.isEmpty()) + return true; + + // We need to access the root model, not the filtered one + for (int cat = 0; cat < _shortcutsModel->rowCount(); cat++) { + QModelIndex catIdx = _shortcutsModel->index(cat, 0); + for (int r = 0; r < _shortcutsModel->rowCount(catIdx); r++) { + QModelIndex actIdx = _shortcutsModel->index(r, 0, catIdx); + Q_ASSERT(actIdx.isValid()); + if (actIdx.data(ShortcutsModel::ActiveShortcutRole).value() != seq) + continue; + + if (!actIdx.data(ShortcutsModel::IsConfigurableRole).toBool()) { + QMessageBox::warning(this, tr("Shortcut Conflict"), + tr("The \"%1\" shortcut is already in use, and cannot be configured.\nPlease choose another one.").arg(seq.toString(QKeySequence::NativeText)), + QMessageBox::Ok); + return false; + } + + QMessageBox box(QMessageBox::Warning, tr("Shortcut Conflict"), + (tr("The \"%1\" shortcut is ambiguous with the shortcut for the following action:") + + "
  • %2

" + + tr("Do you want to reassign this shortcut to the selected action?") + ).arg(seq.toString(QKeySequence::NativeText), actIdx.data().toString()), + QMessageBox::Cancel, this); + box.addButton(tr("Reassign"), QMessageBox::AcceptRole); + if (box.exec() == QMessageBox::Cancel) + return false; + + _conflictingIndex = actIdx; + return true; + } } - } - return true; + return true; } diff --git a/src/qtui/settingspages/keysequencewidget.h b/src/qtui/settingspages/keysequencewidget.h index 82d14dce..f0200e10 100644 --- a/src/qtui/settingspages/keysequencewidget.h +++ b/src/qtui/settingspages/keysequencewidget.h @@ -40,68 +40,71 @@ class ActionCollection; class KeySequenceButton; class QToolButton; -class KeySequenceWidget : public QWidget { - Q_OBJECT +class KeySequenceWidget : public QWidget +{ + Q_OBJECT public: - KeySequenceWidget(QWidget *parent = 0); + KeySequenceWidget(QWidget *parent = 0); - void setModel(ShortcutsModel *model); + void setModel(ShortcutsModel *model); public slots: - void setKeySequence(const QKeySequence &seq); + void setKeySequence(const QKeySequence &seq); signals: - /** - * This signal is emitted when the current key sequence has changed by user input - * \param seq The key sequence the user has chosen - * \param conflicting The index of an action that needs to have its shortcut removed. The user has already been - * asked to agree (if he declines, this signal won't be emitted at all). - */ - void keySequenceChanged(const QKeySequence &seq, const QModelIndex &conflicting = QModelIndex()); + /** + * This signal is emitted when the current key sequence has changed by user input + * \param seq The key sequence the user has chosen + * \param conflicting The index of an action that needs to have its shortcut removed. The user has already been + * asked to agree (if he declines, this signal won't be emitted at all). + */ + void keySequenceChanged(const QKeySequence &seq, const QModelIndex &conflicting = QModelIndex()); - void clicked(); + void clicked(); private slots: - void updateShortcutDisplay(); - void startRecording(); - void cancelRecording(); - void clear(); + void updateShortcutDisplay(); + void startRecording(); + void cancelRecording(); + void clear(); private: - inline bool isRecording() const { return _isRecording; } - void doneRecording(); + inline bool isRecording() const { return _isRecording; } + void doneRecording(); - bool isOkWhenModifierless(int keyQt) const; - bool isShiftAsModifierAllowed(int keyQt) const; - bool isKeySequenceAvailable(const QKeySequence &seq); + bool isOkWhenModifierless(int keyQt) const; + bool isShiftAsModifierAllowed(int keyQt) const; + bool isKeySequenceAvailable(const QKeySequence &seq); - ShortcutsModel *_shortcutsModel; - bool _isRecording; - QKeySequence _keySequence, _oldKeySequence; - uint _modifierKeys; - QModelIndex _conflictingIndex; + ShortcutsModel *_shortcutsModel; + bool _isRecording; + QKeySequence _keySequence, _oldKeySequence; + uint _modifierKeys; + QModelIndex _conflictingIndex; - KeySequenceButton *_keyButton; - QToolButton *_clearButton; + KeySequenceButton *_keyButton; + QToolButton *_clearButton; - friend class KeySequenceButton; + friend class KeySequenceButton; }; /*****************************************************************************/ -class KeySequenceButton : public QPushButton { - Q_OBJECT +class KeySequenceButton : public QPushButton +{ + Q_OBJECT public: - explicit KeySequenceButton(KeySequenceWidget *d, QWidget *parent = 0); + explicit KeySequenceButton(KeySequenceWidget *d, QWidget *parent = 0); protected: - virtual bool event(QEvent *event); - virtual void keyPressEvent(QKeyEvent *event); - virtual void keyReleaseEvent(QKeyEvent *event); + virtual bool event(QEvent *event); + virtual void keyPressEvent(QKeyEvent *event); + virtual void keyReleaseEvent(QKeyEvent *event); private: - KeySequenceWidget *d; + KeySequenceWidget *d; }; + #endif // KEYSEQUENCEWIDGET_H diff --git a/src/qtui/settingspages/networkssettingspage.cpp b/src/qtui/settingspages/networkssettingspage.cpp index 0f252e32..6542b7f2 100644 --- a/src/qtui/settingspages/networkssettingspage.cpp +++ b/src/qtui/settingspages/networkssettingspage.cpp @@ -34,539 +34,602 @@ #include "settingspages/identitiessettingspage.h" NetworksSettingsPage::NetworksSettingsPage(QWidget *parent) -: SettingsPage(tr("IRC"), tr("Networks"), parent) { - ui.setupUi(this); - - // hide SASL options for older cores - if(!(Client::coreFeatures() & Quassel::SaslAuthentication)) - ui.sasl->hide(); - - // set up icons - ui.renameNetwork->setIcon(SmallIcon("edit-rename")); - ui.addNetwork->setIcon(SmallIcon("list-add")); - ui.deleteNetwork->setIcon(SmallIcon("edit-delete")); - ui.addServer->setIcon(SmallIcon("list-add")); - ui.deleteServer->setIcon(SmallIcon("edit-delete")); - ui.editServer->setIcon(SmallIcon("configure")); - ui.upServer->setIcon(SmallIcon("go-up")); - ui.downServer->setIcon(SmallIcon("go-down")); - ui.editIdentities->setIcon(SmallIcon("configure")); - - _ignoreWidgetChanges = false; - - connectedIcon = SmallIcon("network-connect"); - connectingIcon = SmallIcon("network-wired"); // FIXME network-connecting - disconnectedIcon = SmallIcon("network-disconnect"); - - foreach(int mib, QTextCodec::availableMibs()) { - QByteArray codec = QTextCodec::codecForMib(mib)->name(); - ui.sendEncoding->addItem(codec); - ui.recvEncoding->addItem(codec); - ui.serverEncoding->addItem(codec); - } - ui.sendEncoding->model()->sort(0); - ui.recvEncoding->model()->sort(0); - ui.serverEncoding->model()->sort(0); - currentId = 0; - setEnabled(Client::isConnected()); // need a core connection! - setWidgetStates(); - connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), this, SLOT(coreConnectionStateChanged(bool))); - connect(Client::instance(), SIGNAL(networkCreated(NetworkId)), this, SLOT(clientNetworkAdded(NetworkId))); - connect(Client::instance(), SIGNAL(networkRemoved(NetworkId)), this, SLOT(clientNetworkRemoved(NetworkId))); - connect(Client::instance(), SIGNAL(identityCreated(IdentityId)), this, SLOT(clientIdentityAdded(IdentityId))); - connect(Client::instance(), SIGNAL(identityRemoved(IdentityId)), this, SLOT(clientIdentityRemoved(IdentityId))); - - connect(ui.identityList, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); - //connect(ui.randomServer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.performEdit, SIGNAL(textChanged()), this, SLOT(widgetHasChanged())); - connect(ui.autoIdentify, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.autoIdentifyService, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged())); - connect(ui.autoIdentifyPassword, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged())); - connect(ui.sasl, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.saslAccount, SIGNAL(textEdited(QString)), this, SLOT(widgetHasChanged())); - connect(ui.saslPassword, SIGNAL(textEdited(QString)), this, SLOT(widgetHasChanged())); - connect(ui.useCustomEncodings, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.sendEncoding, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); - connect(ui.recvEncoding, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); - connect(ui.serverEncoding, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); - connect(ui.autoReconnect, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.reconnectInterval, SIGNAL(valueChanged(int)), this, SLOT(widgetHasChanged())); - connect(ui.reconnectRetries, SIGNAL(valueChanged(int)), this, SLOT(widgetHasChanged())); - connect(ui.unlimitedRetries, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.rejoinOnReconnect, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - //connect(ui., SIGNAL(), this, SLOT(widgetHasChanged())); - //connect(ui., SIGNAL(), this, SLOT(widgetHasChanged())); - - foreach(IdentityId id, Client::identityIds()) { - clientIdentityAdded(id); - } -} - -void NetworksSettingsPage::save() { - setEnabled(false); - if(currentId != 0) saveToNetworkInfo(networkInfos[currentId]); - - QList toCreate, toUpdate; - QList toRemove; - QHash::iterator i = networkInfos.begin(); - while(i != networkInfos.end()) { - NetworkId id = (*i).networkId; - if(id < 0) { - toCreate.append(*i); - //if(id == currentId) currentId = 0; - //QList items = ui.networkList->findItems((*i).networkName, Qt::MatchExactly); - //if(items.count()) { - // Q_ASSERT(items[0]->data(Qt::UserRole).value() == id); - // delete items[0]; - //} - //i = networkInfos.erase(i); - ++i; - } else { - if((*i) != Client::network((*i).networkId)->networkInfo()) { - toUpdate.append(*i); - } - ++i; - } - } - foreach(NetworkId id, Client::networkIds()) { - if(!networkInfos.contains(id)) toRemove.append(id); - } - SaveNetworksDlg dlg(toCreate, toUpdate, toRemove, this); - int ret = dlg.exec(); - if(ret == QDialog::Rejected) { - // canceled -> reload everything to be safe - load(); - } - setChangedState(false); - setEnabled(true); -} - -void NetworksSettingsPage::load() { - reset(); - foreach(NetworkId netid, Client::networkIds()) { - clientNetworkAdded(netid); - } - ui.networkList->setCurrentRow(0); - setChangedState(false); -} - -void NetworksSettingsPage::reset() { - currentId = 0; - ui.networkList->clear(); - networkInfos.clear(); - -} - -bool NetworksSettingsPage::aboutToSave() { - if(currentId != 0) saveToNetworkInfo(networkInfos[currentId]); - QList errors; - foreach(NetworkInfo info, networkInfos.values()) { - if(!info.serverList.count()) errors.append(1); - } - if(!errors.count()) return true; - QString error(tr("The following problems need to be corrected before your changes can be applied:
    ")); - if(errors.contains(1)) error += tr("
  • All networks need at least one server defined
  • "); - error += tr("
"); - QMessageBox::warning(this, tr("Invalid Network Settings"), error); - return false; -} - -void NetworksSettingsPage::widgetHasChanged() { - if(_ignoreWidgetChanges) return; - bool changed = testHasChanged(); - if(changed != hasChanged()) setChangedState(changed); -} - -bool NetworksSettingsPage::testHasChanged() { - if(currentId != 0) { - saveToNetworkInfo(networkInfos[currentId]); - } - if(Client::networkIds().count() != networkInfos.count()) return true; - foreach(NetworkId id, networkInfos.keys()) { - if(id < 0) return true; - if(Client::network(id)->networkInfo() != networkInfos[id]) return true; - } - return false; -} - -void NetworksSettingsPage::setWidgetStates() { - // network list - if(ui.networkList->selectedItems().count()) { - ui.detailsBox->setEnabled(true); - ui.renameNetwork->setEnabled(true); - ui.deleteNetwork->setEnabled(true); - - /* button disabled for now - NetworkId id = ui.networkList->selectedItems()[0]->data(Qt::UserRole).value(); - const Network *net = id > 0 ? Client::network(id) : 0; - ui.connectNow->setEnabled(net); - // && (Client::network(id)->connectionState() == Network::Initialized - // || Client::network(id)->connectionState() == Network::Disconnected)); - if(net) { - if(net->connectionState() == Network::Disconnected) { - ui.connectNow->setIcon(connectedIcon); - ui.connectNow->setText(tr("Connect")); - } else { - ui.connectNow->setIcon(disconnectedIcon); - ui.connectNow->setText(tr("Disconnect")); - } - } else { - ui.connectNow->setIcon(QIcon()); - ui.connectNow->setText(tr("Apply first!")); - } */ - } else { - ui.renameNetwork->setEnabled(false); - ui.deleteNetwork->setEnabled(false); - //ui.connectNow->setEnabled(false); - ui.detailsBox->setEnabled(false); - } - // network details - if(ui.serverList->selectedItems().count()) { - ui.editServer->setEnabled(true); - ui.deleteServer->setEnabled(true); - ui.upServer->setEnabled(ui.serverList->currentRow() > 0); - ui.downServer->setEnabled(ui.serverList->currentRow() < ui.serverList->count() - 1); - } else { - ui.editServer->setEnabled(false); - ui.deleteServer->setEnabled(false); - ui.upServer->setEnabled(false); - ui.downServer->setEnabled(false); - } -} - -void NetworksSettingsPage::setItemState(NetworkId id, QListWidgetItem *item) { - if(!item && !(item = networkItem(id))) return; - const Network *net = Client::network(id); - if(!net || net->isInitialized()) item->setFlags(item->flags() | Qt::ItemIsEnabled); - else item->setFlags(item->flags() & ~Qt::ItemIsEnabled); - if(net && net->connectionState() == Network::Initialized) { - item->setIcon(connectedIcon); - } else if(net && net->connectionState() != Network::Disconnected) { - item->setIcon(connectingIcon); - } else { - item->setIcon(disconnectedIcon); - } - if(net) { - bool select = false; - // check if we already have another net of this name in the list, and replace it - QList items = ui.networkList->findItems(net->networkName(), Qt::MatchExactly); - if(items.count()) { - foreach(QListWidgetItem *i, items) { - NetworkId oldid = i->data(Qt::UserRole).value(); - if(oldid > 0) continue; // only locally created nets should be replaced - if(oldid == currentId) { - select = true; - currentId = 0; - ui.networkList->clearSelection(); + : SettingsPage(tr("IRC"), tr("Networks"), parent) +{ + ui.setupUi(this); + + // hide SASL options for older cores + if (!(Client::coreFeatures() & Quassel::SaslAuthentication)) + ui.sasl->hide(); + + // set up icons + ui.renameNetwork->setIcon(SmallIcon("edit-rename")); + ui.addNetwork->setIcon(SmallIcon("list-add")); + ui.deleteNetwork->setIcon(SmallIcon("edit-delete")); + ui.addServer->setIcon(SmallIcon("list-add")); + ui.deleteServer->setIcon(SmallIcon("edit-delete")); + ui.editServer->setIcon(SmallIcon("configure")); + ui.upServer->setIcon(SmallIcon("go-up")); + ui.downServer->setIcon(SmallIcon("go-down")); + ui.editIdentities->setIcon(SmallIcon("configure")); + + _ignoreWidgetChanges = false; + + connectedIcon = SmallIcon("network-connect"); + connectingIcon = SmallIcon("network-wired"); // FIXME network-connecting + disconnectedIcon = SmallIcon("network-disconnect"); + + foreach(int mib, QTextCodec::availableMibs()) { + QByteArray codec = QTextCodec::codecForMib(mib)->name(); + ui.sendEncoding->addItem(codec); + ui.recvEncoding->addItem(codec); + ui.serverEncoding->addItem(codec); + } + ui.sendEncoding->model()->sort(0); + ui.recvEncoding->model()->sort(0); + ui.serverEncoding->model()->sort(0); + currentId = 0; + setEnabled(Client::isConnected()); // need a core connection! + setWidgetStates(); + connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), this, SLOT(coreConnectionStateChanged(bool))); + connect(Client::instance(), SIGNAL(networkCreated(NetworkId)), this, SLOT(clientNetworkAdded(NetworkId))); + connect(Client::instance(), SIGNAL(networkRemoved(NetworkId)), this, SLOT(clientNetworkRemoved(NetworkId))); + connect(Client::instance(), SIGNAL(identityCreated(IdentityId)), this, SLOT(clientIdentityAdded(IdentityId))); + connect(Client::instance(), SIGNAL(identityRemoved(IdentityId)), this, SLOT(clientIdentityRemoved(IdentityId))); + + connect(ui.identityList, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); + //connect(ui.randomServer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.performEdit, SIGNAL(textChanged()), this, SLOT(widgetHasChanged())); + connect(ui.autoIdentify, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.autoIdentifyService, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged())); + connect(ui.autoIdentifyPassword, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged())); + connect(ui.sasl, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.saslAccount, SIGNAL(textEdited(QString)), this, SLOT(widgetHasChanged())); + connect(ui.saslPassword, SIGNAL(textEdited(QString)), this, SLOT(widgetHasChanged())); + connect(ui.useCustomEncodings, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.sendEncoding, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); + connect(ui.recvEncoding, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); + connect(ui.serverEncoding, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); + connect(ui.autoReconnect, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.reconnectInterval, SIGNAL(valueChanged(int)), this, SLOT(widgetHasChanged())); + connect(ui.reconnectRetries, SIGNAL(valueChanged(int)), this, SLOT(widgetHasChanged())); + connect(ui.unlimitedRetries, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.rejoinOnReconnect, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + //connect(ui., SIGNAL(), this, SLOT(widgetHasChanged())); + //connect(ui., SIGNAL(), this, SLOT(widgetHasChanged())); + + foreach(IdentityId id, Client::identityIds()) { + clientIdentityAdded(id); + } +} + + +void NetworksSettingsPage::save() +{ + setEnabled(false); + if (currentId != 0) saveToNetworkInfo(networkInfos[currentId]); + + QList toCreate, toUpdate; + QList toRemove; + QHash::iterator i = networkInfos.begin(); + while (i != networkInfos.end()) { + NetworkId id = (*i).networkId; + if (id < 0) { + toCreate.append(*i); + //if(id == currentId) currentId = 0; + //QList items = ui.networkList->findItems((*i).networkName, Qt::MatchExactly); + //if(items.count()) { + // Q_ASSERT(items[0]->data(Qt::UserRole).value() == id); + // delete items[0]; + //} + //i = networkInfos.erase(i); + ++i; } - int row = ui.networkList->row(i); - if(row >= 0) { - QListWidgetItem *olditem = ui.networkList->takeItem(row); - Q_ASSERT(olditem); - delete olditem; + else { + if ((*i) != Client::network((*i).networkId)->networkInfo()) { + toUpdate.append(*i); + } + ++i; } - networkInfos.remove(oldid); - break; - } - } - item->setText(net->networkName()); - if(select) item->setSelected(true); - } -} - -void NetworksSettingsPage::coreConnectionStateChanged(bool state) { - this->setEnabled(state); - if(state) { - load(); - } else { - // reset - //currentId = 0; - } -} - -void NetworksSettingsPage::clientIdentityAdded(IdentityId id) { - const Identity * identity = Client::identity(id); - connect(identity, SIGNAL(updatedRemotely()), this, SLOT(clientIdentityUpdated())); - - QString name = identity->identityName(); - for(int j = 0; j < ui.identityList->count(); j++) { - if((j>0 || ui.identityList->itemData(0).toInt() != 1) && name.localeAwareCompare(ui.identityList->itemText(j)) < 0) { - ui.identityList->insertItem(j, name, id.toInt()); - widgetHasChanged(); - return; - } - } - // append - ui.identityList->insertItem(ui.identityList->count(), name, id.toInt()); - widgetHasChanged(); -} - -void NetworksSettingsPage::clientIdentityUpdated() { - const Identity *identity = qobject_cast(sender()); - if(!identity) { - qWarning() << "NetworksSettingsPage: Invalid identity to update!"; - return; - } - int row = ui.identityList->findData(identity->id().toInt()); - if(row < 0) { - qWarning() << "NetworksSettingsPage: Invalid identity to update!"; - return; - } - if(ui.identityList->itemText(row) != identity->identityName()) { - ui.identityList->setItemText(row, identity->identityName()); - } -} - -void NetworksSettingsPage::clientIdentityRemoved(IdentityId id) { - IdentityId defaultId = defaultIdentity(); - if(currentId != 0) saveToNetworkInfo(networkInfos[currentId]); - foreach(NetworkInfo info, networkInfos.values()) { - if(info.identity == id) { - if(info.networkId == currentId) - ui.identityList->setCurrentIndex(0); - info.identity = defaultId; - networkInfos[info.networkId] = info; - if(info.networkId > 0) Client::updateNetwork(info); - } - } - ui.identityList->removeItem(ui.identityList->findData(id.toInt())); - widgetHasChanged(); -} - -QListWidgetItem *NetworksSettingsPage::networkItem(NetworkId id) const { - for(int i = 0; i < ui.networkList->count(); i++) { - QListWidgetItem *item = ui.networkList->item(i); - if(item->data(Qt::UserRole).value() == id) return item; - } - return 0; -} - -void NetworksSettingsPage::clientNetworkAdded(NetworkId id) { - insertNetwork(id); - //connect(Client::network(id), SIGNAL(updatedRemotely()), this, SLOT(clientNetworkUpdated())); - connect(Client::network(id), SIGNAL(configChanged()), this, SLOT(clientNetworkUpdated())); - - connect(Client::network(id), SIGNAL(connectionStateSet(Network::ConnectionState)), this, SLOT(networkConnectionStateChanged(Network::ConnectionState))); - connect(Client::network(id), SIGNAL(connectionError(const QString &)), this, SLOT(networkConnectionError(const QString &))); -} - -void NetworksSettingsPage::clientNetworkUpdated() { - const Network *net = qobject_cast(sender()); - if(!net) { - qWarning() << "Update request for unknown network received!"; - return; - } - networkInfos[net->networkId()] = net->networkInfo(); - setItemState(net->networkId()); - if(net->networkId() == currentId) displayNetwork(net->networkId()); - setWidgetStates(); - widgetHasChanged(); -} - -void NetworksSettingsPage::clientNetworkRemoved(NetworkId id) { - if(!networkInfos.contains(id)) return; - if(id == currentId) displayNetwork(0); - NetworkInfo info = networkInfos.take(id); - QList items = ui.networkList->findItems(info.networkName, Qt::MatchExactly); - foreach(QListWidgetItem *item, items) { - if(item->data(Qt::UserRole).value() == id) - delete ui.networkList->takeItem(ui.networkList->row(item)); - } - setWidgetStates(); - widgetHasChanged(); -} - -void NetworksSettingsPage::networkConnectionStateChanged(Network::ConnectionState state) { - Q_UNUSED(state); - const Network *net = qobject_cast(sender()); - if(!net) return; - /* - if(net->networkId() == currentId) { - ui.connectNow->setEnabled(state == Network::Initialized || state == Network::Disconnected); - } - */ - setItemState(net->networkId()); - setWidgetStates(); -} - -void NetworksSettingsPage::networkConnectionError(const QString &) { - -} - -QListWidgetItem *NetworksSettingsPage::insertNetwork(NetworkId id) { - NetworkInfo info = Client::network(id)->networkInfo(); - networkInfos[id] = info; - return insertNetwork(info); -} - -QListWidgetItem *NetworksSettingsPage::insertNetwork(const NetworkInfo &info) { - QListWidgetItem *item = 0; - QList items = ui.networkList->findItems(info.networkName, Qt::MatchExactly); - if(!items.count()) item = new QListWidgetItem(disconnectedIcon, info.networkName, ui.networkList); - else { - // we overwrite an existing net if it a) has the same name and b) has a negative ID meaning we created it locally before - // -> then we can be sure that this is the core-side replacement for the net we created - foreach(QListWidgetItem *i, items) { - NetworkId id = i->data(Qt::UserRole).value(); - if(id < 0) { item = i; break; } - } - if(!item) item = new QListWidgetItem(disconnectedIcon, info.networkName, ui.networkList); - } - item->setData(Qt::UserRole, QVariant::fromValue(info.networkId)); - setItemState(info.networkId, item); - widgetHasChanged(); - return item; -} - -void NetworksSettingsPage::displayNetwork(NetworkId id) { - _ignoreWidgetChanges = true; - if(id != 0) { - NetworkInfo info = networkInfos[id]; - ui.identityList->setCurrentIndex(ui.identityList->findData(info.identity.toInt())); - ui.serverList->clear(); - foreach(Network::Server server, info.serverList) { - QListWidgetItem *item = new QListWidgetItem(QString("%1:%2").arg(server.host).arg(server.port)); - if(server.useSsl) - item->setIcon(SmallIcon("document-encrypt")); - ui.serverList->addItem(item); - } - //setItemState(id); - //ui.randomServer->setChecked(info.useRandomServer); - ui.performEdit->setPlainText(info.perform.join("\n")); - ui.autoIdentify->setChecked(info.useAutoIdentify); - ui.autoIdentifyService->setText(info.autoIdentifyService); - ui.autoIdentifyPassword->setText(info.autoIdentifyPassword); - ui.sasl->setChecked(info.useSasl); - ui.saslAccount->setText(info.saslAccount); - ui.saslPassword->setText(info.saslPassword); - if(info.codecForEncoding.isEmpty()) { - ui.sendEncoding->setCurrentIndex(ui.sendEncoding->findText(Network::defaultCodecForEncoding())); - ui.recvEncoding->setCurrentIndex(ui.recvEncoding->findText(Network::defaultCodecForDecoding())); - ui.serverEncoding->setCurrentIndex(ui.serverEncoding->findText(Network::defaultCodecForServer())); - ui.useCustomEncodings->setChecked(false); - } else { - ui.sendEncoding->setCurrentIndex(ui.sendEncoding->findText(info.codecForEncoding)); - ui.recvEncoding->setCurrentIndex(ui.recvEncoding->findText(info.codecForDecoding)); - ui.serverEncoding->setCurrentIndex(ui.serverEncoding->findText(info.codecForServer)); - ui.useCustomEncodings->setChecked(true); - } - ui.autoReconnect->setChecked(info.useAutoReconnect); - ui.reconnectInterval->setValue(info.autoReconnectInterval); - ui.reconnectRetries->setValue(info.autoReconnectRetries); - ui.unlimitedRetries->setChecked(info.unlimitedReconnectRetries); - ui.rejoinOnReconnect->setChecked(info.rejoinChannels); - } else { - // just clear widgets - ui.identityList->setCurrentIndex(-1); - ui.serverList->clear(); - ui.performEdit->clear(); - ui.autoIdentifyService->clear(); - ui.autoIdentifyPassword->clear(); - ui.saslAccount->clear(); - ui.saslPassword->clear(); - setWidgetStates(); - } - _ignoreWidgetChanges = false; - currentId = id; -} - -void NetworksSettingsPage::saveToNetworkInfo(NetworkInfo &info) { - info.identity = ui.identityList->itemData(ui.identityList->currentIndex()).toInt(); - //info.useRandomServer = ui.randomServer->isChecked(); - info.perform = ui.performEdit->toPlainText().split("\n"); - info.useAutoIdentify = ui.autoIdentify->isChecked(); - info.autoIdentifyService = ui.autoIdentifyService->text(); - info.autoIdentifyPassword = ui.autoIdentifyPassword->text(); - info.useSasl = ui.sasl->isChecked(); - info.saslAccount = ui.saslAccount->text(); - info.saslPassword = ui.saslPassword->text(); - if(!ui.useCustomEncodings->isChecked()) { - info.codecForEncoding.clear(); - info.codecForDecoding.clear(); - info.codecForServer.clear(); - } else { - info.codecForEncoding = ui.sendEncoding->currentText().toLatin1(); - info.codecForDecoding = ui.recvEncoding->currentText().toLatin1(); - info.codecForServer = ui.serverEncoding->currentText().toLatin1(); - } - info.useAutoReconnect = ui.autoReconnect->isChecked(); - info.autoReconnectInterval = ui.reconnectInterval->value(); - info.autoReconnectRetries = ui.reconnectRetries->value(); - info.unlimitedReconnectRetries = ui.unlimitedRetries->isChecked(); - info.rejoinChannels = ui.rejoinOnReconnect->isChecked(); + } + foreach(NetworkId id, Client::networkIds()) { + if (!networkInfos.contains(id)) toRemove.append(id); + } + SaveNetworksDlg dlg(toCreate, toUpdate, toRemove, this); + int ret = dlg.exec(); + if (ret == QDialog::Rejected) { + // canceled -> reload everything to be safe + load(); + } + setChangedState(false); + setEnabled(true); } -/*** Network list ***/ -void NetworksSettingsPage::on_networkList_itemSelectionChanged() { - if(currentId != 0) { - saveToNetworkInfo(networkInfos[currentId]); - } - if(ui.networkList->selectedItems().count()) { - NetworkId id = ui.networkList->selectedItems()[0]->data(Qt::UserRole).value(); - currentId = id; - displayNetwork(id); - ui.serverList->setCurrentRow(0); - } else { + +void NetworksSettingsPage::load() +{ + reset(); + foreach(NetworkId netid, Client::networkIds()) { + clientNetworkAdded(netid); + } + ui.networkList->setCurrentRow(0); + setChangedState(false); +} + + +void NetworksSettingsPage::reset() +{ currentId = 0; - } - setWidgetStates(); -} - -void NetworksSettingsPage::on_addNetwork_clicked() { - QStringList existing; - for(int i = 0; i < ui.networkList->count(); i++) existing << ui.networkList->item(i)->text(); - NetworkAddDlg dlg(existing, this); - if(dlg.exec() == QDialog::Accepted) { - NetworkInfo info = dlg.networkInfo(); - if(info.networkName.isEmpty()) - return; // sanity check - - NetworkId id; - for(id = 1; id <= networkInfos.count(); id++) { - widgetHasChanged(); - if(!networkInfos.keys().contains(-id.toInt())) break; - } - id = -id.toInt(); - info.networkId = id; - info.identity = defaultIdentity(); - networkInfos[id] = info; - QListWidgetItem *item = insertNetwork(info); - ui.networkList->setCurrentItem(item); + ui.networkList->clear(); + networkInfos.clear(); +} + + +bool NetworksSettingsPage::aboutToSave() +{ + if (currentId != 0) saveToNetworkInfo(networkInfos[currentId]); + QList errors; + foreach(NetworkInfo info, networkInfos.values()) { + if (!info.serverList.count()) errors.append(1); + } + if (!errors.count()) return true; + QString error(tr("The following problems need to be corrected before your changes can be applied:
    ")); + if (errors.contains(1)) error += tr("
  • All networks need at least one server defined
  • "); + error += tr("
"); + QMessageBox::warning(this, tr("Invalid Network Settings"), error); + return false; +} + + +void NetworksSettingsPage::widgetHasChanged() +{ + if (_ignoreWidgetChanges) return; + bool changed = testHasChanged(); + if (changed != hasChanged()) setChangedState(changed); +} + + +bool NetworksSettingsPage::testHasChanged() +{ + if (currentId != 0) { + saveToNetworkInfo(networkInfos[currentId]); + } + if (Client::networkIds().count() != networkInfos.count()) return true; + foreach(NetworkId id, networkInfos.keys()) { + if (id < 0) return true; + if (Client::network(id)->networkInfo() != networkInfos[id]) return true; + } + return false; +} + + +void NetworksSettingsPage::setWidgetStates() +{ + // network list + if (ui.networkList->selectedItems().count()) { + ui.detailsBox->setEnabled(true); + ui.renameNetwork->setEnabled(true); + ui.deleteNetwork->setEnabled(true); + + /* button disabled for now + NetworkId id = ui.networkList->selectedItems()[0]->data(Qt::UserRole).value(); + const Network *net = id > 0 ? Client::network(id) : 0; + ui.connectNow->setEnabled(net); + // && (Client::network(id)->connectionState() == Network::Initialized + // || Client::network(id)->connectionState() == Network::Disconnected)); + if(net) { + if(net->connectionState() == Network::Disconnected) { + ui.connectNow->setIcon(connectedIcon); + ui.connectNow->setText(tr("Connect")); + } else { + ui.connectNow->setIcon(disconnectedIcon); + ui.connectNow->setText(tr("Disconnect")); + } + } else { + ui.connectNow->setIcon(QIcon()); + ui.connectNow->setText(tr("Apply first!")); + } */ + } + else { + ui.renameNetwork->setEnabled(false); + ui.deleteNetwork->setEnabled(false); + //ui.connectNow->setEnabled(false); + ui.detailsBox->setEnabled(false); + } + // network details + if (ui.serverList->selectedItems().count()) { + ui.editServer->setEnabled(true); + ui.deleteServer->setEnabled(true); + ui.upServer->setEnabled(ui.serverList->currentRow() > 0); + ui.downServer->setEnabled(ui.serverList->currentRow() < ui.serverList->count() - 1); + } + else { + ui.editServer->setEnabled(false); + ui.deleteServer->setEnabled(false); + ui.upServer->setEnabled(false); + ui.downServer->setEnabled(false); + } +} + + +void NetworksSettingsPage::setItemState(NetworkId id, QListWidgetItem *item) +{ + if (!item && !(item = networkItem(id))) return; + const Network *net = Client::network(id); + if (!net || net->isInitialized()) item->setFlags(item->flags() | Qt::ItemIsEnabled); + else item->setFlags(item->flags() & ~Qt::ItemIsEnabled); + if (net && net->connectionState() == Network::Initialized) { + item->setIcon(connectedIcon); + } + else if (net && net->connectionState() != Network::Disconnected) { + item->setIcon(connectingIcon); + } + else { + item->setIcon(disconnectedIcon); + } + if (net) { + bool select = false; + // check if we already have another net of this name in the list, and replace it + QList items = ui.networkList->findItems(net->networkName(), Qt::MatchExactly); + if (items.count()) { + foreach(QListWidgetItem *i, items) { + NetworkId oldid = i->data(Qt::UserRole).value(); + if (oldid > 0) continue; // only locally created nets should be replaced + if (oldid == currentId) { + select = true; + currentId = 0; + ui.networkList->clearSelection(); + } + int row = ui.networkList->row(i); + if (row >= 0) { + QListWidgetItem *olditem = ui.networkList->takeItem(row); + Q_ASSERT(olditem); + delete olditem; + } + networkInfos.remove(oldid); + break; + } + } + item->setText(net->networkName()); + if (select) item->setSelected(true); + } +} + + +void NetworksSettingsPage::coreConnectionStateChanged(bool state) +{ + this->setEnabled(state); + if (state) { + load(); + } + else { + // reset + //currentId = 0; + } +} + + +void NetworksSettingsPage::clientIdentityAdded(IdentityId id) +{ + const Identity *identity = Client::identity(id); + connect(identity, SIGNAL(updatedRemotely()), this, SLOT(clientIdentityUpdated())); + + QString name = identity->identityName(); + for (int j = 0; j < ui.identityList->count(); j++) { + if ((j > 0 || ui.identityList->itemData(0).toInt() != 1) && name.localeAwareCompare(ui.identityList->itemText(j)) < 0) { + ui.identityList->insertItem(j, name, id.toInt()); + widgetHasChanged(); + return; + } + } + // append + ui.identityList->insertItem(ui.identityList->count(), name, id.toInt()); + widgetHasChanged(); +} + + +void NetworksSettingsPage::clientIdentityUpdated() +{ + const Identity *identity = qobject_cast(sender()); + if (!identity) { + qWarning() << "NetworksSettingsPage: Invalid identity to update!"; + return; + } + int row = ui.identityList->findData(identity->id().toInt()); + if (row < 0) { + qWarning() << "NetworksSettingsPage: Invalid identity to update!"; + return; + } + if (ui.identityList->itemText(row) != identity->identityName()) { + ui.identityList->setItemText(row, identity->identityName()); + } +} + + +void NetworksSettingsPage::clientIdentityRemoved(IdentityId id) +{ + IdentityId defaultId = defaultIdentity(); + if (currentId != 0) saveToNetworkInfo(networkInfos[currentId]); + foreach(NetworkInfo info, networkInfos.values()) { + if (info.identity == id) { + if (info.networkId == currentId) + ui.identityList->setCurrentIndex(0); + info.identity = defaultId; + networkInfos[info.networkId] = info; + if (info.networkId > 0) Client::updateNetwork(info); + } + } + ui.identityList->removeItem(ui.identityList->findData(id.toInt())); + widgetHasChanged(); +} + + +QListWidgetItem *NetworksSettingsPage::networkItem(NetworkId id) const +{ + for (int i = 0; i < ui.networkList->count(); i++) { + QListWidgetItem *item = ui.networkList->item(i); + if (item->data(Qt::UserRole).value() == id) return item; + } + return 0; +} + + +void NetworksSettingsPage::clientNetworkAdded(NetworkId id) +{ + insertNetwork(id); + //connect(Client::network(id), SIGNAL(updatedRemotely()), this, SLOT(clientNetworkUpdated())); + connect(Client::network(id), SIGNAL(configChanged()), this, SLOT(clientNetworkUpdated())); + + connect(Client::network(id), SIGNAL(connectionStateSet(Network::ConnectionState)), this, SLOT(networkConnectionStateChanged(Network::ConnectionState))); + connect(Client::network(id), SIGNAL(connectionError(const QString &)), this, SLOT(networkConnectionError(const QString &))); +} + + +void NetworksSettingsPage::clientNetworkUpdated() +{ + const Network *net = qobject_cast(sender()); + if (!net) { + qWarning() << "Update request for unknown network received!"; + return; + } + networkInfos[net->networkId()] = net->networkInfo(); + setItemState(net->networkId()); + if (net->networkId() == currentId) displayNetwork(net->networkId()); setWidgetStates(); - } + widgetHasChanged(); } -void NetworksSettingsPage::on_deleteNetwork_clicked() { - if(ui.networkList->selectedItems().count()) { - NetworkId netid = ui.networkList->selectedItems()[0]->data(Qt::UserRole).value(); - int ret = QMessageBox::question(this, tr("Delete Network?"), - tr("Do you really want to delete the network \"%1\" and all related settings, including the backlog?").arg(networkInfos[netid].networkName), - QMessageBox::Yes|QMessageBox::No, QMessageBox::No); - if(ret == QMessageBox::Yes) { - currentId = 0; - networkInfos.remove(netid); - delete ui.networkList->takeItem(ui.networkList->row(ui.networkList->selectedItems()[0])); - ui.networkList->setCurrentRow(qMin(ui.networkList->currentRow()+1, ui.networkList->count()-1)); - setWidgetStates(); - widgetHasChanged(); + +void NetworksSettingsPage::clientNetworkRemoved(NetworkId id) +{ + if (!networkInfos.contains(id)) return; + if (id == currentId) displayNetwork(0); + NetworkInfo info = networkInfos.take(id); + QList items = ui.networkList->findItems(info.networkName, Qt::MatchExactly); + foreach(QListWidgetItem *item, items) { + if (item->data(Qt::UserRole).value() == id) + delete ui.networkList->takeItem(ui.networkList->row(item)); } - } + setWidgetStates(); + widgetHasChanged(); } -void NetworksSettingsPage::on_renameNetwork_clicked() { - if(!ui.networkList->selectedItems().count()) return; - QString old = ui.networkList->selectedItems()[0]->text(); - QStringList existing; - for(int i = 0; i < ui.networkList->count(); i++) existing << ui.networkList->item(i)->text(); - NetworkEditDlg dlg(old, existing, this); - if(dlg.exec() == QDialog::Accepted) { - ui.networkList->selectedItems()[0]->setText(dlg.networkName()); - NetworkId netid = ui.networkList->selectedItems()[0]->data(Qt::UserRole).value(); - networkInfos[netid].networkName = dlg.networkName(); + +void NetworksSettingsPage::networkConnectionStateChanged(Network::ConnectionState state) +{ + Q_UNUSED(state); + const Network *net = qobject_cast(sender()); + if (!net) return; + /* + if(net->networkId() == currentId) { + ui.connectNow->setEnabled(state == Network::Initialized || state == Network::Disconnected); + } + */ + setItemState(net->networkId()); + setWidgetStates(); +} + + +void NetworksSettingsPage::networkConnectionError(const QString &) +{ +} + + +QListWidgetItem *NetworksSettingsPage::insertNetwork(NetworkId id) +{ + NetworkInfo info = Client::network(id)->networkInfo(); + networkInfos[id] = info; + return insertNetwork(info); +} + + +QListWidgetItem *NetworksSettingsPage::insertNetwork(const NetworkInfo &info) +{ + QListWidgetItem *item = 0; + QList items = ui.networkList->findItems(info.networkName, Qt::MatchExactly); + if (!items.count()) item = new QListWidgetItem(disconnectedIcon, info.networkName, ui.networkList); + else { + // we overwrite an existing net if it a) has the same name and b) has a negative ID meaning we created it locally before + // -> then we can be sure that this is the core-side replacement for the net we created + foreach(QListWidgetItem *i, items) { + NetworkId id = i->data(Qt::UserRole).value(); + if (id < 0) { item = i; break; } + } + if (!item) item = new QListWidgetItem(disconnectedIcon, info.networkName, ui.networkList); + } + item->setData(Qt::UserRole, QVariant::fromValue(info.networkId)); + setItemState(info.networkId, item); widgetHasChanged(); - } + return item; } + +void NetworksSettingsPage::displayNetwork(NetworkId id) +{ + _ignoreWidgetChanges = true; + if (id != 0) { + NetworkInfo info = networkInfos[id]; + ui.identityList->setCurrentIndex(ui.identityList->findData(info.identity.toInt())); + ui.serverList->clear(); + foreach(Network::Server server, info.serverList) { + QListWidgetItem *item = new QListWidgetItem(QString("%1:%2").arg(server.host).arg(server.port)); + if (server.useSsl) + item->setIcon(SmallIcon("document-encrypt")); + ui.serverList->addItem(item); + } + //setItemState(id); + //ui.randomServer->setChecked(info.useRandomServer); + ui.performEdit->setPlainText(info.perform.join("\n")); + ui.autoIdentify->setChecked(info.useAutoIdentify); + ui.autoIdentifyService->setText(info.autoIdentifyService); + ui.autoIdentifyPassword->setText(info.autoIdentifyPassword); + ui.sasl->setChecked(info.useSasl); + ui.saslAccount->setText(info.saslAccount); + ui.saslPassword->setText(info.saslPassword); + if (info.codecForEncoding.isEmpty()) { + ui.sendEncoding->setCurrentIndex(ui.sendEncoding->findText(Network::defaultCodecForEncoding())); + ui.recvEncoding->setCurrentIndex(ui.recvEncoding->findText(Network::defaultCodecForDecoding())); + ui.serverEncoding->setCurrentIndex(ui.serverEncoding->findText(Network::defaultCodecForServer())); + ui.useCustomEncodings->setChecked(false); + } + else { + ui.sendEncoding->setCurrentIndex(ui.sendEncoding->findText(info.codecForEncoding)); + ui.recvEncoding->setCurrentIndex(ui.recvEncoding->findText(info.codecForDecoding)); + ui.serverEncoding->setCurrentIndex(ui.serverEncoding->findText(info.codecForServer)); + ui.useCustomEncodings->setChecked(true); + } + ui.autoReconnect->setChecked(info.useAutoReconnect); + ui.reconnectInterval->setValue(info.autoReconnectInterval); + ui.reconnectRetries->setValue(info.autoReconnectRetries); + ui.unlimitedRetries->setChecked(info.unlimitedReconnectRetries); + ui.rejoinOnReconnect->setChecked(info.rejoinChannels); + } + else { + // just clear widgets + ui.identityList->setCurrentIndex(-1); + ui.serverList->clear(); + ui.performEdit->clear(); + ui.autoIdentifyService->clear(); + ui.autoIdentifyPassword->clear(); + ui.saslAccount->clear(); + ui.saslPassword->clear(); + setWidgetStates(); + } + _ignoreWidgetChanges = false; + currentId = id; +} + + +void NetworksSettingsPage::saveToNetworkInfo(NetworkInfo &info) +{ + info.identity = ui.identityList->itemData(ui.identityList->currentIndex()).toInt(); + //info.useRandomServer = ui.randomServer->isChecked(); + info.perform = ui.performEdit->toPlainText().split("\n"); + info.useAutoIdentify = ui.autoIdentify->isChecked(); + info.autoIdentifyService = ui.autoIdentifyService->text(); + info.autoIdentifyPassword = ui.autoIdentifyPassword->text(); + info.useSasl = ui.sasl->isChecked(); + info.saslAccount = ui.saslAccount->text(); + info.saslPassword = ui.saslPassword->text(); + if (!ui.useCustomEncodings->isChecked()) { + info.codecForEncoding.clear(); + info.codecForDecoding.clear(); + info.codecForServer.clear(); + } + else { + info.codecForEncoding = ui.sendEncoding->currentText().toLatin1(); + info.codecForDecoding = ui.recvEncoding->currentText().toLatin1(); + info.codecForServer = ui.serverEncoding->currentText().toLatin1(); + } + info.useAutoReconnect = ui.autoReconnect->isChecked(); + info.autoReconnectInterval = ui.reconnectInterval->value(); + info.autoReconnectRetries = ui.reconnectRetries->value(); + info.unlimitedReconnectRetries = ui.unlimitedRetries->isChecked(); + info.rejoinChannels = ui.rejoinOnReconnect->isChecked(); +} + + +/*** Network list ***/ + +void NetworksSettingsPage::on_networkList_itemSelectionChanged() +{ + if (currentId != 0) { + saveToNetworkInfo(networkInfos[currentId]); + } + if (ui.networkList->selectedItems().count()) { + NetworkId id = ui.networkList->selectedItems()[0]->data(Qt::UserRole).value(); + currentId = id; + displayNetwork(id); + ui.serverList->setCurrentRow(0); + } + else { + currentId = 0; + } + setWidgetStates(); +} + + +void NetworksSettingsPage::on_addNetwork_clicked() +{ + QStringList existing; + for (int i = 0; i < ui.networkList->count(); i++) existing << ui.networkList->item(i)->text(); + NetworkAddDlg dlg(existing, this); + if (dlg.exec() == QDialog::Accepted) { + NetworkInfo info = dlg.networkInfo(); + if (info.networkName.isEmpty()) + return; // sanity check + + NetworkId id; + for (id = 1; id <= networkInfos.count(); id++) { + widgetHasChanged(); + if (!networkInfos.keys().contains(-id.toInt())) break; + } + id = -id.toInt(); + info.networkId = id; + info.identity = defaultIdentity(); + networkInfos[id] = info; + QListWidgetItem *item = insertNetwork(info); + ui.networkList->setCurrentItem(item); + setWidgetStates(); + } +} + + +void NetworksSettingsPage::on_deleteNetwork_clicked() +{ + if (ui.networkList->selectedItems().count()) { + NetworkId netid = ui.networkList->selectedItems()[0]->data(Qt::UserRole).value(); + int ret = QMessageBox::question(this, tr("Delete Network?"), + tr("Do you really want to delete the network \"%1\" and all related settings, including the backlog?").arg(networkInfos[netid].networkName), + QMessageBox::Yes|QMessageBox::No, QMessageBox::No); + if (ret == QMessageBox::Yes) { + currentId = 0; + networkInfos.remove(netid); + delete ui.networkList->takeItem(ui.networkList->row(ui.networkList->selectedItems()[0])); + ui.networkList->setCurrentRow(qMin(ui.networkList->currentRow()+1, ui.networkList->count()-1)); + setWidgetStates(); + widgetHasChanged(); + } + } +} + + +void NetworksSettingsPage::on_renameNetwork_clicked() +{ + if (!ui.networkList->selectedItems().count()) return; + QString old = ui.networkList->selectedItems()[0]->text(); + QStringList existing; + for (int i = 0; i < ui.networkList->count(); i++) existing << ui.networkList->item(i)->text(); + NetworkEditDlg dlg(old, existing, this); + if (dlg.exec() == QDialog::Accepted) { + ui.networkList->selectedItems()[0]->setText(dlg.networkName()); + NetworkId netid = ui.networkList->selectedItems()[0]->data(Qt::UserRole).value(); + networkInfos[netid].networkName = dlg.networkName(); + widgetHasChanged(); + } +} + + /* void NetworksSettingsPage::on_connectNow_clicked() { if(!ui.networkList->selectedItems().count()) return; @@ -580,219 +643,257 @@ void NetworksSettingsPage::on_connectNow_clicked() { /*** Server list ***/ -void NetworksSettingsPage::on_serverList_itemSelectionChanged() { - setWidgetStates(); +void NetworksSettingsPage::on_serverList_itemSelectionChanged() +{ + setWidgetStates(); } -void NetworksSettingsPage::on_addServer_clicked() { - if(currentId == 0) return; - ServerEditDlg dlg(Network::Server(), this); - if(dlg.exec() == QDialog::Accepted) { - networkInfos[currentId].serverList.append(dlg.serverData()); + +void NetworksSettingsPage::on_addServer_clicked() +{ + if (currentId == 0) return; + ServerEditDlg dlg(Network::Server(), this); + if (dlg.exec() == QDialog::Accepted) { + networkInfos[currentId].serverList.append(dlg.serverData()); + displayNetwork(currentId); + ui.serverList->setCurrentRow(ui.serverList->count()-1); + widgetHasChanged(); + } +} + + +void NetworksSettingsPage::on_editServer_clicked() +{ + if (currentId == 0) return; + int cur = ui.serverList->currentRow(); + ServerEditDlg dlg(networkInfos[currentId].serverList[cur], this); + if (dlg.exec() == QDialog::Accepted) { + networkInfos[currentId].serverList[cur] = dlg.serverData(); + displayNetwork(currentId); + ui.serverList->setCurrentRow(cur); + widgetHasChanged(); + } +} + + +void NetworksSettingsPage::on_deleteServer_clicked() +{ + if (currentId == 0) return; + int cur = ui.serverList->currentRow(); + networkInfos[currentId].serverList.removeAt(cur); displayNetwork(currentId); - ui.serverList->setCurrentRow(ui.serverList->count()-1); + ui.serverList->setCurrentRow(qMin(cur, ui.serverList->count()-1)); widgetHasChanged(); - } } -void NetworksSettingsPage::on_editServer_clicked() { - if(currentId == 0) return; - int cur = ui.serverList->currentRow(); - ServerEditDlg dlg(networkInfos[currentId].serverList[cur], this); - if(dlg.exec() == QDialog::Accepted) { - networkInfos[currentId].serverList[cur] = dlg.serverData(); + +void NetworksSettingsPage::on_upServer_clicked() +{ + int cur = ui.serverList->currentRow(); + Network::Server server = networkInfos[currentId].serverList.takeAt(cur); + networkInfos[currentId].serverList.insert(cur-1, server); displayNetwork(currentId); - ui.serverList->setCurrentRow(cur); + ui.serverList->setCurrentRow(cur-1); widgetHasChanged(); - } } -void NetworksSettingsPage::on_deleteServer_clicked() { - if(currentId == 0) return; - int cur = ui.serverList->currentRow(); - networkInfos[currentId].serverList.removeAt(cur); - displayNetwork(currentId); - ui.serverList->setCurrentRow(qMin(cur, ui.serverList->count()-1)); - widgetHasChanged(); -} -void NetworksSettingsPage::on_upServer_clicked() { - int cur = ui.serverList->currentRow(); - Network::Server server = networkInfos[currentId].serverList.takeAt(cur); - networkInfos[currentId].serverList.insert(cur-1, server); - displayNetwork(currentId); - ui.serverList->setCurrentRow(cur-1); - widgetHasChanged(); +void NetworksSettingsPage::on_downServer_clicked() +{ + int cur = ui.serverList->currentRow(); + Network::Server server = networkInfos[currentId].serverList.takeAt(cur); + networkInfos[currentId].serverList.insert(cur+1, server); + displayNetwork(currentId); + ui.serverList->setCurrentRow(cur+1); + widgetHasChanged(); } -void NetworksSettingsPage::on_downServer_clicked() { - int cur = ui.serverList->currentRow(); - Network::Server server = networkInfos[currentId].serverList.takeAt(cur); - networkInfos[currentId].serverList.insert(cur+1, server); - displayNetwork(currentId); - ui.serverList->setCurrentRow(cur+1); - widgetHasChanged(); -} -void NetworksSettingsPage::on_editIdentities_clicked() { - SettingsPageDlg dlg(new IdentitiesSettingsPage(this), this); - dlg.exec(); +void NetworksSettingsPage::on_editIdentities_clicked() +{ + SettingsPageDlg dlg(new IdentitiesSettingsPage(this), this); + dlg.exec(); } -IdentityId NetworksSettingsPage::defaultIdentity() const { - IdentityId defaultId = 0; - QList ids = Client::identityIds(); - foreach(IdentityId id, ids) { - if(defaultId == 0 || id < defaultId) - defaultId = id; - } - return defaultId; + +IdentityId NetworksSettingsPage::defaultIdentity() const +{ + IdentityId defaultId = 0; + QList ids = Client::identityIds(); + foreach(IdentityId id, ids) { + if (defaultId == 0 || id < defaultId) + defaultId = id; + } + return defaultId; } + /************************************************************************** * NetworkAddDlg *************************************************************************/ -NetworkAddDlg::NetworkAddDlg(const QStringList &exist, QWidget *parent) : QDialog(parent), existing(exist) { - ui.setupUi(this); - ui.useSSL->setIcon(SmallIcon("document-encrypt")); +NetworkAddDlg::NetworkAddDlg(const QStringList &exist, QWidget *parent) : QDialog(parent), existing(exist) +{ + ui.setupUi(this); + ui.useSSL->setIcon(SmallIcon("document-encrypt")); - // read preset networks - QStringList networks = Network::presetNetworks(); - foreach(QString s, existing) + // read preset networks + QStringList networks = Network::presetNetworks(); + foreach(QString s, existing) networks.removeAll(s); - if(networks.count()) - ui.presetList->addItems(networks); - else { - ui.useManual->setChecked(true); - ui.usePreset->setEnabled(false); - } - connect(ui.networkName, SIGNAL(textChanged(const QString &)), SLOT(setButtonStates())); - connect(ui.serverAddress, SIGNAL(textChanged(const QString &)), SLOT(setButtonStates())); - setButtonStates(); -} - -NetworkInfo NetworkAddDlg::networkInfo() const { - if(ui.useManual->isChecked()) { - NetworkInfo info; - info.networkName = ui.networkName->text().trimmed(); - info.serverList << Network::Server(ui.serverAddress->text().trimmed(), ui.port->value(), ui.serverPassword->text(), ui.useSSL->isChecked()); - return info; - } else - return Network::networkInfoFromPreset(ui.presetList->currentText()); -} - -void NetworkAddDlg::setButtonStates() { - bool ok = false; - if(ui.usePreset->isChecked() && ui.presetList->count()) - ok = true; - else if(ui.useManual->isChecked()) { - ok = !ui.networkName->text().trimmed().isEmpty() && !existing.contains(ui.networkName->text().trimmed()) - && !ui.serverAddress->text().isEmpty(); - } - ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ok); + if (networks.count()) + ui.presetList->addItems(networks); + else { + ui.useManual->setChecked(true); + ui.usePreset->setEnabled(false); + } + connect(ui.networkName, SIGNAL(textChanged(const QString &)), SLOT(setButtonStates())); + connect(ui.serverAddress, SIGNAL(textChanged(const QString &)), SLOT(setButtonStates())); + setButtonStates(); +} + + +NetworkInfo NetworkAddDlg::networkInfo() const +{ + if (ui.useManual->isChecked()) { + NetworkInfo info; + info.networkName = ui.networkName->text().trimmed(); + info.serverList << Network::Server(ui.serverAddress->text().trimmed(), ui.port->value(), ui.serverPassword->text(), ui.useSSL->isChecked()); + return info; + } + else + return Network::networkInfoFromPreset(ui.presetList->currentText()); +} + + +void NetworkAddDlg::setButtonStates() +{ + bool ok = false; + if (ui.usePreset->isChecked() && ui.presetList->count()) + ok = true; + else if (ui.useManual->isChecked()) { + ok = !ui.networkName->text().trimmed().isEmpty() && !existing.contains(ui.networkName->text().trimmed()) + && !ui.serverAddress->text().isEmpty(); + } + ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ok); } + /************************************************************************** * NetworkEditDlg *************************************************************************/ -NetworkEditDlg::NetworkEditDlg(const QString &old, const QStringList &exist, QWidget *parent) : QDialog(parent), existing(exist) { - ui.setupUi(this); +NetworkEditDlg::NetworkEditDlg(const QString &old, const QStringList &exist, QWidget *parent) : QDialog(parent), existing(exist) +{ + ui.setupUi(this); - if(old.isEmpty()) { - // new network - setWindowTitle(tr("Add Network")); - on_networkEdit_textChanged(""); // disable ok button - } else ui.networkEdit->setText(old); + if (old.isEmpty()) { + // new network + setWindowTitle(tr("Add Network")); + on_networkEdit_textChanged(""); // disable ok button + } + else ui.networkEdit->setText(old); } -QString NetworkEditDlg::networkName() const { - return ui.networkEdit->text().trimmed(); +QString NetworkEditDlg::networkName() const +{ + return ui.networkEdit->text().trimmed(); } -void NetworkEditDlg::on_networkEdit_textChanged(const QString &text) { - ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(text.isEmpty() || existing.contains(text.trimmed())); + +void NetworkEditDlg::on_networkEdit_textChanged(const QString &text) +{ + ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(text.isEmpty() || existing.contains(text.trimmed())); } + /************************************************************************** * ServerEditDlg *************************************************************************/ -ServerEditDlg::ServerEditDlg(const Network::Server &server, QWidget *parent) : QDialog(parent) { - ui.setupUi(this); - ui.useSSL->setIcon(SmallIcon("document-encrypt")); - ui.host->setText(server.host); - ui.port->setValue(server.port); - ui.password->setText(server.password); - ui.useSSL->setChecked(server.useSsl); - ui.sslVersion->setCurrentIndex(server.sslVersion); - ui.useProxy->setChecked(server.useProxy); - ui.proxyType->setCurrentIndex(server.proxyType == QNetworkProxy::Socks5Proxy ? 0 : 1); - ui.proxyHost->setText(server.proxyHost); - ui.proxyPort->setValue(server.proxyPort); - ui.proxyUsername->setText(server.proxyUser); - ui.proxyPassword->setText(server.proxyPass); - on_host_textChanged(); -} - -Network::Server ServerEditDlg::serverData() const { - Network::Server server(ui.host->text().trimmed(), ui.port->value(), ui.password->text(), ui.useSSL->isChecked()); - server.sslVersion = ui.sslVersion->currentIndex(); - server.useProxy = ui.useProxy->isChecked(); - server.proxyType = ui.proxyType->currentIndex() == 0 ? QNetworkProxy::Socks5Proxy : QNetworkProxy::HttpProxy; - server.proxyHost = ui.proxyHost->text(); - server.proxyPort = ui.proxyPort->value(); - server.proxyUser = ui.proxyUsername->text(); - server.proxyPass = ui.proxyPassword->text(); - return server; -} - -void ServerEditDlg::on_host_textChanged() { - ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(ui.host->text().trimmed().isEmpty()); +ServerEditDlg::ServerEditDlg(const Network::Server &server, QWidget *parent) : QDialog(parent) +{ + ui.setupUi(this); + ui.useSSL->setIcon(SmallIcon("document-encrypt")); + ui.host->setText(server.host); + ui.port->setValue(server.port); + ui.password->setText(server.password); + ui.useSSL->setChecked(server.useSsl); + ui.sslVersion->setCurrentIndex(server.sslVersion); + ui.useProxy->setChecked(server.useProxy); + ui.proxyType->setCurrentIndex(server.proxyType == QNetworkProxy::Socks5Proxy ? 0 : 1); + ui.proxyHost->setText(server.proxyHost); + ui.proxyPort->setValue(server.proxyPort); + ui.proxyUsername->setText(server.proxyUser); + ui.proxyPassword->setText(server.proxyPass); + on_host_textChanged(); +} + + +Network::Server ServerEditDlg::serverData() const +{ + Network::Server server(ui.host->text().trimmed(), ui.port->value(), ui.password->text(), ui.useSSL->isChecked()); + server.sslVersion = ui.sslVersion->currentIndex(); + server.useProxy = ui.useProxy->isChecked(); + server.proxyType = ui.proxyType->currentIndex() == 0 ? QNetworkProxy::Socks5Proxy : QNetworkProxy::HttpProxy; + server.proxyHost = ui.proxyHost->text(); + server.proxyPort = ui.proxyPort->value(); + server.proxyUser = ui.proxyUsername->text(); + server.proxyPass = ui.proxyPassword->text(); + return server; +} + + +void ServerEditDlg::on_host_textChanged() +{ + ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(ui.host->text().trimmed().isEmpty()); } + /************************************************************************** * SaveNetworksDlg *************************************************************************/ SaveNetworksDlg::SaveNetworksDlg(const QList &toCreate, const QList &toUpdate, const QList &toRemove, QWidget *parent) : QDialog(parent) { - ui.setupUi(this); + ui.setupUi(this); - numevents = toCreate.count() + toUpdate.count() + toRemove.count(); - rcvevents = 0; - if(numevents) { - ui.progressBar->setMaximum(numevents); - ui.progressBar->setValue(0); + numevents = toCreate.count() + toUpdate.count() + toRemove.count(); + rcvevents = 0; + if (numevents) { + ui.progressBar->setMaximum(numevents); + ui.progressBar->setValue(0); - connect(Client::instance(), SIGNAL(networkCreated(NetworkId)), this, SLOT(clientEvent())); - connect(Client::instance(), SIGNAL(networkRemoved(NetworkId)), this, SLOT(clientEvent())); + connect(Client::instance(), SIGNAL(networkCreated(NetworkId)), this, SLOT(clientEvent())); + connect(Client::instance(), SIGNAL(networkRemoved(NetworkId)), this, SLOT(clientEvent())); - foreach(NetworkId id, toRemove) { - Client::removeNetwork(id); - } - foreach(NetworkInfo info, toCreate) { - Client::createNetwork(info); + foreach(NetworkId id, toRemove) { + Client::removeNetwork(id); + } + foreach(NetworkInfo info, toCreate) { + Client::createNetwork(info); + } + foreach(NetworkInfo info, toUpdate) { + const Network *net = Client::network(info.networkId); + if (!net) { + qWarning() << "Invalid client network!"; + numevents--; + continue; + } + // FIXME this only checks for one changed item rather than all! + connect(net, SIGNAL(updatedRemotely()), this, SLOT(clientEvent())); + Client::updateNetwork(info); + } } - foreach(NetworkInfo info, toUpdate) { - const Network *net = Client::network(info.networkId); - if(!net) { - qWarning() << "Invalid client network!"; - numevents--; - continue; - } - // FIXME this only checks for one changed item rather than all! - connect(net, SIGNAL(updatedRemotely()), this, SLOT(clientEvent())); - Client::updateNetwork(info); + else { + qWarning() << "Sync dialog called without stuff to change!"; + accept(); } - } else { - qWarning() << "Sync dialog called without stuff to change!"; - accept(); - } } -void SaveNetworksDlg::clientEvent() { - ui.progressBar->setValue(++rcvevents); - if(rcvevents >= numevents) accept(); + +void SaveNetworksDlg::clientEvent() +{ + ui.progressBar->setValue(++rcvevents); + if (rcvevents >= numevents) accept(); } diff --git a/src/qtui/settingspages/networkssettingspage.h b/src/qtui/settingspages/networkssettingspage.h index db209a74..09128c8c 100644 --- a/src/qtui/settingspages/networkssettingspage.h +++ b/src/qtui/settingspages/networkssettingspage.h @@ -32,137 +32,143 @@ #include "ui_servereditdlg.h" #include "ui_saveidentitiesdlg.h" -class NetworksSettingsPage : public SettingsPage { - Q_OBJECT +class NetworksSettingsPage : public SettingsPage +{ + Q_OBJECT public: - NetworksSettingsPage(QWidget *parent = 0); + NetworksSettingsPage(QWidget *parent = 0); - virtual inline bool needsCoreConnection() const { return true; } + virtual inline bool needsCoreConnection() const { return true; } - bool aboutToSave(); + bool aboutToSave(); public slots: - void save(); - void load(); + void save(); + void load(); private slots: - void widgetHasChanged(); - void setWidgetStates(); - void coreConnectionStateChanged(bool); - void networkConnectionStateChanged(Network::ConnectionState state); - void networkConnectionError(const QString &msg); - - void displayNetwork(NetworkId); - void setItemState(NetworkId, QListWidgetItem *item = 0); - - void clientNetworkAdded(NetworkId); - void clientNetworkRemoved(NetworkId); - void clientNetworkUpdated(); - - void clientIdentityAdded(IdentityId); - void clientIdentityRemoved(IdentityId); - void clientIdentityUpdated(); - - void on_networkList_itemSelectionChanged(); - void on_addNetwork_clicked(); - void on_deleteNetwork_clicked(); - void on_renameNetwork_clicked(); - void on_editIdentities_clicked(); - - // void on_connectNow_clicked(); - - void on_serverList_itemSelectionChanged(); - void on_addServer_clicked(); - void on_deleteServer_clicked(); - void on_editServer_clicked(); - void on_upServer_clicked(); - void on_downServer_clicked(); + void widgetHasChanged(); + void setWidgetStates(); + void coreConnectionStateChanged(bool); + void networkConnectionStateChanged(Network::ConnectionState state); + void networkConnectionError(const QString &msg); + + void displayNetwork(NetworkId); + void setItemState(NetworkId, QListWidgetItem *item = 0); + + void clientNetworkAdded(NetworkId); + void clientNetworkRemoved(NetworkId); + void clientNetworkUpdated(); + + void clientIdentityAdded(IdentityId); + void clientIdentityRemoved(IdentityId); + void clientIdentityUpdated(); + + void on_networkList_itemSelectionChanged(); + void on_addNetwork_clicked(); + void on_deleteNetwork_clicked(); + void on_renameNetwork_clicked(); + void on_editIdentities_clicked(); + + // void on_connectNow_clicked(); + + void on_serverList_itemSelectionChanged(); + void on_addServer_clicked(); + void on_deleteServer_clicked(); + void on_editServer_clicked(); + void on_upServer_clicked(); + void on_downServer_clicked(); private: - Ui::NetworksSettingsPage ui; + Ui::NetworksSettingsPage ui; - NetworkId currentId; - QHash networkInfos; - bool _ignoreWidgetChanges; + NetworkId currentId; + QHash networkInfos; + bool _ignoreWidgetChanges; - QPixmap connectedIcon, connectingIcon, disconnectedIcon; + QPixmap connectedIcon, connectingIcon, disconnectedIcon; - void reset(); - bool testHasChanged(); - QListWidgetItem *insertNetwork(NetworkId); - QListWidgetItem *insertNetwork(const NetworkInfo &info); - QListWidgetItem *networkItem(NetworkId) const; - void saveToNetworkInfo(NetworkInfo &); - IdentityId defaultIdentity() const; + void reset(); + bool testHasChanged(); + QListWidgetItem *insertNetwork(NetworkId); + QListWidgetItem *insertNetwork(const NetworkInfo &info); + QListWidgetItem *networkItem(NetworkId) const; + void saveToNetworkInfo(NetworkInfo &); + IdentityId defaultIdentity() const; }; -class NetworkAddDlg : public QDialog { - Q_OBJECT +class NetworkAddDlg : public QDialog +{ + Q_OBJECT - public: +public: NetworkAddDlg(const QStringList &existing = QStringList(), QWidget *parent = 0); NetworkInfo networkInfo() const; - private slots: +private slots: void setButtonStates(); - private: +private: Ui::NetworkAddDlg ui; QStringList existing; }; -class NetworkEditDlg : public QDialog { - Q_OBJECT +class NetworkEditDlg : public QDialog +{ + Q_OBJECT - public: +public: NetworkEditDlg(const QString &old, const QStringList &existing = QStringList(), QWidget *parent = 0); QString networkName() const; - private slots: +private slots: void on_networkEdit_textChanged(const QString &); - private: +private: Ui::NetworkEditDlg ui; QStringList existing; }; -class ServerEditDlg : public QDialog { - Q_OBJECT +class ServerEditDlg : public QDialog +{ + Q_OBJECT public: - ServerEditDlg(const Network::Server &server = Network::Server(), QWidget *parent = 0); + ServerEditDlg(const Network::Server &server = Network::Server(), QWidget *parent = 0); - Network::Server serverData() const; + Network::Server serverData() const; private slots: - void on_host_textChanged(); + void on_host_textChanged(); private: - Ui::ServerEditDlg ui; + Ui::ServerEditDlg ui; }; -class SaveNetworksDlg : public QDialog { - Q_OBJECT +class SaveNetworksDlg : public QDialog +{ + Q_OBJECT - public: +public: SaveNetworksDlg(const QList &toCreate, const QList &toUpdate, const QList &toRemove, QWidget *parent = 0); - private slots: +private slots: void clientEvent(); - private: +private: Ui::SaveIdentitiesDlg ui; int numevents, rcvevents; }; + #endif diff --git a/src/qtui/settingspages/notificationssettingspage.cpp b/src/qtui/settingspages/notificationssettingspage.cpp index 6ac1e0b7..3d4a0b64 100644 --- a/src/qtui/settingspages/notificationssettingspage.cpp +++ b/src/qtui/settingspages/notificationssettingspage.cpp @@ -25,54 +25,63 @@ #include "qtui.h" NotificationsSettingsPage::NotificationsSettingsPage(QWidget *parent) - : SettingsPage(tr("Interface"), tr("Notifications"), parent), - _hasDefaults(false) + : SettingsPage(tr("Interface"), tr("Notifications"), parent), + _hasDefaults(false) { - - QVBoxLayout *layout = new QVBoxLayout(this); - foreach(AbstractNotificationBackend *backend, QtUi::notificationBackends()) { - SettingsPage *cw = backend->createConfigWidget(); - if(cw) { - cw->setParent(this); - _configWidgets.append(cw); - layout->addWidget(cw); - connect(cw, SIGNAL(changed(bool)), SLOT(widgetHasChanged())); - _hasDefaults |= cw->hasDefaults(); + QVBoxLayout *layout = new QVBoxLayout(this); + foreach(AbstractNotificationBackend *backend, QtUi::notificationBackends()) { + SettingsPage *cw = backend->createConfigWidget(); + if (cw) { + cw->setParent(this); + _configWidgets.append(cw); + layout->addWidget(cw); + connect(cw, SIGNAL(changed(bool)), SLOT(widgetHasChanged())); + _hasDefaults |= cw->hasDefaults(); + } } - } - layout->addStretch(20); - load(); + layout->addStretch(20); + load(); } -bool NotificationsSettingsPage::hasDefaults() const { - return _hasDefaults; + +bool NotificationsSettingsPage::hasDefaults() const +{ + return _hasDefaults; } -void NotificationsSettingsPage::defaults() { - foreach(SettingsPage *cw, _configWidgets) + +void NotificationsSettingsPage::defaults() +{ + foreach(SettingsPage *cw, _configWidgets) cw->defaults(); - widgetHasChanged(); + widgetHasChanged(); } -void NotificationsSettingsPage::load() { - foreach(SettingsPage *cw, _configWidgets) + +void NotificationsSettingsPage::load() +{ + foreach(SettingsPage *cw, _configWidgets) cw->load(); - setChangedState(false); + setChangedState(false); } -void NotificationsSettingsPage::save() { - foreach(SettingsPage *cw, _configWidgets) + +void NotificationsSettingsPage::save() +{ + foreach(SettingsPage *cw, _configWidgets) cw->save(); - setChangedState(false); + setChangedState(false); } -void NotificationsSettingsPage::widgetHasChanged() { - bool changed = false; - foreach(SettingsPage *cw, _configWidgets) { - if(cw->hasChanged()) { - changed = true; - break; + +void NotificationsSettingsPage::widgetHasChanged() +{ + bool changed = false; + foreach(SettingsPage *cw, _configWidgets) { + if (cw->hasChanged()) { + changed = true; + break; + } } - } - if(changed != hasChanged()) setChangedState(changed); + if (changed != hasChanged()) setChangedState(changed); } diff --git a/src/qtui/settingspages/notificationssettingspage.h b/src/qtui/settingspages/notificationssettingspage.h index 7734fa2f..13354149 100644 --- a/src/qtui/settingspages/notificationssettingspage.h +++ b/src/qtui/settingspages/notificationssettingspage.h @@ -30,25 +30,27 @@ * \NOTE: When this is called, all backends need to be already registered. No dynamic changes * are tracked or reacted to! */ -class NotificationsSettingsPage : public SettingsPage { - Q_OBJECT +class NotificationsSettingsPage : public SettingsPage +{ + Q_OBJECT - public: +public: NotificationsSettingsPage(QWidget *parent = 0); bool hasDefaults() const; - public slots: +public slots: void save(); void load(); void defaults(); - private slots: +private slots: void widgetHasChanged(); - private: +private: QList _configWidgets; bool _hasDefaults; }; + #endif diff --git a/src/qtui/settingspages/previewbufferview.h b/src/qtui/settingspages/previewbufferview.h index 1c50d635..4e1f7ae8 100644 --- a/src/qtui/settingspages/previewbufferview.h +++ b/src/qtui/settingspages/previewbufferview.h @@ -23,15 +23,17 @@ #include "bufferview.h" -class PreviewBufferView : public BufferView { - Q_OBJECT +class PreviewBufferView : public BufferView +{ + Q_OBJECT public: - PreviewBufferView(QWidget *parent = 0) : BufferView(parent) {} + PreviewBufferView(QWidget *parent = 0) : BufferView(parent) {} protected: - virtual void keyPressEvent(QKeyEvent *event) { QTreeView::keyPressEvent(event); } - virtual void contextMenuEvent(QContextMenuEvent *) {} + virtual void keyPressEvent(QKeyEvent *event) { QTreeView::keyPressEvent(event); } + virtual void contextMenuEvent(QContextMenuEvent *) {} }; + #endif //PREVIEWBUFFERVIEW_H diff --git a/src/qtui/settingspages/shortcutsmodel.cpp b/src/qtui/settingspages/shortcutsmodel.cpp index c1e5d264..8a42f2c0 100644 --- a/src/qtui/settingspages/shortcutsmodel.cpp +++ b/src/qtui/settingspages/shortcutsmodel.cpp @@ -25,208 +25,230 @@ #include "util.h" ShortcutsModel::ShortcutsModel(const QHash &actionCollections, QObject *parent) - : QAbstractItemModel(parent), - _changedCount(0) + : QAbstractItemModel(parent), + _changedCount(0) { - for(int r = 0; r < actionCollections.values().count(); r++) { - ActionCollection *coll = actionCollections.values().at(r); - Item *item = new Item(); - item->row = r; - item->collection = coll; - for(int i = 0; i < coll->actions().count(); i++) { - Action *action = qobject_cast(coll->actions().at(i)); - if(!action) - continue; - Item *actionItem = new Item(); - actionItem->parentItem = item; - actionItem->row = i; - actionItem->collection = coll; - actionItem->action = action; - actionItem->shortcut = action->shortcut(); - item->actionItems.append(actionItem); + for (int r = 0; r < actionCollections.values().count(); r++) { + ActionCollection *coll = actionCollections.values().at(r); + Item *item = new Item(); + item->row = r; + item->collection = coll; + for (int i = 0; i < coll->actions().count(); i++) { + Action *action = qobject_cast(coll->actions().at(i)); + if (!action) + continue; + Item *actionItem = new Item(); + actionItem->parentItem = item; + actionItem->row = i; + actionItem->collection = coll; + actionItem->action = action; + actionItem->shortcut = action->shortcut(); + item->actionItems.append(actionItem); + } + _categoryItems.append(item); } - _categoryItems.append(item); - } } -ShortcutsModel::~ShortcutsModel() { - qDeleteAll(_categoryItems); + +ShortcutsModel::~ShortcutsModel() +{ + qDeleteAll(_categoryItems); } -QModelIndex ShortcutsModel::parent(const QModelIndex &child) const { - if(!child.isValid()) - return QModelIndex(); - Item *item = static_cast(child.internalPointer()); - Q_ASSERT(item); +QModelIndex ShortcutsModel::parent(const QModelIndex &child) const +{ + if (!child.isValid()) + return QModelIndex(); - if(!item->parentItem) - return QModelIndex(); + Item *item = static_cast(child.internalPointer()); + Q_ASSERT(item); - return createIndex(item->parentItem->row, 0, item->parentItem); + if (!item->parentItem) + return QModelIndex(); + + return createIndex(item->parentItem->row, 0, item->parentItem); } -QModelIndex ShortcutsModel::index(int row, int column, const QModelIndex &parent) const { - if(parent.isValid()) - return createIndex(row, column, static_cast(parent.internalPointer())->actionItems.at(row)); +QModelIndex ShortcutsModel::index(int row, int column, const QModelIndex &parent) const +{ + if (parent.isValid()) + return createIndex(row, column, static_cast(parent.internalPointer())->actionItems.at(row)); - // top level category item - return createIndex(row, column, _categoryItems.at(row)); + // top level category item + return createIndex(row, column, _categoryItems.at(row)); } -int ShortcutsModel::columnCount(const QModelIndex &parent) const { - return 2; - if(!parent.isValid()) + +int ShortcutsModel::columnCount(const QModelIndex &parent) const +{ return 2; + if (!parent.isValid()) + return 2; - Item *item = static_cast(parent.internalPointer()); - Q_ASSERT(item); + Item *item = static_cast(parent.internalPointer()); + Q_ASSERT(item); - if(!item->parentItem) - return 2; + if (!item->parentItem) + return 2; - return 2; + return 2; } -int ShortcutsModel::rowCount(const QModelIndex &parent) const { - if(!parent.isValid()) - return _categoryItems.count(); - Item *item = static_cast(parent.internalPointer()); - Q_ASSERT(item); +int ShortcutsModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) + return _categoryItems.count(); - if(!item->parentItem) - return item->actionItems.count(); + Item *item = static_cast(parent.internalPointer()); + Q_ASSERT(item); - return 0; -} + if (!item->parentItem) + return item->actionItems.count(); -QVariant ShortcutsModel::headerData(int section, Qt::Orientation orientation, int role) const { - if(orientation != Qt::Horizontal || role != Qt::DisplayRole) - return QVariant(); - switch(section) { - case 0: - return tr("Action"); - case 1: - return tr("Shortcut"); - default: - return QVariant(); - } + return 0; } -QVariant ShortcutsModel::data(const QModelIndex &index, int role) const { - if(!index.isValid()) - return QVariant(); - - Item *item = static_cast(index.internalPointer()); - Q_ASSERT(item); - if(!item->parentItem) { - if(index.column() != 0) - return QVariant(); - switch(role) { - case Qt::DisplayRole: - return item->collection->property("Category"); - default: - return QVariant(); - } - } - - Action *action = qobject_cast(item->action); - Q_ASSERT(action); - - switch(role) { - case Qt::DisplayRole: - switch(index.column()) { +QVariant ShortcutsModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation != Qt::Horizontal || role != Qt::DisplayRole) + return QVariant(); + switch (section) { case 0: - return stripAcceleratorMarkers(action->text()); + return tr("Action"); case 1: - return item->shortcut.toString(QKeySequence::NativeText); + return tr("Shortcut"); default: - return QVariant(); + return QVariant(); } +} - case Qt::DecorationRole: - if(index.column() == 0) - return action->icon(); - return QVariant(); - case ActionRole: - return QVariant::fromValue(action); +QVariant ShortcutsModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + Item *item = static_cast(index.internalPointer()); + Q_ASSERT(item); + + if (!item->parentItem) { + if (index.column() != 0) + return QVariant(); + switch (role) { + case Qt::DisplayRole: + return item->collection->property("Category"); + default: + return QVariant(); + } + } - case DefaultShortcutRole: - return action->shortcut(Action::DefaultShortcut); - case ActiveShortcutRole: - return item->shortcut; + Action *action = qobject_cast(item->action); + Q_ASSERT(action); - case IsConfigurableRole: - return action->isShortcutConfigurable(); + switch (role) { + case Qt::DisplayRole: + switch (index.column()) { + case 0: + return stripAcceleratorMarkers(action->text()); + case 1: + return item->shortcut.toString(QKeySequence::NativeText); + default: + return QVariant(); + } + + case Qt::DecorationRole: + if (index.column() == 0) + return action->icon(); + return QVariant(); + + case ActionRole: + return QVariant::fromValue(action); + + case DefaultShortcutRole: + return action->shortcut(Action::DefaultShortcut); + case ActiveShortcutRole: + return item->shortcut; + + case IsConfigurableRole: + return action->isShortcutConfigurable(); - default: - return QVariant(); - } + default: + return QVariant(); + } } -bool ShortcutsModel::setData(const QModelIndex &index, const QVariant &value, int role) { - if(role != ActiveShortcutRole) - return false; - if(!index.parent().isValid()) - return false; +bool ShortcutsModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (role != ActiveShortcutRole) + return false; + + if (!index.parent().isValid()) + return false; - Item *item = static_cast(index.internalPointer()); - Q_ASSERT(item); + Item *item = static_cast(index.internalPointer()); + Q_ASSERT(item); - QKeySequence newSeq = value.value(); - QKeySequence oldSeq = item->shortcut; - QKeySequence storedSeq = item->action->shortcut(Action::ActiveShortcut); + QKeySequence newSeq = value.value(); + QKeySequence oldSeq = item->shortcut; + QKeySequence storedSeq = item->action->shortcut(Action::ActiveShortcut); - item->shortcut = newSeq; - emit dataChanged(index, index.sibling(index.row(), 1)); + item->shortcut = newSeq; + emit dataChanged(index, index.sibling(index.row(), 1)); - if(oldSeq == storedSeq && newSeq != storedSeq) { - if(++_changedCount == 1) - emit hasChanged(true); - } else if(oldSeq != storedSeq && newSeq == storedSeq) { - if(--_changedCount == 0) - emit hasChanged(false); - } + if (oldSeq == storedSeq && newSeq != storedSeq) { + if (++_changedCount == 1) + emit hasChanged(true); + } + else if (oldSeq != storedSeq && newSeq == storedSeq) { + if (--_changedCount == 0) + emit hasChanged(false); + } - return true; + return true; } -void ShortcutsModel::load() { - foreach(Item *catItem, _categoryItems) { - foreach(Item *actItem, catItem->actionItems) { - actItem->shortcut = actItem->action->shortcut(Action::ActiveShortcut); + +void ShortcutsModel::load() +{ + foreach(Item *catItem, _categoryItems) { + foreach(Item *actItem, catItem->actionItems) { + actItem->shortcut = actItem->action->shortcut(Action::ActiveShortcut); + } + } + emit dataChanged(index(0, 1), index(rowCount()-1, 1)); + if (_changedCount != 0) { + _changedCount = 0; + emit hasChanged(false); } - } - emit dataChanged(index(0, 1), index(rowCount()-1, 1)); - if(_changedCount != 0) { - _changedCount = 0; - emit hasChanged(false); - } } -void ShortcutsModel::commit() { - foreach(Item *catItem, _categoryItems) { - foreach(Item *actItem, catItem->actionItems) { - actItem->action->setShortcut(actItem->shortcut, Action::ActiveShortcut); + +void ShortcutsModel::commit() +{ + foreach(Item *catItem, _categoryItems) { + foreach(Item *actItem, catItem->actionItems) { + actItem->action->setShortcut(actItem->shortcut, Action::ActiveShortcut); + } + } + if (_changedCount != 0) { + _changedCount = 0; + emit hasChanged(false); } - } - if(_changedCount != 0) { - _changedCount = 0; - emit hasChanged(false); - } } -void ShortcutsModel::defaults() { - for(int cat = 0; cat < rowCount(); cat++) { - QModelIndex catidx = index(cat, 0); - for(int act = 0; act < rowCount(catidx); act++) { - QModelIndex actidx = index(act, 1, catidx); - setData(actidx, actidx.data(DefaultShortcutRole), ActiveShortcutRole); + +void ShortcutsModel::defaults() +{ + for (int cat = 0; cat < rowCount(); cat++) { + QModelIndex catidx = index(cat, 0); + for (int act = 0; act < rowCount(catidx); act++) { + QModelIndex actidx = index(act, 1, catidx); + setData(actidx, actidx.data(DefaultShortcutRole), ActiveShortcutRole); + } } - } } diff --git a/src/qtui/settingspages/shortcutsmodel.h b/src/qtui/settingspages/shortcutsmodel.h index a52e073c..3aa7657b 100644 --- a/src/qtui/settingspages/shortcutsmodel.h +++ b/src/qtui/settingspages/shortcutsmodel.h @@ -32,65 +32,67 @@ class ActionCollection; * Note that the ShortcutsModel will not react to changes in the ActionCollection (e.g. adding, * removing actions), because it is supposed to be used after all actions being defined. */ -class ShortcutsModel : public QAbstractItemModel { - Q_OBJECT +class ShortcutsModel : public QAbstractItemModel +{ + Q_OBJECT public: - enum Role { - ActionRole = Qt::UserRole, - DefaultShortcutRole, - ActiveShortcutRole, - IsConfigurableRole - }; + enum Role { + ActionRole = Qt::UserRole, + DefaultShortcutRole, + ActiveShortcutRole, + IsConfigurableRole + }; - ShortcutsModel(const QHash &actionCollections, QObject *parent = 0); - ~ShortcutsModel(); + ShortcutsModel(const QHash &actionCollections, QObject *parent = 0); + ~ShortcutsModel(); - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; - QModelIndex parent(const QModelIndex &child) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - bool setData(const QModelIndex &index, const QVariant &value, int role = ActiveShortcutRole); + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &child) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + bool setData(const QModelIndex &index, const QVariant &value, int role = ActiveShortcutRole); public slots: - //! Load shortcuts from the ActionCollections - /** Note that this will not rebuild the internal structure of the model, as we assume the - * ActionCollections to be static during the lifetime of the settingspage. This will merely - * re-read the shortcuts currently set in Quassel. - */ - void load(); + //! Load shortcuts from the ActionCollections + /** Note that this will not rebuild the internal structure of the model, as we assume the + * ActionCollections to be static during the lifetime of the settingspage. This will merely + * re-read the shortcuts currently set in Quassel. + */ + void load(); - //! Load default shortcuts from the ActionCollections - /** Note that this will not rebuild the internal structure of the model, as we assume the - * ActionCollections to be static during the lifetime of the settingspage. This will update - * the model's state from the ActionCollections' defaults. - */ - void defaults(); + //! Load default shortcuts from the ActionCollections + /** Note that this will not rebuild the internal structure of the model, as we assume the + * ActionCollections to be static during the lifetime of the settingspage. This will update + * the model's state from the ActionCollections' defaults. + */ + void defaults(); - //! Commit the model changes to the ActionCollections - void commit(); + //! Commit the model changes to the ActionCollections + void commit(); - inline bool hasChanged() const { return _changedCount; } + inline bool hasChanged() const { return _changedCount; } signals: - //! Reflects the difference between model contents and the ActionCollections we loaded this from - void hasChanged(bool changed); + //! Reflects the difference between model contents and the ActionCollections we loaded this from + void hasChanged(bool changed); private: - struct Item { - inline Item() { parentItem = 0; collection = 0; action = 0; } - inline ~Item() { qDeleteAll(actionItems); } - int row; - Item *parentItem; - ActionCollection *collection; - Action *action; - QKeySequence shortcut; - QList actionItems; - }; + struct Item { + inline Item() { parentItem = 0; collection = 0; action = 0; } + inline ~Item() { qDeleteAll(actionItems); } + int row; + Item *parentItem; + ActionCollection *collection; + Action *action; + QKeySequence shortcut; + QList actionItems; + }; - QList _categoryItems; - int _changedCount; + QList _categoryItems; + int _changedCount; }; + #endif // SHORTCUTSMODEL_H diff --git a/src/qtui/settingspages/shortcutssettingspage.cpp b/src/qtui/settingspages/shortcutssettingspage.cpp index af97445a..ecb133f6 100644 --- a/src/qtui/settingspages/shortcutssettingspage.cpp +++ b/src/qtui/settingspages/shortcutssettingspage.cpp @@ -1,4 +1,3 @@ - /*************************************************************************** * Copyright (C) 2010 by the Quassel Project * * devel@quassel-irc.org * @@ -29,126 +28,149 @@ #include "shortcutsmodel.h" #include "util.h" -ShortcutsFilter::ShortcutsFilter(QObject *parent) : QSortFilterProxyModel(parent) { - setDynamicSortFilter(true); +ShortcutsFilter::ShortcutsFilter(QObject *parent) : QSortFilterProxyModel(parent) +{ + setDynamicSortFilter(true); } -void ShortcutsFilter::setFilterString(const QString &filterString) { - _filterString = filterString; - invalidateFilter(); + +void ShortcutsFilter::setFilterString(const QString &filterString) +{ + _filterString = filterString; + invalidateFilter(); } -bool ShortcutsFilter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { - if(!source_parent.isValid()) - return true; - QModelIndex index = source_parent.model()->index(source_row, 0, source_parent); - Q_ASSERT(index.isValid()); - if(!qobject_cast(index.data(ShortcutsModel::ActionRole).value())->isShortcutConfigurable()) - return false; +bool ShortcutsFilter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const +{ + if (!source_parent.isValid()) + return true; + + QModelIndex index = source_parent.model()->index(source_row, 0, source_parent); + Q_ASSERT(index.isValid()); + if (!qobject_cast(index.data(ShortcutsModel::ActionRole).value())->isShortcutConfigurable()) + return false; - for(int col = 0; col < source_parent.model()->columnCount(source_parent); col++) { - if(source_parent.model()->index(source_row, col, source_parent).data().toString().contains(_filterString, Qt::CaseInsensitive)) - return true; - } - return false; + for (int col = 0; col < source_parent.model()->columnCount(source_parent); col++) { + if (source_parent.model()->index(source_row, col, source_parent).data().toString().contains(_filterString, Qt::CaseInsensitive)) + return true; + } + return false; } + /****************************************************************************/ ShortcutsSettingsPage::ShortcutsSettingsPage(const QHash &actionCollections, QWidget *parent) - : SettingsPage(tr("Interface"), tr("Shortcuts"), parent), - _shortcutsModel(new ShortcutsModel(actionCollections, this)), - _shortcutsFilter(new ShortcutsFilter(this)) + : SettingsPage(tr("Interface"), tr("Shortcuts"), parent), + _shortcutsModel(new ShortcutsModel(actionCollections, this)), + _shortcutsFilter(new ShortcutsFilter(this)) { - ui.setupUi(this); + ui.setupUi(this); - _shortcutsFilter->setSourceModel(_shortcutsModel); - ui.shortcutsView->setModel(_shortcutsFilter); - ui.shortcutsView->expandAll(); - ui.shortcutsView->resizeColumnToContents(0); - ui.shortcutsView->sortByColumn(0, Qt::AscendingOrder); + _shortcutsFilter->setSourceModel(_shortcutsModel); + ui.shortcutsView->setModel(_shortcutsFilter); + ui.shortcutsView->expandAll(); + ui.shortcutsView->resizeColumnToContents(0); + ui.shortcutsView->sortByColumn(0, Qt::AscendingOrder); - ui.keySequenceWidget->setModel(_shortcutsModel); - connect(ui.keySequenceWidget, SIGNAL(keySequenceChanged(QKeySequence,QModelIndex)), SLOT(keySequenceChanged(QKeySequence,QModelIndex))); + ui.keySequenceWidget->setModel(_shortcutsModel); + connect(ui.keySequenceWidget, SIGNAL(keySequenceChanged(QKeySequence, QModelIndex)), SLOT(keySequenceChanged(QKeySequence, QModelIndex))); - connect(ui.shortcutsView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), SLOT(setWidgetStates())); + connect(ui.shortcutsView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), SLOT(setWidgetStates())); - setWidgetStates(); + setWidgetStates(); - connect(ui.useDefault, SIGNAL(clicked(bool)), SLOT(toggledCustomOrDefault())); - connect(ui.useCustom, SIGNAL(clicked(bool)), SLOT(toggledCustomOrDefault())); + connect(ui.useDefault, SIGNAL(clicked(bool)), SLOT(toggledCustomOrDefault())); + connect(ui.useCustom, SIGNAL(clicked(bool)), SLOT(toggledCustomOrDefault())); - connect(_shortcutsModel, SIGNAL(hasChanged(bool)), SLOT(setChangedState(bool))); + connect(_shortcutsModel, SIGNAL(hasChanged(bool)), SLOT(setChangedState(bool))); - // fugly, but directly setting it from the ctor doesn't seem to work - QTimer::singleShot(0, ui.searchEdit, SLOT(setFocus())); + // fugly, but directly setting it from the ctor doesn't seem to work + QTimer::singleShot(0, ui.searchEdit, SLOT(setFocus())); } -void ShortcutsSettingsPage::setWidgetStates() { - if(ui.shortcutsView->currentIndex().isValid() && ui.shortcutsView->currentIndex().parent().isValid()) { - QKeySequence active = ui.shortcutsView->currentIndex().data(ShortcutsModel::ActiveShortcutRole).value(); - QKeySequence def = ui.shortcutsView->currentIndex().data(ShortcutsModel::DefaultShortcutRole).value(); - ui.defaultShortcut->setText(def.isEmpty()? tr("None") : def.toString(QKeySequence::NativeText)); - ui.actionBox->setEnabled(true); - if(active == def) { - ui.useDefault->setChecked(true); - ui.keySequenceWidget->setKeySequence(QKeySequence()); - } else { - ui.useCustom->setChecked(true); - ui.keySequenceWidget->setKeySequence(active); + +void ShortcutsSettingsPage::setWidgetStates() +{ + if (ui.shortcutsView->currentIndex().isValid() && ui.shortcutsView->currentIndex().parent().isValid()) { + QKeySequence active = ui.shortcutsView->currentIndex().data(ShortcutsModel::ActiveShortcutRole).value(); + QKeySequence def = ui.shortcutsView->currentIndex().data(ShortcutsModel::DefaultShortcutRole).value(); + ui.defaultShortcut->setText(def.isEmpty() ? tr("None") : def.toString(QKeySequence::NativeText)); + ui.actionBox->setEnabled(true); + if (active == def) { + ui.useDefault->setChecked(true); + ui.keySequenceWidget->setKeySequence(QKeySequence()); + } + else { + ui.useCustom->setChecked(true); + ui.keySequenceWidget->setKeySequence(active); + } + } + else { + ui.defaultShortcut->setText(tr("None")); + ui.actionBox->setEnabled(false); + ui.useDefault->setChecked(true); + ui.keySequenceWidget->setKeySequence(QKeySequence()); } - } else { - ui.defaultShortcut->setText(tr("None")); - ui.actionBox->setEnabled(false); - ui.useDefault->setChecked(true); - ui.keySequenceWidget->setKeySequence(QKeySequence()); - } } -void ShortcutsSettingsPage::on_searchEdit_textChanged(const QString &text) { - _shortcutsFilter->setFilterString(text); + +void ShortcutsSettingsPage::on_searchEdit_textChanged(const QString &text) +{ + _shortcutsFilter->setFilterString(text); } -void ShortcutsSettingsPage::keySequenceChanged(const QKeySequence &seq, const QModelIndex &conflicting) { - if(conflicting.isValid()) - _shortcutsModel->setData(conflicting, QKeySequence(), ShortcutsModel::ActiveShortcutRole); - QModelIndex rowIdx = _shortcutsFilter->mapToSource(ui.shortcutsView->currentIndex()); - Q_ASSERT(rowIdx.isValid()); - _shortcutsModel->setData(rowIdx, seq, ShortcutsModel::ActiveShortcutRole); - setWidgetStates(); +void ShortcutsSettingsPage::keySequenceChanged(const QKeySequence &seq, const QModelIndex &conflicting) +{ + if (conflicting.isValid()) + _shortcutsModel->setData(conflicting, QKeySequence(), ShortcutsModel::ActiveShortcutRole); + + QModelIndex rowIdx = _shortcutsFilter->mapToSource(ui.shortcutsView->currentIndex()); + Q_ASSERT(rowIdx.isValid()); + _shortcutsModel->setData(rowIdx, seq, ShortcutsModel::ActiveShortcutRole); + setWidgetStates(); } -void ShortcutsSettingsPage::toggledCustomOrDefault() { - if(!ui.shortcutsView->currentIndex().isValid()) - return; - QModelIndex index = _shortcutsFilter->mapToSource(ui.shortcutsView->currentIndex()); - Q_ASSERT(index.isValid()); +void ShortcutsSettingsPage::toggledCustomOrDefault() +{ + if (!ui.shortcutsView->currentIndex().isValid()) + return; - if(ui.useDefault->isChecked()) { - _shortcutsModel->setData(index, index.data(ShortcutsModel::DefaultShortcutRole)); - } else { - _shortcutsModel->setData(index, QKeySequence()); - } - setWidgetStates(); + QModelIndex index = _shortcutsFilter->mapToSource(ui.shortcutsView->currentIndex()); + Q_ASSERT(index.isValid()); + + if (ui.useDefault->isChecked()) { + _shortcutsModel->setData(index, index.data(ShortcutsModel::DefaultShortcutRole)); + } + else { + _shortcutsModel->setData(index, QKeySequence()); + } + setWidgetStates(); } -void ShortcutsSettingsPage::save() { - _shortcutsModel->commit(); - QtUi::saveShortcuts(); - SettingsPage::save(); + +void ShortcutsSettingsPage::save() +{ + _shortcutsModel->commit(); + QtUi::saveShortcuts(); + SettingsPage::save(); } -void ShortcutsSettingsPage::load() { - _shortcutsModel->load(); - SettingsPage::load(); +void ShortcutsSettingsPage::load() +{ + _shortcutsModel->load(); + + SettingsPage::load(); } -void ShortcutsSettingsPage::defaults() { - _shortcutsModel->defaults(); - SettingsPage::defaults(); +void ShortcutsSettingsPage::defaults() +{ + _shortcutsModel->defaults(); + + SettingsPage::defaults(); } diff --git a/src/qtui/settingspages/shortcutssettingspage.h b/src/qtui/settingspages/shortcutssettingspage.h index bd3413df..aa7701be 100644 --- a/src/qtui/settingspages/shortcutssettingspage.h +++ b/src/qtui/settingspages/shortcutssettingspage.h @@ -30,43 +30,47 @@ class ActionCollection; class ShortcutsModel; -class ShortcutsFilter : public QSortFilterProxyModel { - Q_OBJECT +class ShortcutsFilter : public QSortFilterProxyModel +{ + Q_OBJECT public: - ShortcutsFilter(QObject *parent = 0); + ShortcutsFilter(QObject *parent = 0); public slots: - void setFilterString(const QString &filterString); + void setFilterString(const QString &filterString); protected: - virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; + virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; private: - QString _filterString; + QString _filterString; }; -class ShortcutsSettingsPage : public SettingsPage { - Q_OBJECT + +class ShortcutsSettingsPage : public SettingsPage +{ + Q_OBJECT public: - ShortcutsSettingsPage(const QHash &actionCollections, QWidget *parent = 0); + ShortcutsSettingsPage(const QHash &actionCollections, QWidget *parent = 0); - inline bool hasDefaults() const { return true; } + inline bool hasDefaults() const { return true; } public slots: - void save(); - void load(); - void defaults(); + void save(); + void load(); + void defaults(); private slots: - void on_searchEdit_textChanged(const QString &text); - void keySequenceChanged(const QKeySequence &seq, const QModelIndex &conflicting); - void setWidgetStates(); - void toggledCustomOrDefault(); + void on_searchEdit_textChanged(const QString &text); + void keySequenceChanged(const QKeySequence &seq, const QModelIndex &conflicting); + void setWidgetStates(); + void toggledCustomOrDefault(); private: - Ui::ShortcutsSettingsPage ui; - ShortcutsModel *_shortcutsModel; - ShortcutsFilter *_shortcutsFilter; + Ui::ShortcutsSettingsPage ui; + ShortcutsModel *_shortcutsModel; + ShortcutsFilter *_shortcutsFilter; }; + #endif // SHORTCUTSSETTINGSPAGE_H diff --git a/src/qtui/settingspages/topicwidgetsettingspage.cpp b/src/qtui/settingspages/topicwidgetsettingspage.cpp index 46f40cb9..e9a3374f 100644 --- a/src/qtui/settingspages/topicwidgetsettingspage.cpp +++ b/src/qtui/settingspages/topicwidgetsettingspage.cpp @@ -20,9 +20,9 @@ #include "topicwidgetsettingspage.h" TopicWidgetSettingsPage::TopicWidgetSettingsPage(QWidget *parent) - : SettingsPage(tr("Interface"), tr("Topic Widget"), parent) + : SettingsPage(tr("Interface"), tr("Topic Widget"), parent) { - ui.setupUi(this); + ui.setupUi(this); - initAutoWidgets(); + initAutoWidgets(); } diff --git a/src/qtui/settingspages/topicwidgetsettingspage.h b/src/qtui/settingspages/topicwidgetsettingspage.h index adc3ed49..2f9063d4 100644 --- a/src/qtui/settingspages/topicwidgetsettingspage.h +++ b/src/qtui/settingspages/topicwidgetsettingspage.h @@ -24,18 +24,20 @@ #include "settingspage.h" #include "ui_topicwidgetsettingspage.h" -class TopicWidgetSettingsPage : public SettingsPage { - Q_OBJECT +class TopicWidgetSettingsPage : public SettingsPage +{ + Q_OBJECT public: - TopicWidgetSettingsPage(QWidget *parent = 0); + TopicWidgetSettingsPage(QWidget *parent = 0); - inline bool hasDefaults() const { return true; } + inline bool hasDefaults() const { return true; } private: - Ui::TopicWidgetSettingsPage ui; + Ui::TopicWidgetSettingsPage ui; - inline QString settingsKey() const { return QString("TopicWidget"); } + inline QString settingsKey() const { return QString("TopicWidget"); } }; + #endif diff --git a/src/qtui/simplenetworkeditor.cpp b/src/qtui/simplenetworkeditor.cpp index a185e62b..22ff3a9a 100644 --- a/src/qtui/simplenetworkeditor.cpp +++ b/src/qtui/simplenetworkeditor.cpp @@ -25,109 +25,132 @@ #include "networkssettingspage.h" SimpleNetworkEditor::SimpleNetworkEditor(QWidget *parent) - : QWidget(parent) + : QWidget(parent) { - ui.setupUi(this); + ui.setupUi(this); - ui.addServer->setIcon(SmallIcon("list-add")); - ui.deleteServer->setIcon(SmallIcon("edit-delete")); - ui.editServer->setIcon(SmallIcon("configure")); - ui.upServer->setIcon(SmallIcon("go-up")); - ui.downServer->setIcon(SmallIcon("go-down")); + ui.addServer->setIcon(SmallIcon("list-add")); + ui.deleteServer->setIcon(SmallIcon("edit-delete")); + ui.editServer->setIcon(SmallIcon("configure")); + ui.upServer->setIcon(SmallIcon("go-up")); + ui.downServer->setIcon(SmallIcon("go-down")); - connect(ui.networkNameEdit, SIGNAL(textEdited(const QString &)), this, SIGNAL(widgetHasChanged())); - connect(ui.channelList, SIGNAL(textChanged()), this, SIGNAL(widgetHasChanged())); + connect(ui.networkNameEdit, SIGNAL(textEdited(const QString &)), this, SIGNAL(widgetHasChanged())); + connect(ui.channelList, SIGNAL(textChanged()), this, SIGNAL(widgetHasChanged())); } -void SimpleNetworkEditor::setWidgetStates() { - if(ui.serverList->selectedItems().count()) { - ui.editServer->setEnabled(true); - ui.deleteServer->setEnabled(true); - ui.upServer->setEnabled(ui.serverList->currentRow() > 0); - ui.downServer->setEnabled(ui.serverList->currentRow() < ui.serverList->count() - 1); - } else { - ui.editServer->setEnabled(false); - ui.deleteServer->setEnabled(false); - ui.upServer->setEnabled(false); - ui.downServer->setEnabled(false); - } + +void SimpleNetworkEditor::setWidgetStates() +{ + if (ui.serverList->selectedItems().count()) { + ui.editServer->setEnabled(true); + ui.deleteServer->setEnabled(true); + ui.upServer->setEnabled(ui.serverList->currentRow() > 0); + ui.downServer->setEnabled(ui.serverList->currentRow() < ui.serverList->count() - 1); + } + else { + ui.editServer->setEnabled(false); + ui.deleteServer->setEnabled(false); + ui.upServer->setEnabled(false); + ui.downServer->setEnabled(false); + } } -void SimpleNetworkEditor::displayNetworkInfo(const NetworkInfo &networkInfo) { - _networkInfo = networkInfo; - ui.serverList->clear(); - foreach(Network::Server server, _networkInfo.serverList) { - QListWidgetItem *item = new QListWidgetItem(QString("%1:%2").arg(server.host).arg(server.port)); - if(server.useSsl) - item->setIcon(SmallIcon("document-encrypt")); - ui.serverList->addItem(item); - } +void SimpleNetworkEditor::displayNetworkInfo(const NetworkInfo &networkInfo) +{ + _networkInfo = networkInfo; + + ui.serverList->clear(); + foreach(Network::Server server, _networkInfo.serverList) { + QListWidgetItem *item = new QListWidgetItem(QString("%1:%2").arg(server.host).arg(server.port)); + if (server.useSsl) + item->setIcon(SmallIcon("document-encrypt")); + ui.serverList->addItem(item); + } + + ui.networkNameEdit->setText(_networkInfo.networkName); + setWidgetStates(); +} + + +void SimpleNetworkEditor::saveToNetworkInfo(NetworkInfo &networkInfo) +{ + _networkInfo.networkName = ui.networkNameEdit->text(); + networkInfo = _networkInfo; +} + - ui.networkNameEdit->setText(_networkInfo.networkName); - setWidgetStates(); +QStringList SimpleNetworkEditor::defaultChannels() const +{ + return ui.channelList->toPlainText().split("\n", QString::SkipEmptyParts); } -void SimpleNetworkEditor::saveToNetworkInfo(NetworkInfo &networkInfo) { - _networkInfo.networkName = ui.networkNameEdit->text(); - networkInfo = _networkInfo; + +void SimpleNetworkEditor::setDefaultChannels(const QStringList &channels) +{ + ui.channelList->setPlainText(channels.join("\n")); } -QStringList SimpleNetworkEditor::defaultChannels() const { - return ui.channelList->toPlainText().split("\n", QString::SkipEmptyParts); + +void SimpleNetworkEditor::on_serverList_itemSelectionChanged() +{ + setWidgetStates(); } -void SimpleNetworkEditor::setDefaultChannels(const QStringList &channels) { - ui.channelList->setPlainText(channels.join("\n")); + +void SimpleNetworkEditor::on_addServer_clicked() +{ + ServerEditDlg dlg(Network::Server(), this); + if (dlg.exec() == QDialog::Accepted) { + _networkInfo.serverList.append(dlg.serverData()); + displayNetworkInfo(_networkInfo); + ui.serverList->setCurrentRow(ui.serverList->count() - 1); + emit widgetHasChanged(); + } } -void SimpleNetworkEditor::on_serverList_itemSelectionChanged() { - setWidgetStates(); + +void SimpleNetworkEditor::on_editServer_clicked() +{ + int cur = ui.serverList->currentRow(); + ServerEditDlg dlg(_networkInfo.serverList[cur], this); + if (dlg.exec() == QDialog::Accepted) { + _networkInfo.serverList[cur] = dlg.serverData(); + displayNetworkInfo(_networkInfo); + ui.serverList->setCurrentRow(cur); + emit widgetHasChanged(); + } } -void SimpleNetworkEditor::on_addServer_clicked() { - ServerEditDlg dlg(Network::Server(), this); - if(dlg.exec() == QDialog::Accepted) { - _networkInfo.serverList.append(dlg.serverData()); + +void SimpleNetworkEditor::on_deleteServer_clicked() +{ + int cur = ui.serverList->currentRow(); + _networkInfo.serverList.removeAt(cur); displayNetworkInfo(_networkInfo); - ui.serverList->setCurrentRow(ui.serverList->count() - 1); + ui.serverList->setCurrentRow(qMin(cur, ui.serverList->count() - 1)); emit widgetHasChanged(); - } } -void SimpleNetworkEditor::on_editServer_clicked() { - int cur = ui.serverList->currentRow(); - ServerEditDlg dlg(_networkInfo.serverList[cur], this); - if(dlg.exec() == QDialog::Accepted) { - _networkInfo.serverList[cur] = dlg.serverData(); + +void SimpleNetworkEditor::on_upServer_clicked() +{ + int cur = ui.serverList->currentRow(); + Network::Server server = _networkInfo.serverList.takeAt(cur); + _networkInfo.serverList.insert(cur - 1, server); displayNetworkInfo(_networkInfo); - ui.serverList->setCurrentRow(cur); + ui.serverList->setCurrentRow(cur - 1); emit widgetHasChanged(); - } -} - -void SimpleNetworkEditor::on_deleteServer_clicked() { - int cur = ui.serverList->currentRow(); - _networkInfo.serverList.removeAt(cur); - displayNetworkInfo(_networkInfo); - ui.serverList->setCurrentRow(qMin(cur, ui.serverList->count() - 1)); - emit widgetHasChanged(); } -void SimpleNetworkEditor::on_upServer_clicked() { - int cur = ui.serverList->currentRow(); - Network::Server server = _networkInfo.serverList.takeAt(cur); - _networkInfo.serverList.insert(cur - 1, server); - displayNetworkInfo(_networkInfo); - ui.serverList->setCurrentRow(cur - 1); - emit widgetHasChanged(); -} -void SimpleNetworkEditor::on_downServer_clicked() { - int cur = ui.serverList->currentRow(); - Network::Server server = _networkInfo.serverList.takeAt(cur); - _networkInfo.serverList.insert(cur + 1, server); - displayNetworkInfo(_networkInfo); - ui.serverList->setCurrentRow(cur + 1); - emit widgetHasChanged(); +void SimpleNetworkEditor::on_downServer_clicked() +{ + int cur = ui.serverList->currentRow(); + Network::Server server = _networkInfo.serverList.takeAt(cur); + _networkInfo.serverList.insert(cur + 1, server); + displayNetworkInfo(_networkInfo); + ui.serverList->setCurrentRow(cur + 1); + emit widgetHasChanged(); } diff --git a/src/qtui/simplenetworkeditor.h b/src/qtui/simplenetworkeditor.h index d4130609..055511b7 100644 --- a/src/qtui/simplenetworkeditor.h +++ b/src/qtui/simplenetworkeditor.h @@ -25,36 +25,38 @@ #include "network.h" -class SimpleNetworkEditor : public QWidget { - Q_OBJECT +class SimpleNetworkEditor : public QWidget +{ + Q_OBJECT public: - SimpleNetworkEditor(QWidget *parent = 0); + SimpleNetworkEditor(QWidget *parent = 0); - void displayNetworkInfo(const NetworkInfo &networkInfo); - void saveToNetworkInfo(NetworkInfo &networkInfo); + void displayNetworkInfo(const NetworkInfo &networkInfo); + void saveToNetworkInfo(NetworkInfo &networkInfo); - QStringList defaultChannels() const; - void setDefaultChannels(const QStringList &channels); + QStringList defaultChannels() const; + void setDefaultChannels(const QStringList &channels); signals: - void widgetHasChanged(); + void widgetHasChanged(); private slots: - // code duplication from settingspages/networkssettingspage.{h|cpp} - void on_serverList_itemSelectionChanged(); - void on_addServer_clicked(); - void on_deleteServer_clicked(); - void on_editServer_clicked(); - void on_upServer_clicked(); - void on_downServer_clicked(); + // code duplication from settingspages/networkssettingspage.{h|cpp} + void on_serverList_itemSelectionChanged(); + void on_addServer_clicked(); + void on_deleteServer_clicked(); + void on_editServer_clicked(); + void on_upServer_clicked(); + void on_downServer_clicked(); - void setWidgetStates(); + void setWidgetStates(); private: - Ui::SimpleNetworkEditor ui; + Ui::SimpleNetworkEditor ui; - NetworkInfo _networkInfo; + NetworkInfo _networkInfo; }; + #endif //SIMPLENETWORKEDITOR_H diff --git a/src/qtui/sslinfodlg.cpp b/src/qtui/sslinfodlg.cpp index b636f161..bb037605 100644 --- a/src/qtui/sslinfodlg.cpp +++ b/src/qtui/sslinfodlg.cpp @@ -31,51 +31,53 @@ // ======================================== SslInfoDlg::SslInfoDlg(const QSslSocket *socket, QWidget *parent) - : QDialog(parent), - _socket(socket) + : QDialog(parent), + _socket(socket) { - ui.setupUi(this); + ui.setupUi(this); - QSslCipher cipher = socket->sessionCipher(); + QSslCipher cipher = socket->sessionCipher(); - ui.hostname->setText(socket->peerName()); - ui.address->setText(socket->peerAddress().toString()); - ui.encryption->setText(cipher.name()); - ui.protocol->setText(cipher.protocolString()); + ui.hostname->setText(socket->peerName()); + ui.address->setText(socket->peerAddress().toString()); + ui.encryption->setText(cipher.name()); + ui.protocol->setText(cipher.protocolString()); - connect(ui.certificateChain, SIGNAL(currentIndexChanged(int)), SLOT(setCurrentCert(int))); - foreach(const QSslCertificate &cert, socket->peerCertificateChain()) { - ui.certificateChain->addItem(cert.subjectInfo(QSslCertificate::CommonName)); - } + connect(ui.certificateChain, SIGNAL(currentIndexChanged(int)), SLOT(setCurrentCert(int))); + foreach(const QSslCertificate &cert, socket->peerCertificateChain()) { + ui.certificateChain->addItem(cert.subjectInfo(QSslCertificate::CommonName)); + } } -void SslInfoDlg::setCurrentCert(int index) { - QSslCertificate cert = socket()->peerCertificateChain().at(index); - ui.subjectCommonName->setText(cert.subjectInfo(QSslCertificate::CommonName)); - ui.subjectOrganization->setText(cert.subjectInfo(QSslCertificate::Organization)); - ui.subjectOrganizationalUnit->setText(cert.subjectInfo(QSslCertificate::OrganizationalUnitName)); - ui.subjectCountry->setText(cert.subjectInfo(QSslCertificate::CountryName)); - ui.subjectState->setText(cert.subjectInfo(QSslCertificate::StateOrProvinceName)); - ui.subjectCity->setText(cert.subjectInfo(QSslCertificate::LocalityName)); - ui.issuerCommonName->setText(cert.issuerInfo(QSslCertificate::CommonName)); - ui.issuerOrganization->setText(cert.issuerInfo(QSslCertificate::Organization)); - ui.issuerOrganizationalUnit->setText(cert.issuerInfo(QSslCertificate::OrganizationalUnitName)); - ui.issuerCountry->setText(cert.issuerInfo(QSslCertificate::CountryName)); - ui.issuerState->setText(cert.issuerInfo(QSslCertificate::StateOrProvinceName)); - ui.issuerCity->setText(cert.issuerInfo(QSslCertificate::LocalityName)); +void SslInfoDlg::setCurrentCert(int index) +{ + QSslCertificate cert = socket()->peerCertificateChain().at(index); + ui.subjectCommonName->setText(cert.subjectInfo(QSslCertificate::CommonName)); + ui.subjectOrganization->setText(cert.subjectInfo(QSslCertificate::Organization)); + ui.subjectOrganizationalUnit->setText(cert.subjectInfo(QSslCertificate::OrganizationalUnitName)); + ui.subjectCountry->setText(cert.subjectInfo(QSslCertificate::CountryName)); + ui.subjectState->setText(cert.subjectInfo(QSslCertificate::StateOrProvinceName)); + ui.subjectCity->setText(cert.subjectInfo(QSslCertificate::LocalityName)); + + ui.issuerCommonName->setText(cert.issuerInfo(QSslCertificate::CommonName)); + ui.issuerOrganization->setText(cert.issuerInfo(QSslCertificate::Organization)); + ui.issuerOrganizationalUnit->setText(cert.issuerInfo(QSslCertificate::OrganizationalUnitName)); + ui.issuerCountry->setText(cert.issuerInfo(QSslCertificate::CountryName)); + ui.issuerState->setText(cert.issuerInfo(QSslCertificate::StateOrProvinceName)); + ui.issuerCity->setText(cert.issuerInfo(QSslCertificate::LocalityName)); - if(socket()->sslErrors().isEmpty()) - ui.trusted->setText(tr("Yes")); - else { - QString errorString = tr("No, for the following reasons:
    "); - foreach(const QSslError &error, socket()->sslErrors()) - errorString += "
  • " + error.errorString() + "
  • "; - errorString += "
"; - ui.trusted->setText(errorString); - } + if (socket()->sslErrors().isEmpty()) + ui.trusted->setText(tr("Yes")); + else { + QString errorString = tr("No, for the following reasons:
    "); + foreach(const QSslError &error, socket()->sslErrors()) + errorString += "
  • " + error.errorString() + "
  • "; + errorString += "
"; + ui.trusted->setText(errorString); + } - ui.validity->setText(tr("%1 to %2").arg(cert.effectiveDate().date().toString(Qt::ISODate), cert.expiryDate().date().toString(Qt::ISODate))); - ui.md5Digest->setText(prettyDigest(cert.digest(QCryptographicHash::Md5))); - ui.sha1Digest->setText(prettyDigest(cert.digest(QCryptographicHash::Sha1))); + ui.validity->setText(tr("%1 to %2").arg(cert.effectiveDate().date().toString(Qt::ISODate), cert.expiryDate().date().toString(Qt::ISODate))); + ui.md5Digest->setText(prettyDigest(cert.digest(QCryptographicHash::Md5))); + ui.sha1Digest->setText(prettyDigest(cert.digest(QCryptographicHash::Sha1))); } diff --git a/src/qtui/sslinfodlg.h b/src/qtui/sslinfodlg.h index d7660215..1fcd3387 100644 --- a/src/qtui/sslinfodlg.h +++ b/src/qtui/sslinfodlg.h @@ -33,19 +33,21 @@ class QSslSocket; class QSslCertificate; -class SslInfoDlg : public QDialog { - Q_OBJECT +class SslInfoDlg : public QDialog +{ + Q_OBJECT public: - SslInfoDlg(const QSslSocket *socket, QWidget *parent = 0); - inline const QSslSocket *socket() const { return _socket; } + SslInfoDlg(const QSslSocket *socket, QWidget *parent = 0); + inline const QSslSocket *socket() const { return _socket; } private slots: - void setCurrentCert(int index); + void setCurrentCert(int index); private: - Ui::SslInfoDlg ui; - const QSslSocket *_socket; + Ui::SslInfoDlg ui; + const QSslSocket *_socket; }; + #endif diff --git a/src/qtui/statusnotifieritem.cpp b/src/qtui/statusnotifieritem.cpp index 841f0cf5..ecfe5646 100644 --- a/src/qtui/statusnotifieritem.cpp +++ b/src/qtui/statusnotifieritem.cpp @@ -41,274 +41,323 @@ const QString StatusNotifierItem::_statusNotifierWatcherServiceName("org.kde.Sta /** * Specialization to provide access to icon names */ -class QuasselDBusMenuExporter : public DBusMenuExporter { +class QuasselDBusMenuExporter : public DBusMenuExporter +{ public: - QuasselDBusMenuExporter(const QString &dbusObjectPath, QMenu *menu, const QDBusConnection &dbusConnection) - : DBusMenuExporter(dbusObjectPath, menu, dbusConnection) - {} + QuasselDBusMenuExporter(const QString &dbusObjectPath, QMenu *menu, const QDBusConnection &dbusConnection) + : DBusMenuExporter(dbusObjectPath, menu, dbusConnection) + {} protected: - virtual QString iconNameForAction(QAction *action) { // TODO Qt 4.7: fixme when we have converted our iconloader - Icon icon(action->icon()); + virtual QString iconNameForAction(QAction *action) // TODO Qt 4.7: fixme when we have converted our iconloader + { + Icon icon(action->icon()); #if QT_VERSION >= 0x040701 - // QIcon::name() is in the 4.7 git branch, but it is not in 4.7 TP. - // If you get a build error here, you need to update your pre-release - // of Qt 4.7. - return icon.isNull() ? QString() : icon.name(); + // QIcon::name() is in the 4.7 git branch, but it is not in 4.7 TP. + // If you get a build error here, you need to update your pre-release + // of Qt 4.7. + return icon.isNull() ? QString() : icon.name(); #else - return QString(); + return QString(); #endif - } + } }; + #endif /* HAVE_DBUSMENU */ StatusNotifierItem::StatusNotifierItem(QWidget *parent) - : StatusNotifierItemParent(parent), - _statusNotifierItemDBus(0), - _statusNotifierWatcher(0), - _notificationsClient(0), - _notificationsClientSupportsMarkup(true), - _lastNotificationsDBusId(0) + : StatusNotifierItemParent(parent), + _statusNotifierItemDBus(0), + _statusNotifierWatcher(0), + _notificationsClient(0), + _notificationsClientSupportsMarkup(true), + _lastNotificationsDBusId(0) { - } -StatusNotifierItem::~StatusNotifierItem() { - delete _statusNotifierWatcher; + +StatusNotifierItem::~StatusNotifierItem() +{ + delete _statusNotifierWatcher; } -void StatusNotifierItem::init() { - qDBusRegisterMetaType(); - qDBusRegisterMetaType(); - qDBusRegisterMetaType(); - _statusNotifierItemDBus = new StatusNotifierItemDBus(this); +void StatusNotifierItem::init() +{ + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); - connect(this, SIGNAL(toolTipChanged(QString,QString)), _statusNotifierItemDBus, SIGNAL(NewToolTip())); - connect(this, SIGNAL(animationEnabledChanged(bool)), _statusNotifierItemDBus, SIGNAL(NewAttentionIcon())); + _statusNotifierItemDBus = new StatusNotifierItemDBus(this); - QDBusServiceWatcher *watcher = new QDBusServiceWatcher(_statusNotifierWatcherServiceName, - QDBusConnection::sessionBus(), - QDBusServiceWatcher::WatchForOwnerChange, - this); - connect(watcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)), SLOT(serviceChange(QString,QString,QString))); + connect(this, SIGNAL(toolTipChanged(QString, QString)), _statusNotifierItemDBus, SIGNAL(NewToolTip())); + connect(this, SIGNAL(animationEnabledChanged(bool)), _statusNotifierItemDBus, SIGNAL(NewAttentionIcon())); - setMode(StatusNotifier); + QDBusServiceWatcher *watcher = new QDBusServiceWatcher(_statusNotifierWatcherServiceName, + QDBusConnection::sessionBus(), + QDBusServiceWatcher::WatchForOwnerChange, + this); + connect(watcher, SIGNAL(serviceOwnerChanged(QString, QString, QString)), SLOT(serviceChange(QString, QString, QString))); - _notificationsClient = new org::freedesktop::Notifications("org.freedesktop.Notifications", "/org/freedesktop/Notifications", - QDBusConnection::sessionBus(), this); + setMode(StatusNotifier); - connect(_notificationsClient, SIGNAL(NotificationClosed(uint,uint)), SLOT(notificationClosed(uint,uint))); - connect(_notificationsClient, SIGNAL(ActionInvoked(uint,QString)), SLOT(notificationInvoked(uint,QString))); + _notificationsClient = new org::freedesktop::Notifications("org.freedesktop.Notifications", "/org/freedesktop/Notifications", + QDBusConnection::sessionBus(), this); - if(_notificationsClient->isValid()) { - QStringList desktopCapabilities = _notificationsClient->GetCapabilities(); - _notificationsClientSupportsMarkup = desktopCapabilities.contains("body-markup"); - _notificationsClientSupportsActions = desktopCapabilities.contains("actions"); - } + connect(_notificationsClient, SIGNAL(NotificationClosed(uint, uint)), SLOT(notificationClosed(uint, uint))); + connect(_notificationsClient, SIGNAL(ActionInvoked(uint, QString)), SLOT(notificationInvoked(uint, QString))); - StatusNotifierItemParent::init(); - trayMenu()->installEventFilter(this); + if (_notificationsClient->isValid()) { + QStringList desktopCapabilities = _notificationsClient->GetCapabilities(); + _notificationsClientSupportsMarkup = desktopCapabilities.contains("body-markup"); + _notificationsClientSupportsActions = desktopCapabilities.contains("actions"); + } + + StatusNotifierItemParent::init(); + trayMenu()->installEventFilter(this); - // use the appdata icon folder for now - _iconThemePath = Quassel::findDataFilePath("icons"); + // use the appdata icon folder for now + _iconThemePath = Quassel::findDataFilePath("icons"); #ifdef HAVE_DBUSMENU - _menuObjectPath = "/MenuBar"; - new QuasselDBusMenuExporter(menuObjectPath(), trayMenu(), _statusNotifierItemDBus->dbusConnection()); // will be added as menu child + _menuObjectPath = "/MenuBar"; + new QuasselDBusMenuExporter(menuObjectPath(), trayMenu(), _statusNotifierItemDBus->dbusConnection()); // will be added as menu child #endif } -void StatusNotifierItem::registerToDaemon() { - if(!_statusNotifierWatcher) { - _statusNotifierWatcher = new org::kde::StatusNotifierWatcher(_statusNotifierWatcherServiceName, - "/StatusNotifierWatcher", - QDBusConnection::sessionBus()); - connect(_statusNotifierWatcher, SIGNAL(StatusNotifierHostRegistered()), SLOT(checkForRegisteredHosts())); - connect(_statusNotifierWatcher, SIGNAL(StatusNotifierHostUnregistered()), SLOT(checkForRegisteredHosts())); - } - if(_statusNotifierWatcher->isValid() - && _statusNotifierWatcher->property("ProtocolVersion").toInt() == _protocolVersion) { - - _statusNotifierWatcher->RegisterStatusNotifierItem(_statusNotifierItemDBus->service()); - checkForRegisteredHosts(); - - } else { - //qDebug() << "StatusNotifierWatcher not reachable!"; - setMode(Legacy); - } + +void StatusNotifierItem::registerToDaemon() +{ + if (!_statusNotifierWatcher) { + _statusNotifierWatcher = new org::kde::StatusNotifierWatcher(_statusNotifierWatcherServiceName, + "/StatusNotifierWatcher", + QDBusConnection::sessionBus()); + connect(_statusNotifierWatcher, SIGNAL(StatusNotifierHostRegistered()), SLOT(checkForRegisteredHosts())); + connect(_statusNotifierWatcher, SIGNAL(StatusNotifierHostUnregistered()), SLOT(checkForRegisteredHosts())); + } + if (_statusNotifierWatcher->isValid() + && _statusNotifierWatcher->property("ProtocolVersion").toInt() == _protocolVersion) { + _statusNotifierWatcher->RegisterStatusNotifierItem(_statusNotifierItemDBus->service()); + checkForRegisteredHosts(); + } + else { + //qDebug() << "StatusNotifierWatcher not reachable!"; + setMode(Legacy); + } } -void StatusNotifierItem::serviceChange(const QString& name, const QString& oldOwner, const QString& newOwner) { - Q_UNUSED(name); - if(newOwner.isEmpty()) { - //unregistered - //qDebug() << "Connection to the StatusNotifierWatcher lost"; - delete _statusNotifierWatcher; - _statusNotifierWatcher = 0; - setMode(Legacy); - } else if(oldOwner.isEmpty()) { - //registered - setMode(StatusNotifier); - } + +void StatusNotifierItem::serviceChange(const QString &name, const QString &oldOwner, const QString &newOwner) +{ + Q_UNUSED(name); + if (newOwner.isEmpty()) { + //unregistered + //qDebug() << "Connection to the StatusNotifierWatcher lost"; + delete _statusNotifierWatcher; + _statusNotifierWatcher = 0; + setMode(Legacy); + } + else if (oldOwner.isEmpty()) { + //registered + setMode(StatusNotifier); + } } -void StatusNotifierItem::checkForRegisteredHosts() { - if(!_statusNotifierWatcher || !_statusNotifierWatcher->property("IsStatusNotifierHostRegistered").toBool()) - setMode(Legacy); - else - setMode(StatusNotifier); + +void StatusNotifierItem::checkForRegisteredHosts() +{ + if (!_statusNotifierWatcher || !_statusNotifierWatcher->property("IsStatusNotifierHostRegistered").toBool()) + setMode(Legacy); + else + setMode(StatusNotifier); } -bool StatusNotifierItem::isSystemTrayAvailable() const { - if(mode() == StatusNotifier) - return true; // else it should be set to legacy on registration - return StatusNotifierItemParent::isSystemTrayAvailable(); +bool StatusNotifierItem::isSystemTrayAvailable() const +{ + if (mode() == StatusNotifier) + return true; // else it should be set to legacy on registration + + return StatusNotifierItemParent::isSystemTrayAvailable(); } -bool StatusNotifierItem::isVisible() const { - if(mode() == StatusNotifier) - return shouldBeVisible(); // we don't have a way to check, so we need to trust everything went right - return StatusNotifierItemParent::isVisible(); +bool StatusNotifierItem::isVisible() const +{ + if (mode() == StatusNotifier) + return shouldBeVisible(); // we don't have a way to check, so we need to trust everything went right + + return StatusNotifierItemParent::isVisible(); } -void StatusNotifierItem::setMode(Mode mode_) { - if(mode_ == mode()) - return; - if(mode_ != StatusNotifier) { - _statusNotifierItemDBus->unregisterService(); - } +void StatusNotifierItem::setMode(Mode mode_) +{ + if (mode_ == mode()) + return; + + if (mode_ != StatusNotifier) { + _statusNotifierItemDBus->unregisterService(); + } - StatusNotifierItemParent::setMode(mode_); + StatusNotifierItemParent::setMode(mode_); - if(mode() == StatusNotifier) { - _statusNotifierItemDBus->registerService(); - registerToDaemon(); - } + if (mode() == StatusNotifier) { + _statusNotifierItemDBus->registerService(); + registerToDaemon(); + } } -void StatusNotifierItem::setState(State state_) { - StatusNotifierItemParent::setState(state_); - emit _statusNotifierItemDBus->NewStatus(metaObject()->enumerator(metaObject()->indexOfEnumerator("State")).valueToKey(state())); - emit _statusNotifierItemDBus->NewIcon(); -} +void StatusNotifierItem::setState(State state_) +{ + StatusNotifierItemParent::setState(state_); -void StatusNotifierItem::setVisible(bool visible) { - if(visible == isVisible()) - return; + emit _statusNotifierItemDBus->NewStatus(metaObject()->enumerator(metaObject()->indexOfEnumerator("State")).valueToKey(state())); + emit _statusNotifierItemDBus->NewIcon(); +} - LegacySystemTray::setVisible(visible); - if(mode() == StatusNotifier) { - if(shouldBeVisible()) { - _statusNotifierItemDBus->registerService(); - registerToDaemon(); - } else { - _statusNotifierItemDBus->unregisterService(); - _statusNotifierWatcher->deleteLater(); - _statusNotifierWatcher = 0; +void StatusNotifierItem::setVisible(bool visible) +{ + if (visible == isVisible()) + return; + + LegacySystemTray::setVisible(visible); + + if (mode() == StatusNotifier) { + if (shouldBeVisible()) { + _statusNotifierItemDBus->registerService(); + registerToDaemon(); + } + else { + _statusNotifierItemDBus->unregisterService(); + _statusNotifierWatcher->deleteLater(); + _statusNotifierWatcher = 0; + } } - } } -QString StatusNotifierItem::title() const { - return QString("Quassel IRC"); + +QString StatusNotifierItem::title() const +{ + return QString("Quassel IRC"); } -QString StatusNotifierItem::iconName() const { - if(state() == Passive) - return QString("quassel-inactive"); - else - return QString("quassel"); + +QString StatusNotifierItem::iconName() const +{ + if (state() == Passive) + return QString("quassel-inactive"); + else + return QString("quassel"); } -QString StatusNotifierItem::attentionIconName() const { - if(animationEnabled()) - return QString("quassel-message"); - else - return QString("quassel"); + +QString StatusNotifierItem::attentionIconName() const +{ + if (animationEnabled()) + return QString("quassel-message"); + else + return QString("quassel"); } -QString StatusNotifierItem::toolTipIconName() const { - return QString("quassel"); + +QString StatusNotifierItem::toolTipIconName() const +{ + return QString("quassel"); } -QString StatusNotifierItem::iconThemePath() const { - return _iconThemePath; + +QString StatusNotifierItem::iconThemePath() const +{ + return _iconThemePath; } -QString StatusNotifierItem::menuObjectPath() const { - return _menuObjectPath; + +QString StatusNotifierItem::menuObjectPath() const +{ + return _menuObjectPath; } -void StatusNotifierItem::activated(const QPoint &pos) { - Q_UNUSED(pos) - activate(Trigger); + +void StatusNotifierItem::activated(const QPoint &pos) +{ + Q_UNUSED(pos) + activate(Trigger); } -bool StatusNotifierItem::eventFilter(QObject *watched, QEvent *event) { - if(mode() == StatusNotifier) { - //FIXME: ugly ugly workaround to weird QMenu's focus problems + +bool StatusNotifierItem::eventFilter(QObject *watched, QEvent *event) +{ + if (mode() == StatusNotifier) { + //FIXME: ugly ugly workaround to weird QMenu's focus problems #ifdef HAVE_KDE - if(watched == trayMenu() && - (event->type() == QEvent::WindowDeactivate || (event->type() == QEvent::MouseButtonRelease && static_cast(event)->button() == Qt::LeftButton))) { - // put at the back of event queue to let the action activate anyways - QTimer::singleShot(0, trayMenu(), SLOT(hide())); - } + if (watched == trayMenu() && + (event->type() == QEvent::WindowDeactivate || (event->type() == QEvent::MouseButtonRelease && static_cast(event)->button() == Qt::LeftButton))) { + // put at the back of event queue to let the action activate anyways + QTimer::singleShot(0, trayMenu(), SLOT(hide())); + } #else - if(watched == trayMenu() && event->type() == QEvent::HoverLeave) { - trayMenu()->hide(); - } + if (watched == trayMenu() && event->type() == QEvent::HoverLeave) { + trayMenu()->hide(); + } #endif - } - return StatusNotifierItemParent::eventFilter(watched, event); + } + return StatusNotifierItemParent::eventFilter(watched, event); } -void StatusNotifierItem::showMessage(const QString &title, const QString &message_, SystemTray::MessageIcon icon, int timeout, uint notificationId) { - QString message = message_; - if(_notificationsClient->isValid()) { - if(_notificationsClientSupportsMarkup) - message = Qt::escape(message); - - QStringList actions; - if(_notificationsClientSupportsActions) - actions << "activate" << "View"; - - // we always queue notifications right now - QDBusReply reply = _notificationsClient->Notify(title, 0, "quassel", title, message, actions, QVariantMap(), timeout); - if(reply.isValid()) { - uint dbusid = reply.value(); - _notificationsIdMap.insert(dbusid, notificationId); - _lastNotificationsDBusId = dbusid; + +void StatusNotifierItem::showMessage(const QString &title, const QString &message_, SystemTray::MessageIcon icon, int timeout, uint notificationId) +{ + QString message = message_; + if (_notificationsClient->isValid()) { + if (_notificationsClientSupportsMarkup) + message = Qt::escape(message); + + QStringList actions; + if (_notificationsClientSupportsActions) + actions << "activate" << "View"; + + // we always queue notifications right now + QDBusReply reply = _notificationsClient->Notify(title, 0, "quassel", title, message, actions, QVariantMap(), timeout); + if (reply.isValid()) { + uint dbusid = reply.value(); + _notificationsIdMap.insert(dbusid, notificationId); + _lastNotificationsDBusId = dbusid; + } } - } else - StatusNotifierItemParent::showMessage(title, message, icon, timeout, notificationId); + else + StatusNotifierItemParent::showMessage(title, message, icon, timeout, notificationId); } -void StatusNotifierItem::closeMessage(uint notificationId) { - foreach(uint dbusid, _notificationsIdMap.keys()) { - if(_notificationsIdMap.value(dbusid) == notificationId) { - _notificationsIdMap.remove(dbusid); - _notificationsClient->CloseNotification(dbusid); + +void StatusNotifierItem::closeMessage(uint notificationId) +{ + foreach(uint dbusid, _notificationsIdMap.keys()) { + if (_notificationsIdMap.value(dbusid) == notificationId) { + _notificationsIdMap.remove(dbusid); + _notificationsClient->CloseNotification(dbusid); + } } - } - _lastNotificationsDBusId = 0; + _lastNotificationsDBusId = 0; } -void StatusNotifierItem::notificationClosed(uint dbusid, uint reason) { - Q_UNUSED(reason) - _lastNotificationsDBusId = 0; - emit messageClosed(_notificationsIdMap.take(dbusid)); + +void StatusNotifierItem::notificationClosed(uint dbusid, uint reason) +{ + Q_UNUSED(reason) + _lastNotificationsDBusId = 0; + emit messageClosed(_notificationsIdMap.take(dbusid)); } -void StatusNotifierItem::notificationInvoked(uint dbusid, const QString &action) { - Q_UNUSED(action) - emit messageClicked(_notificationsIdMap.value(dbusid, 0)); + +void StatusNotifierItem::notificationInvoked(uint dbusid, const QString &action) +{ + Q_UNUSED(action) + emit messageClicked(_notificationsIdMap.value(dbusid, 0)); } + #endif diff --git a/src/qtui/statusnotifieritem.h b/src/qtui/statusnotifieritem.h index fc774cfd..4a312018 100644 --- a/src/qtui/statusnotifieritem.h +++ b/src/qtui/statusnotifieritem.h @@ -39,62 +39,64 @@ class StatusNotifierItemDBus; -class StatusNotifierItem : public StatusNotifierItemParent { - Q_OBJECT +class StatusNotifierItem : public StatusNotifierItemParent +{ + Q_OBJECT public: - explicit StatusNotifierItem(QWidget *parent); - virtual ~StatusNotifierItem(); + explicit StatusNotifierItem(QWidget *parent); + virtual ~StatusNotifierItem(); - virtual bool isSystemTrayAvailable() const; - virtual bool isVisible() const; + virtual bool isSystemTrayAvailable() const; + virtual bool isVisible() const; public slots: - virtual void setState(State state); - virtual void setVisible(bool visible); - virtual void showMessage(const QString &title, const QString &message, MessageIcon icon = Information, int msTimeout = 10000, uint notificationId = 0); - virtual void closeMessage(uint notificationId); + virtual void setState(State state); + virtual void setVisible(bool visible); + virtual void showMessage(const QString &title, const QString &message, MessageIcon icon = Information, int msTimeout = 10000, uint notificationId = 0); + virtual void closeMessage(uint notificationId); protected: - virtual void init(); - virtual void setMode(Mode mode); + virtual void init(); + virtual void setMode(Mode mode); - QString title() const; - QString iconName() const; - QString attentionIconName() const; - QString toolTipIconName() const; - QString iconThemePath() const; - QString menuObjectPath() const; + QString title() const; + QString iconName() const; + QString attentionIconName() const; + QString toolTipIconName() const; + QString iconThemePath() const; + QString menuObjectPath() const; - virtual bool eventFilter(QObject *watched, QEvent *event); + virtual bool eventFilter(QObject *watched, QEvent *event); private slots: - void activated(const QPoint &pos); - void serviceChange(const QString& name, const QString& oldOwner, const QString& newOwner); - void checkForRegisteredHosts(); + void activated(const QPoint &pos); + void serviceChange(const QString &name, const QString &oldOwner, const QString &newOwner); + void checkForRegisteredHosts(); - void notificationClosed(uint id, uint reason); - void notificationInvoked(uint id, const QString &action); + void notificationClosed(uint id, uint reason); + void notificationInvoked(uint id, const QString &action); private: - void registerToDaemon(); + void registerToDaemon(); - static const int _protocolVersion; - static const QString _statusNotifierWatcherServiceName; - StatusNotifierItemDBus *_statusNotifierItemDBus; + static const int _protocolVersion; + static const QString _statusNotifierWatcherServiceName; + StatusNotifierItemDBus *_statusNotifierItemDBus; - org::kde::StatusNotifierWatcher *_statusNotifierWatcher; - org::freedesktop::Notifications *_notificationsClient; - bool _notificationsClientSupportsMarkup; - bool _notificationsClientSupportsActions; - quint32 _lastNotificationsDBusId; - QHash _notificationsIdMap; ///< Maps our own notification ID to the D-Bus one + org::kde::StatusNotifierWatcher *_statusNotifierWatcher; + org::freedesktop::Notifications *_notificationsClient; + bool _notificationsClientSupportsMarkup; + bool _notificationsClientSupportsActions; + quint32 _lastNotificationsDBusId; + QHash _notificationsIdMap; ///< Maps our own notification ID to the D-Bus one - QString _iconThemePath; - QString _menuObjectPath; + QString _iconThemePath; + QString _menuObjectPath; - friend class StatusNotifierItemDBus; + friend class StatusNotifierItemDBus; }; + #endif /* HAVE_DBUS */ #endif /* STATUSNOTIFIERITEM_H_ */ diff --git a/src/qtui/statusnotifieritemdbus.cpp b/src/qtui/statusnotifieritemdbus.cpp index 893b24dd..a52566eb 100644 --- a/src/qtui/statusnotifieritemdbus.cpp +++ b/src/qtui/statusnotifieritemdbus.cpp @@ -42,14 +42,17 @@ #ifdef Q_OS_WIN64 __inline int toInt(WId wid) { - return (int)((__int64)wid); + return (int)((__int64)wid); } + #else __inline int toInt(WId wid) { - return (int)wid; + return (int)wid; } + + #endif // Marshall the ImageStruct data into a D-BUS argument @@ -63,6 +66,7 @@ const QDBusArgument &operator<<(QDBusArgument &argument, const DBusImageStruct & return argument; } + // Retrieve the ImageStruct data from the D-BUS argument const QDBusArgument &operator>>(const QDBusArgument &argument, DBusImageStruct &icon) { @@ -88,31 +92,32 @@ const QDBusArgument &operator>>(const QDBusArgument &argument, DBusImageStruct & const QDBusArgument &operator<<(QDBusArgument &argument, const DBusImageVector &iconVector) { argument.beginArray(qMetaTypeId()); - for (int i=0; i>(const QDBusArgument &argument, DBusImageVector &iconVector) { argument.beginArray(); iconVector.clear(); - while ( !argument.atEnd() ) { - DBusImageStruct element; - argument >> element; - iconVector.append(element); + while (!argument.atEnd()) { + DBusImageStruct element; + argument >> element; + iconVector.append(element); } argument.endArray(); - return argument; } + // Marshall the ToolTipStruct data into a D-BUS argument const QDBusArgument &operator<<(QDBusArgument &argument, const DBusToolTipStruct &toolTip) { @@ -125,6 +130,7 @@ const QDBusArgument &operator<<(QDBusArgument &argument, const DBusToolTipStruct return argument; } + // Retrieve the ToolTipStruct data from the D-BUS argument const QDBusArgument &operator>>(const QDBusArgument &argument, DBusToolTipStruct &toolTip) { @@ -152,28 +158,31 @@ const QDBusArgument &operator>>(const QDBusArgument &argument, DBusToolTipStruct int StatusNotifierItemDBus::s_serviceCount = 0; StatusNotifierItemDBus::StatusNotifierItemDBus(StatusNotifierItem *parent) - : QObject(parent), + : QObject(parent), m_statusNotifierItem(parent), m_service(QString("org.kde.StatusNotifierItem-%1-%2") - .arg(QCoreApplication::applicationPid()) - .arg(++s_serviceCount)), + .arg(QCoreApplication::applicationPid()) + .arg(++s_serviceCount)), m_dbus(QDBusConnection::connectToBus(QDBusConnection::SessionBus, m_service)) { - new StatusNotifierItemAdaptor(this); - //qDebug() << "service is" << m_service; - registerService(); + new StatusNotifierItemAdaptor(this); + //qDebug() << "service is" << m_service; + registerService(); } + StatusNotifierItemDBus::~StatusNotifierItemDBus() { unregisterService(); } + QDBusConnection StatusNotifierItemDBus::dbusConnection() const { return m_dbus; } + // FIXME: prevent double registrations, also test this on platforms != KDE // void StatusNotifierItemDBus::registerService() @@ -183,21 +192,24 @@ void StatusNotifierItemDBus::registerService() m_dbus.registerObject("/StatusNotifierItem", this); } + // FIXME: see above void StatusNotifierItemDBus::unregisterService() { //qDebug() << "unregistering from" << m_service; - if(m_dbus.isConnected()) { + if (m_dbus.isConnected()) { m_dbus.unregisterObject("/StatusNotifierItem"); m_dbus.unregisterService(m_service); } } + QString StatusNotifierItemDBus::service() const { return m_service; } + //DBUS slots //Values and calls have been adapted to Quassel @@ -206,21 +218,25 @@ QString StatusNotifierItemDBus::Category() const return QString("Communications"); // no need to make this configurable for Quassel } + QString StatusNotifierItemDBus::Title() const { return m_statusNotifierItem->title(); } + QString StatusNotifierItemDBus::Id() const { return QString("QuasselIRC"); } + QString StatusNotifierItemDBus::Status() const { return m_statusNotifierItem->metaObject()->enumerator(m_statusNotifierItem->metaObject()->indexOfEnumerator("State")).valueToKey(m_statusNotifierItem->state()); } + int StatusNotifierItemDBus::WindowId() const { return toInt(QtUi::mainWindow()->winId()); @@ -235,21 +251,25 @@ QString StatusNotifierItemDBus::IconName() const return m_statusNotifierItem->iconName(); } + DBusImageVector StatusNotifierItemDBus::IconPixmap() const { return DBusImageVector(); } + QString StatusNotifierItemDBus::OverlayIconName() const { return QString(); } + DBusImageVector StatusNotifierItemDBus::OverlayIconPixmap() const { return DBusImageVector(); } + //Requesting attention icon and movie QString StatusNotifierItemDBus::AttentionIconName() const @@ -257,11 +277,13 @@ QString StatusNotifierItemDBus::AttentionIconName() const return m_statusNotifierItem->attentionIconName(); } + DBusImageVector StatusNotifierItemDBus::AttentionIconPixmap() const { return DBusImageVector(); } + QString StatusNotifierItemDBus::AttentionMovieName() const { return QString(); @@ -281,11 +303,13 @@ DBusToolTipStruct StatusNotifierItemDBus::ToolTip() const return toolTip; } + QString StatusNotifierItemDBus::IconThemePath() const { return m_statusNotifierItem->iconThemePath(); } + //Menu QDBusObjectPath StatusNotifierItemDBus::Menu() const @@ -307,22 +331,25 @@ void StatusNotifierItemDBus::ContextMenu(int x, int y) #ifdef HAVE_KDE m_statusNotifierItem->trayMenu()->setWindowFlags(Qt::Window|Qt::FramelessWindowHint); #endif - m_statusNotifierItem->trayMenu()->popup(QPoint(x,y)); + m_statusNotifierItem->trayMenu()->popup(QPoint(x, y)); #ifdef HAVE_KDE KWindowSystem::setState(m_statusNotifierItem->trayMenu()->winId(), NET::SkipTaskbar|NET::SkipPager|NET::KeepAbove); KWindowSystem::setType(m_statusNotifierItem->trayMenu()->winId(), NET::PopupMenu); KWindowSystem::forceActiveWindow(m_statusNotifierItem->trayMenu()->winId()); #endif - } else { + } + else { m_statusNotifierItem->trayMenu()->hide(); } } + void StatusNotifierItemDBus::Activate(int x, int y) { - m_statusNotifierItem->activated(QPoint(x,y)); + m_statusNotifierItem->activated(QPoint(x, y)); } + void StatusNotifierItemDBus::SecondaryActivate(int x, int y) { Q_UNUSED(x) @@ -330,6 +357,7 @@ void StatusNotifierItemDBus::SecondaryActivate(int x, int y) // emit m_statusNotifierItem->secondaryActivateRequested(QPoint(x,y)); } + void StatusNotifierItemDBus::Scroll(int delta, const QString &orientation) { Q_UNUSED(delta) diff --git a/src/qtui/systemtray.cpp b/src/qtui/systemtray.cpp index 0bafd5e4..642f7942 100644 --- a/src/qtui/systemtray.cpp +++ b/src/qtui/systemtray.cpp @@ -35,136 +35,167 @@ #endif SystemTray::SystemTray(QWidget *parent) -: QObject(parent), - _mode(Invalid), - _state(Passive), - _shouldBeVisible(true), - _passiveIcon(DesktopIcon("quassel-inactive")), - _activeIcon(DesktopIcon("quassel")), - _needsAttentionIcon(DesktopIcon("quassel-message")), - _trayMenu(0), - _associatedWidget(parent) + : QObject(parent), + _mode(Invalid), + _state(Passive), + _shouldBeVisible(true), + _passiveIcon(DesktopIcon("quassel-inactive")), + _activeIcon(DesktopIcon("quassel")), + _needsAttentionIcon(DesktopIcon("quassel-message")), + _trayMenu(0), + _associatedWidget(parent) { - Q_ASSERT(parent); + Q_ASSERT(parent); } -SystemTray::~SystemTray() { - _trayMenu->deleteLater(); + +SystemTray::~SystemTray() +{ + _trayMenu->deleteLater(); } -QWidget *SystemTray::associatedWidget() const { - return _associatedWidget; + +QWidget *SystemTray::associatedWidget() const +{ + return _associatedWidget; } -void SystemTray::init() { - ActionCollection *coll = QtUi::actionCollection("General"); - _minimizeRestoreAction = new Action(tr("&Minimize"), this, this, SLOT(minimizeRestore())); + +void SystemTray::init() +{ + ActionCollection *coll = QtUi::actionCollection("General"); + _minimizeRestoreAction = new Action(tr("&Minimize"), this, this, SLOT(minimizeRestore())); #ifdef HAVE_KDE - KMenu *kmenu; - _trayMenu = kmenu = new KMenu(); - kmenu->addTitle(_activeIcon, "Quassel IRC"); + KMenu *kmenu; + _trayMenu = kmenu = new KMenu(); + kmenu->addTitle(_activeIcon, "Quassel IRC"); #else - _trayMenu = new QMenu(associatedWidget()); + _trayMenu = new QMenu(associatedWidget()); #endif - _trayMenu->setTitle("Quassel IRC"); + _trayMenu->setTitle("Quassel IRC"); #ifndef HAVE_KDE - _trayMenu->setAttribute(Qt::WA_Hover); + _trayMenu->setAttribute(Qt::WA_Hover); #endif - _trayMenu->addAction(coll->action("ConnectCore")); - _trayMenu->addAction(coll->action("DisconnectCore")); - _trayMenu->addAction(coll->action("CoreInfo")); - _trayMenu->addSeparator(); - _trayMenu->addAction(_minimizeRestoreAction); - _trayMenu->addAction(coll->action("Quit")); + _trayMenu->addAction(coll->action("ConnectCore")); + _trayMenu->addAction(coll->action("DisconnectCore")); + _trayMenu->addAction(coll->action("CoreInfo")); + _trayMenu->addSeparator(); + _trayMenu->addAction(_minimizeRestoreAction); + _trayMenu->addAction(coll->action("Quit")); - connect(_trayMenu, SIGNAL(aboutToShow()), SLOT(trayMenuAboutToShow())); + connect(_trayMenu, SIGNAL(aboutToShow()), SLOT(trayMenuAboutToShow())); - NotificationSettings notificationSettings; - notificationSettings.initAndNotify("Systray/Animate", this, SLOT(enableAnimationChanged(QVariant)), true); + NotificationSettings notificationSettings; + notificationSettings.initAndNotify("Systray/Animate", this, SLOT(enableAnimationChanged(QVariant)), true); } -void SystemTray::trayMenuAboutToShow() { - if(GraphicalUi::isMainWidgetVisible()) - _minimizeRestoreAction->setText(tr("&Minimize")); - else - _minimizeRestoreAction->setText(tr("&Restore")); + +void SystemTray::trayMenuAboutToShow() +{ + if (GraphicalUi::isMainWidgetVisible()) + _minimizeRestoreAction->setText(tr("&Minimize")); + else + _minimizeRestoreAction->setText(tr("&Restore")); } -void SystemTray::setMode(Mode mode_) { - if(mode_ != _mode) { - _mode = mode_; + +void SystemTray::setMode(Mode mode_) +{ + if (mode_ != _mode) { + _mode = mode_; #ifdef HAVE_KDE - if(_trayMenu) { - if(_mode == Legacy) { - _trayMenu->setWindowFlags(Qt::Popup); - } else { - _trayMenu->setWindowFlags(Qt::Window); - } - } + if (_trayMenu) { + if (_mode == Legacy) { + _trayMenu->setWindowFlags(Qt::Popup); + } + else { + _trayMenu->setWindowFlags(Qt::Window); + } + } #endif - } + } } -Icon SystemTray::stateIcon() const { - return stateIcon(state()); + +Icon SystemTray::stateIcon() const +{ + return stateIcon(state()); } -Icon SystemTray::stateIcon(State state) const { - switch(state) { - case Passive: - return _passiveIcon; - case Active: - return _activeIcon; - case NeedsAttention: - return _needsAttentionIcon; - } - return Icon(); + +Icon SystemTray::stateIcon(State state) const +{ + switch (state) { + case Passive: + return _passiveIcon; + case Active: + return _activeIcon; + case NeedsAttention: + return _needsAttentionIcon; + } + return Icon(); } -void SystemTray::setState(State state) { - if(_state != state) { - _state = state; - } + +void SystemTray::setState(State state) +{ + if (_state != state) { + _state = state; + } } -void SystemTray::setAlert(bool alerted) { - if(alerted) - setState(NeedsAttention); - else - setState(Client::isConnected() ? Active : Passive); + +void SystemTray::setAlert(bool alerted) +{ + if (alerted) + setState(NeedsAttention); + else + setState(Client::isConnected() ? Active : Passive); } -void SystemTray::setVisible(bool visible) { - _shouldBeVisible = visible; + +void SystemTray::setVisible(bool visible) +{ + _shouldBeVisible = visible; } -void SystemTray::setToolTip(const QString &title, const QString &subtitle) { - _toolTipTitle = title; - _toolTipSubTitle = subtitle; - emit toolTipChanged(title, subtitle); + +void SystemTray::setToolTip(const QString &title, const QString &subtitle) +{ + _toolTipTitle = title; + _toolTipSubTitle = subtitle; + emit toolTipChanged(title, subtitle); } -void SystemTray::showMessage(const QString &title, const QString &message, MessageIcon icon, int millisecondsTimeoutHint, uint id) { - Q_UNUSED(title) - Q_UNUSED(message) - Q_UNUSED(icon) - Q_UNUSED(millisecondsTimeoutHint) - Q_UNUSED(id) + +void SystemTray::showMessage(const QString &title, const QString &message, MessageIcon icon, int millisecondsTimeoutHint, uint id) +{ + Q_UNUSED(title) + Q_UNUSED(message) + Q_UNUSED(icon) + Q_UNUSED(millisecondsTimeoutHint) + Q_UNUSED(id) } -void SystemTray::activate(SystemTray::ActivationReason reason) { - emit activated(reason); + +void SystemTray::activate(SystemTray::ActivationReason reason) +{ + emit activated(reason); } -void SystemTray::minimizeRestore() { - GraphicalUi::toggleMainWidget(); + +void SystemTray::minimizeRestore() +{ + GraphicalUi::toggleMainWidget(); } -void SystemTray::enableAnimationChanged(const QVariant &v) { - _animationEnabled = v.toBool(); - emit animationEnabledChanged(v.toBool()); + +void SystemTray::enableAnimationChanged(const QVariant &v) +{ + _animationEnabled = v.toBool(); + emit animationEnabledChanged(v.toBool()); } diff --git a/src/qtui/systemtray.h b/src/qtui/systemtray.h index 366ab521..850ad520 100644 --- a/src/qtui/systemtray.h +++ b/src/qtui/systemtray.h @@ -26,103 +26,105 @@ class Action; class QMenu; -class SystemTray : public QObject { - Q_OBJECT - Q_ENUMS(State Mode MessageIcon ActivationReason) - -public: - enum State { - Passive, - Active, - NeedsAttention - }; - - enum Mode { - Invalid, - Legacy, - StatusNotifier - }; - - // same as in QSystemTrayIcon - enum MessageIcon { - NoIcon, - Information, - Warning, - Critical - }; - - // same as in QSystemTrayIcon - enum ActivationReason { - Unknown, - Context, - DoubleClick, - Trigger, - MiddleClick - }; - - explicit SystemTray(QWidget *parent); - virtual ~SystemTray(); - virtual void init(); - - inline Mode mode() const; - inline State state() const; - inline bool isAlerted() const; - virtual inline bool isSystemTrayAvailable() const; - - void setAlert(bool alerted); - virtual inline bool isVisible() const { return false; } - - QWidget *associatedWidget() const; +class SystemTray : public QObject +{ + Q_OBJECT + Q_ENUMS(State Mode MessageIcon ActivationReason) + +public : + enum State { + Passive, + Active, + NeedsAttention + }; + + enum Mode { + Invalid, + Legacy, + StatusNotifier + }; + + // same as in QSystemTrayIcon + enum MessageIcon { + NoIcon, + Information, + Warning, + Critical + }; + + // same as in QSystemTrayIcon + enum ActivationReason { + Unknown, + Context, + DoubleClick, + Trigger, + MiddleClick + }; + + explicit SystemTray(QWidget *parent); + virtual ~SystemTray(); + virtual void init(); + + inline Mode mode() const; + inline State state() const; + inline bool isAlerted() const; + virtual inline bool isSystemTrayAvailable() const; + + void setAlert(bool alerted); + virtual inline bool isVisible() const { return false; } + + QWidget *associatedWidget() const; public slots: - virtual void setState(State); - virtual void setVisible(bool visible = true); - virtual void setToolTip(const QString &title, const QString &subtitle); - virtual void showMessage(const QString &title, const QString &message, MessageIcon icon = Information, int msTimeout = 10000, uint notificationId = 0); - virtual void closeMessage(uint notificationId) { Q_UNUSED(notificationId) } + virtual void setState(State); + virtual void setVisible(bool visible = true); + virtual void setToolTip(const QString &title, const QString &subtitle); + virtual void showMessage(const QString &title, const QString &message, MessageIcon icon = Information, int msTimeout = 10000, uint notificationId = 0); + virtual void closeMessage(uint notificationId) { Q_UNUSED(notificationId) } signals: - void activated(SystemTray::ActivationReason); - void iconChanged(const Icon &); - void animationEnabledChanged(bool); - void toolTipChanged(const QString &title, const QString &subtitle); - void messageClicked(uint notificationId); - void messageClosed(uint notificationId); + void activated(SystemTray::ActivationReason); + void iconChanged(const Icon &); + void animationEnabledChanged(bool); + void toolTipChanged(const QString &title, const QString &subtitle); + void messageClicked(uint notificationId); + void messageClosed(uint notificationId); protected slots: - virtual void activate(SystemTray::ActivationReason = Trigger); + virtual void activate(SystemTray::ActivationReason = Trigger); protected: - virtual void setMode(Mode mode); - inline bool shouldBeVisible() const; + virtual void setMode(Mode mode); + inline bool shouldBeVisible() const; - virtual Icon stateIcon() const; - Icon stateIcon(State state) const; - inline QString toolTipTitle() const; - inline QString toolTipSubTitle() const; - inline QMenu *trayMenu() const; + virtual Icon stateIcon() const; + Icon stateIcon(State state) const; + inline QString toolTipTitle() const; + inline QString toolTipSubTitle() const; + inline QMenu *trayMenu() const; - inline bool animationEnabled() const; + inline bool animationEnabled() const; private slots: - void minimizeRestore(); - void trayMenuAboutToShow(); - void enableAnimationChanged(const QVariant &); + void minimizeRestore(); + void trayMenuAboutToShow(); + void enableAnimationChanged(const QVariant &); private: - Mode _mode; - State _state; - bool _shouldBeVisible; + Mode _mode; + State _state; + bool _shouldBeVisible; - QString _toolTipTitle, _toolTipSubTitle; - Icon _passiveIcon, _activeIcon, _needsAttentionIcon; - bool _animationEnabled; + QString _toolTipTitle, _toolTipSubTitle; + Icon _passiveIcon, _activeIcon, _needsAttentionIcon; + bool _animationEnabled; - QMenu *_trayMenu; - QWidget *_associatedWidget; - Action *_minimizeRestoreAction; + QMenu *_trayMenu; + QWidget *_associatedWidget; + Action *_minimizeRestoreAction; }; + // inlines bool SystemTray::isSystemTrayAvailable() const { return false; } diff --git a/src/qtui/systraynotificationbackend.cpp b/src/qtui/systraynotificationbackend.cpp index 74134954..5fa0cf3e 100644 --- a/src/qtui/systraynotificationbackend.cpp +++ b/src/qtui/systraynotificationbackend.cpp @@ -35,134 +35,165 @@ #include "systemtray.h" SystrayNotificationBackend::SystrayNotificationBackend(QObject *parent) - : AbstractNotificationBackend(parent), - _blockActivation(false) + : AbstractNotificationBackend(parent), + _blockActivation(false) { - NotificationSettings notificationSettings; - notificationSettings.initAndNotify("Systray/ShowBubble", this, SLOT(showBubbleChanged(QVariant)), true); - notificationSettings.initAndNotify("Systray/Animate", this, SLOT(animateChanged(QVariant)), true); + NotificationSettings notificationSettings; + notificationSettings.initAndNotify("Systray/ShowBubble", this, SLOT(showBubbleChanged(QVariant)), true); + notificationSettings.initAndNotify("Systray/Animate", this, SLOT(animateChanged(QVariant)), true); - connect(QtUi::mainWindow()->systemTray(), SIGNAL(messageClicked(uint)), SLOT(notificationActivated(uint))); - connect(QtUi::mainWindow()->systemTray(), SIGNAL(activated(SystemTray::ActivationReason)), - SLOT(notificationActivated(SystemTray::ActivationReason))); + connect(QtUi::mainWindow()->systemTray(), SIGNAL(messageClicked(uint)), SLOT(notificationActivated(uint))); + connect(QtUi::mainWindow()->systemTray(), SIGNAL(activated(SystemTray::ActivationReason)), + SLOT(notificationActivated(SystemTray::ActivationReason))); - QApplication::instance()->installEventFilter(this); + QApplication::instance()->installEventFilter(this); - updateToolTip(); + updateToolTip(); } -void SystrayNotificationBackend::notify(const Notification &n) { - if(n.type != Highlight && n.type != PrivMsg) - return; - _notifications.append(n); - if(_showBubble) { - QString title = Client::networkModel()->networkName(n.bufferId) + " - " + Client::networkModel()->bufferName(n.bufferId); - QString message = QString("<%1> %2").arg(n.sender, n.message); - QtUi::mainWindow()->systemTray()->showMessage(title, message, SystemTray::Information, 10000, n.notificationId); - } +void SystrayNotificationBackend::notify(const Notification &n) +{ + if (n.type != Highlight && n.type != PrivMsg) + return; + + _notifications.append(n); + if (_showBubble) { + QString title = Client::networkModel()->networkName(n.bufferId) + " - " + Client::networkModel()->bufferName(n.bufferId); + QString message = QString("<%1> %2").arg(n.sender, n.message); + QtUi::mainWindow()->systemTray()->showMessage(title, message, SystemTray::Information, 10000, n.notificationId); + } - if(_animate) - QtUi::mainWindow()->systemTray()->setAlert(true); + if (_animate) + QtUi::mainWindow()->systemTray()->setAlert(true); - updateToolTip(); + updateToolTip(); } -void SystrayNotificationBackend::close(uint notificationId) { - QList::iterator i = _notifications.begin(); - while(i != _notifications.end()) { - if(i->notificationId == notificationId) - i = _notifications.erase(i); - else - ++i; - } - QtUi::mainWindow()->systemTray()->closeMessage(notificationId); +void SystrayNotificationBackend::close(uint notificationId) +{ + QList::iterator i = _notifications.begin(); + while (i != _notifications.end()) { + if (i->notificationId == notificationId) + i = _notifications.erase(i); + else + ++i; + } + + QtUi::mainWindow()->systemTray()->closeMessage(notificationId); - //if(!_notifications.count()) //FIXME make configurable + //if(!_notifications.count()) //FIXME make configurable QtUi::mainWindow()->systemTray()->setAlert(false); - updateToolTip(); + updateToolTip(); } -void SystrayNotificationBackend::notificationActivated(uint notificationId) { - if(!_blockActivation) { - if(_notifications.count()) { - if(QtUi::mainWindow()->systemTray()->mode() == SystemTray::Legacy) - _blockActivation = true; // prevent double activation because both tray icon and bubble might send a signal - if(!notificationId) - notificationId = _notifications.count()? _notifications.last().notificationId : 0; - emit activated(notificationId); - } else - GraphicalUi::toggleMainWidget(); - } + +void SystrayNotificationBackend::notificationActivated(uint notificationId) +{ + if (!_blockActivation) { + if (_notifications.count()) { + if (QtUi::mainWindow()->systemTray()->mode() == SystemTray::Legacy) + _blockActivation = true; // prevent double activation because both tray icon and bubble might send a signal + if (!notificationId) + notificationId = _notifications.count() ? _notifications.last().notificationId : 0; + emit activated(notificationId); + } + else + GraphicalUi::toggleMainWidget(); + } } -void SystrayNotificationBackend::notificationActivated(SystemTray::ActivationReason reason) { - if(reason == SystemTray::Trigger) { - notificationActivated(0); - } + +void SystrayNotificationBackend::notificationActivated(SystemTray::ActivationReason reason) +{ + if (reason == SystemTray::Trigger) { + notificationActivated(0); + } } + // moving the mouse or releasing the button means that we're not dealing with a double activation -bool SystrayNotificationBackend::eventFilter(QObject *obj, QEvent *event) { - if(event->type() == QEvent::MouseMove || event->type() == QEvent::MouseButtonRelease) { - _blockActivation = false; - } - return AbstractNotificationBackend::eventFilter(obj, event); +bool SystrayNotificationBackend::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::MouseMove || event->type() == QEvent::MouseButtonRelease) { + _blockActivation = false; + } + return AbstractNotificationBackend::eventFilter(obj, event); } -void SystrayNotificationBackend::showBubbleChanged(const QVariant &v) { - _showBubble = v.toBool(); + +void SystrayNotificationBackend::showBubbleChanged(const QVariant &v) +{ + _showBubble = v.toBool(); } -void SystrayNotificationBackend::animateChanged(const QVariant &v) { - _animate = v.toBool(); + +void SystrayNotificationBackend::animateChanged(const QVariant &v) +{ + _animate = v.toBool(); } -void SystrayNotificationBackend::updateToolTip() { - QtUi::mainWindow()->systemTray()->setToolTip("Quassel IRC", - _notifications.count()? tr("%n pending highlight(s)", "", _notifications.count()) : QString()); + +void SystrayNotificationBackend::updateToolTip() +{ + QtUi::mainWindow()->systemTray()->setToolTip("Quassel IRC", + _notifications.count() ? tr("%n pending highlight(s)", "", _notifications.count()) : QString()); } -SettingsPage *SystrayNotificationBackend::createConfigWidget() const { - return new ConfigWidget(); + +SettingsPage *SystrayNotificationBackend::createConfigWidget() const +{ + return new ConfigWidget(); } + /***************************************************************************/ -SystrayNotificationBackend::ConfigWidget::ConfigWidget(QWidget *parent) : SettingsPage("Internal", "SystrayNotification", parent) { - _showBubbleBox = new QCheckBox(tr("Show a message in a popup")); - _showBubbleBox->setIcon(SmallIcon("dialog-information")); - connect(_showBubbleBox, SIGNAL(toggled(bool)), this, SLOT(widgetChanged())); - QHBoxLayout *layout = new QHBoxLayout(this); - layout->addWidget(_showBubbleBox); +SystrayNotificationBackend::ConfigWidget::ConfigWidget(QWidget *parent) : SettingsPage("Internal", "SystrayNotification", parent) +{ + _showBubbleBox = new QCheckBox(tr("Show a message in a popup")); + _showBubbleBox->setIcon(SmallIcon("dialog-information")); + connect(_showBubbleBox, SIGNAL(toggled(bool)), this, SLOT(widgetChanged())); + QHBoxLayout *layout = new QHBoxLayout(this); + layout->addWidget(_showBubbleBox); } -void SystrayNotificationBackend::ConfigWidget::widgetChanged() { - bool changed = (_showBubble != _showBubbleBox->isChecked()); - if(changed != hasChanged()) - setChangedState(changed); + +void SystrayNotificationBackend::ConfigWidget::widgetChanged() +{ + bool changed = (_showBubble != _showBubbleBox->isChecked()); + if (changed != hasChanged()) + setChangedState(changed); } -bool SystrayNotificationBackend::ConfigWidget::hasDefaults() const { - return true; + +bool SystrayNotificationBackend::ConfigWidget::hasDefaults() const +{ + return true; } -void SystrayNotificationBackend::ConfigWidget::defaults() { - _showBubbleBox->setChecked(false); - widgetChanged(); + +void SystrayNotificationBackend::ConfigWidget::defaults() +{ + _showBubbleBox->setChecked(false); + widgetChanged(); } -void SystrayNotificationBackend::ConfigWidget::load() { - NotificationSettings s; - _showBubble = s.value("Systray/ShowBubble", false).toBool(); - _showBubbleBox->setChecked(_showBubble); - setChangedState(false); + +void SystrayNotificationBackend::ConfigWidget::load() +{ + NotificationSettings s; + _showBubble = s.value("Systray/ShowBubble", false).toBool(); + _showBubbleBox->setChecked(_showBubble); + setChangedState(false); } -void SystrayNotificationBackend::ConfigWidget::save() { - NotificationSettings s; - s.setValue("Systray/ShowBubble", _showBubbleBox->isChecked()); - load(); + +void SystrayNotificationBackend::ConfigWidget::save() +{ + NotificationSettings s; + s.setValue("Systray/ShowBubble", _showBubbleBox->isChecked()); + load(); } diff --git a/src/qtui/systraynotificationbackend.h b/src/qtui/systraynotificationbackend.h index aa08b392..362ac904 100644 --- a/src/qtui/systraynotificationbackend.h +++ b/src/qtui/systraynotificationbackend.h @@ -27,52 +27,56 @@ class QCheckBox; -class SystrayNotificationBackend : public AbstractNotificationBackend { - Q_OBJECT +class SystrayNotificationBackend : public AbstractNotificationBackend +{ + Q_OBJECT public: - SystrayNotificationBackend(QObject *parent = 0); + SystrayNotificationBackend(QObject *parent = 0); - void notify(const Notification &); - void close(uint notificationId); - virtual SettingsPage *createConfigWidget() const; + void notify(const Notification &); + void close(uint notificationId); + virtual SettingsPage *createConfigWidget() const; protected: - virtual bool eventFilter(QObject *obj, QEvent *event); + virtual bool eventFilter(QObject *obj, QEvent *event); private slots: - void notificationActivated(uint notificationId); - void notificationActivated(SystemTray::ActivationReason); + void notificationActivated(uint notificationId); + void notificationActivated(SystemTray::ActivationReason); - void animateChanged(const QVariant &); - void showBubbleChanged(const QVariant &); - void updateToolTip(); + void animateChanged(const QVariant &); + void showBubbleChanged(const QVariant &); + void updateToolTip(); private: - class ConfigWidget; + class ConfigWidget; - bool _showBubble; - bool _animate; - QList _notifications; - bool _blockActivation; + bool _showBubble; + bool _animate; + QList _notifications; + bool _blockActivation; }; -class SystrayNotificationBackend::ConfigWidget : public SettingsPage { - Q_OBJECT + +class SystrayNotificationBackend::ConfigWidget : public SettingsPage +{ + Q_OBJECT public: - ConfigWidget(QWidget *parent = 0); - void save(); - void load(); - bool hasDefaults() const; - void defaults(); + ConfigWidget(QWidget *parent = 0); + void save(); + void load(); + bool hasDefaults() const; + void defaults(); private slots: - void widgetChanged(); + void widgetChanged(); private: - QCheckBox *_showBubbleBox; - bool _showBubble; + QCheckBox *_showBubbleBox; + bool _showBubble; }; + #endif diff --git a/src/qtui/taskbarnotificationbackend.cpp b/src/qtui/taskbarnotificationbackend.cpp index 46e562b3..15e2c889 100644 --- a/src/qtui/taskbarnotificationbackend.cpp +++ b/src/qtui/taskbarnotificationbackend.cpp @@ -31,92 +31,114 @@ #include "qtui.h" TaskbarNotificationBackend::TaskbarNotificationBackend(QObject *parent) - : AbstractNotificationBackend(parent) + : AbstractNotificationBackend(parent) { - NotificationSettings notificationSettings; - _enabled = notificationSettings.value("Taskbar/Enabled", true).toBool(); - _timeout = notificationSettings.value("Taskbar/Timeout", 0).toInt(); + NotificationSettings notificationSettings; + _enabled = notificationSettings.value("Taskbar/Enabled", true).toBool(); + _timeout = notificationSettings.value("Taskbar/Timeout", 0).toInt(); - notificationSettings.notify("Taskbar/Enabled", this, SLOT(enabledChanged(const QVariant &))); - notificationSettings.notify("Taskbar/Timeout", this, SLOT(timeoutChanged(const QVariant &))); + notificationSettings.notify("Taskbar/Enabled", this, SLOT(enabledChanged(const QVariant &))); + notificationSettings.notify("Taskbar/Timeout", this, SLOT(timeoutChanged(const QVariant &))); } -void TaskbarNotificationBackend::notify(const Notification ¬ification) { - if(_enabled && (notification.type == Highlight || notification.type == PrivMsg)) { - QApplication::alert(QtUi::mainWindow(), _timeout); - } + +void TaskbarNotificationBackend::notify(const Notification ¬ification) +{ + if (_enabled && (notification.type == Highlight || notification.type == PrivMsg)) { + QApplication::alert(QtUi::mainWindow(), _timeout); + } } -void TaskbarNotificationBackend::close(uint notificationId) { - Q_UNUSED(notificationId); + +void TaskbarNotificationBackend::close(uint notificationId) +{ + Q_UNUSED(notificationId); } -void TaskbarNotificationBackend::enabledChanged(const QVariant &v) { - _enabled = v.toBool(); + +void TaskbarNotificationBackend::enabledChanged(const QVariant &v) +{ + _enabled = v.toBool(); } -void TaskbarNotificationBackend::timeoutChanged(const QVariant &v) { - _timeout = v.toInt(); + +void TaskbarNotificationBackend::timeoutChanged(const QVariant &v) +{ + _timeout = v.toInt(); } -SettingsPage *TaskbarNotificationBackend::createConfigWidget() const { - return new ConfigWidget(); + +SettingsPage *TaskbarNotificationBackend::createConfigWidget() const +{ + return new ConfigWidget(); } + /***************************************************************************/ -TaskbarNotificationBackend::ConfigWidget::ConfigWidget(QWidget *parent) : SettingsPage("Internal", "TaskbarNotification", parent) { - QHBoxLayout *layout = new QHBoxLayout(this); +TaskbarNotificationBackend::ConfigWidget::ConfigWidget(QWidget *parent) : SettingsPage("Internal", "TaskbarNotification", parent) +{ + QHBoxLayout *layout = new QHBoxLayout(this); #ifdef Q_WS_MAC - layout->addWidget(enabledBox = new QCheckBox(tr("Activate dock entry, timeout:"), this)); + layout->addWidget(enabledBox = new QCheckBox(tr("Activate dock entry, timeout:"), this)); #else - layout->addWidget(enabledBox = new QCheckBox(tr("Mark taskbar entry, timeout:"), this)); + layout->addWidget(enabledBox = new QCheckBox(tr("Mark taskbar entry, timeout:"), this)); #endif - enabledBox->setIcon(SmallIcon("flag-blue")); - enabledBox->setEnabled(true); - - timeoutBox = new QSpinBox(this); - timeoutBox->setMinimum(1); - timeoutBox->setMaximum(99); - timeoutBox->setSpecialValueText(tr("Unlimited")); - timeoutBox->setSuffix(tr(" seconds")); - layout->addWidget(timeoutBox); - layout->addStretch(20); - - connect(enabledBox, SIGNAL(toggled(bool)), SLOT(widgetChanged())); - connect(enabledBox, SIGNAL(toggled(bool)), timeoutBox, SLOT(setEnabled(bool))); - connect(timeoutBox, SIGNAL(valueChanged(int)), SLOT(widgetChanged())); + enabledBox->setIcon(SmallIcon("flag-blue")); + enabledBox->setEnabled(true); + + timeoutBox = new QSpinBox(this); + timeoutBox->setMinimum(1); + timeoutBox->setMaximum(99); + timeoutBox->setSpecialValueText(tr("Unlimited")); + timeoutBox->setSuffix(tr(" seconds")); + layout->addWidget(timeoutBox); + layout->addStretch(20); + + connect(enabledBox, SIGNAL(toggled(bool)), SLOT(widgetChanged())); + connect(enabledBox, SIGNAL(toggled(bool)), timeoutBox, SLOT(setEnabled(bool))); + connect(timeoutBox, SIGNAL(valueChanged(int)), SLOT(widgetChanged())); } -void TaskbarNotificationBackend::ConfigWidget::widgetChanged() { - bool changed = (enabled != enabledBox->isChecked() || timeout/1000 != timeoutBox->value()); - if(changed != hasChanged()) setChangedState(changed); + +void TaskbarNotificationBackend::ConfigWidget::widgetChanged() +{ + bool changed = (enabled != enabledBox->isChecked() || timeout/1000 != timeoutBox->value()); + if (changed != hasChanged()) setChangedState(changed); } -bool TaskbarNotificationBackend::ConfigWidget::hasDefaults() const { - return true; + +bool TaskbarNotificationBackend::ConfigWidget::hasDefaults() const +{ + return true; } -void TaskbarNotificationBackend::ConfigWidget::defaults() { - enabledBox->setChecked(true); - timeoutBox->setValue(0); - widgetChanged(); + +void TaskbarNotificationBackend::ConfigWidget::defaults() +{ + enabledBox->setChecked(true); + timeoutBox->setValue(0); + widgetChanged(); } -void TaskbarNotificationBackend::ConfigWidget::load() { - NotificationSettings s; - enabled = s.value("Taskbar/Enabled", true).toBool(); - timeout = s.value("Taskbar/Timeout", 0).toInt(); - enabledBox->setChecked(enabled); - timeoutBox->setValue(timeout/1000); +void TaskbarNotificationBackend::ConfigWidget::load() +{ + NotificationSettings s; + enabled = s.value("Taskbar/Enabled", true).toBool(); + timeout = s.value("Taskbar/Timeout", 0).toInt(); + + enabledBox->setChecked(enabled); + timeoutBox->setValue(timeout/1000); - setChangedState(false); + setChangedState(false); } -void TaskbarNotificationBackend::ConfigWidget::save() { - NotificationSettings s; - s.setValue("Taskbar/Enabled", enabledBox->isChecked()); - s.setValue("Taskbar/Timeout", timeoutBox->value() * 1000); - load(); + +void TaskbarNotificationBackend::ConfigWidget::save() +{ + NotificationSettings s; + s.setValue("Taskbar/Enabled", enabledBox->isChecked()); + s.setValue("Taskbar/Timeout", timeoutBox->value() * 1000); + load(); } diff --git a/src/qtui/taskbarnotificationbackend.h b/src/qtui/taskbarnotificationbackend.h index 5ba4b552..abc63673 100644 --- a/src/qtui/taskbarnotificationbackend.h +++ b/src/qtui/taskbarnotificationbackend.h @@ -28,46 +28,50 @@ class QCheckBox; class QSpinBox; -class TaskbarNotificationBackend : public AbstractNotificationBackend { - Q_OBJECT +class TaskbarNotificationBackend : public AbstractNotificationBackend +{ + Q_OBJECT public: - TaskbarNotificationBackend(QObject *parent = 0); + TaskbarNotificationBackend(QObject *parent = 0); - void notify(const Notification &); - void close(uint notificationId); - virtual SettingsPage *createConfigWidget() const; + void notify(const Notification &); + void close(uint notificationId); + virtual SettingsPage *createConfigWidget() const; private slots: - void enabledChanged(const QVariant &); - void timeoutChanged(const QVariant &); + void enabledChanged(const QVariant &); + void timeoutChanged(const QVariant &); private: - class ConfigWidget; + class ConfigWidget; - bool _enabled; - int _timeout; + bool _enabled; + int _timeout; }; -class TaskbarNotificationBackend::ConfigWidget : public SettingsPage { - Q_OBJECT + +class TaskbarNotificationBackend::ConfigWidget : public SettingsPage +{ + Q_OBJECT public: - ConfigWidget(QWidget *parent = 0); - void save(); - void load(); - bool hasDefaults() const; - void defaults(); + ConfigWidget(QWidget *parent = 0); + void save(); + void load(); + bool hasDefaults() const; + void defaults(); private slots: - void widgetChanged(); + void widgetChanged(); private: - QCheckBox *enabledBox; - QSpinBox *timeoutBox; + QCheckBox *enabledBox; + QSpinBox *timeoutBox; - bool enabled; - int timeout; + bool enabled; + int timeout; }; + #endif diff --git a/src/qtui/titlesetter.cpp b/src/qtui/titlesetter.cpp index 297b4cec..c9d53dca 100644 --- a/src/qtui/titlesetter.cpp +++ b/src/qtui/titlesetter.cpp @@ -25,36 +25,40 @@ #include "mainwin.h" TitleSetter::TitleSetter(MainWin *parent) - : AbstractItemView(parent), + : AbstractItemView(parent), _mainWin(parent) { - } -void TitleSetter::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { - Q_UNUSED(previous); - changeWindowTitle(current.sibling(current.row(), 0)); + +void TitleSetter::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) +{ + Q_UNUSED(previous); + changeWindowTitle(current.sibling(current.row(), 0)); } -void TitleSetter::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { - QItemSelectionRange changedArea(topLeft, bottomRight); - QModelIndex currentTopicIndex = selectionModel()->currentIndex().sibling(selectionModel()->currentIndex().row(), 0); - if(changedArea.contains(currentTopicIndex)) - changeWindowTitle(currentTopicIndex); + +void TitleSetter::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) +{ + QItemSelectionRange changedArea(topLeft, bottomRight); + QModelIndex currentTopicIndex = selectionModel()->currentIndex().sibling(selectionModel()->currentIndex().row(), 0); + if (changedArea.contains(currentTopicIndex)) + changeWindowTitle(currentTopicIndex); }; -void TitleSetter::changeWindowTitle(const QModelIndex &index) { - BufferId id = index.data(NetworkModel::BufferIdRole).value(); - if(!id.isValid()) - return; +void TitleSetter::changeWindowTitle(const QModelIndex &index) +{ + BufferId id = index.data(NetworkModel::BufferIdRole).value(); + if (!id.isValid()) + return; - QString title; - if(Client::networkModel()->bufferType(id) == BufferInfo::StatusBuffer) - title = index.data().toString(); - else - title = QString("%1 (%2)").arg(index.data().toString(), Client::networkModel()->networkName(id)); - QString newTitle = QString("%1 - %2").arg("Quassel IRC").arg(title); + QString title; + if (Client::networkModel()->bufferType(id) == BufferInfo::StatusBuffer) + title = index.data().toString(); + else + title = QString("%1 (%2)").arg(index.data().toString(), Client::networkModel()->networkName(id)); + QString newTitle = QString("%1 - %2").arg("Quassel IRC").arg(title); - _mainWin->setWindowTitle(newTitle); - _mainWin->setWindowIconText(newTitle); + _mainWin->setWindowTitle(newTitle); + _mainWin->setWindowIconText(newTitle); } diff --git a/src/qtui/titlesetter.h b/src/qtui/titlesetter.h index fe16b2d3..e595d07b 100644 --- a/src/qtui/titlesetter.h +++ b/src/qtui/titlesetter.h @@ -18,7 +18,6 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ - #ifndef TITLESETTER_H #define TITLESETTER_H @@ -26,17 +25,18 @@ class MainWin; -class TitleSetter : public AbstractItemView { - Q_OBJECT +class TitleSetter : public AbstractItemView +{ + Q_OBJECT - public: +public: TitleSetter(MainWin *parent); - protected slots: +protected slots: virtual void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); - private: +private: MainWin *_mainWin; void changeWindowTitle(const QModelIndex &index); }; diff --git a/src/qtui/topicwidget.cpp b/src/qtui/topicwidget.cpp index 464de091..ebc241c2 100644 --- a/src/qtui/topicwidget.cpp +++ b/src/qtui/topicwidget.cpp @@ -26,209 +26,238 @@ #include "uisettings.h" TopicWidget::TopicWidget(QWidget *parent) - : AbstractItemView(parent) + : AbstractItemView(parent) { - ui.setupUi(this); - ui.topicEditButton->setIcon(SmallIcon("edit-rename")); - ui.topicLineEdit->setWordWrapEnabled(true); - ui.topicLineEdit->installEventFilter(this); - - connect(ui.topicLabel, SIGNAL(clickableActivated(Clickable)), SLOT(clickableActivated(Clickable))); - connect(ui.topicLineEdit, SIGNAL(noTextEntered()), SLOT(on_topicLineEdit_textEntered())); - - UiSettings s("TopicWidget"); - s.notify("DynamicResize", this, SLOT(updateResizeMode())); - s.notify("ResizeOnHover", this, SLOT(updateResizeMode())); - updateResizeMode(); - - UiStyleSettings fs("Fonts"); - fs.notify("UseCustomTopicWidgetFont", this, SLOT(setUseCustomFont(QVariant))); - fs.notify("TopicWidget", this, SLOT(setCustomFont(QVariant))); - if(fs.value("UseCustomTopicWidgetFont", false).toBool()) - setCustomFont(fs.value("TopicWidget", QFont())); - - _mouseEntered = false; - _readonly = false; + ui.setupUi(this); + ui.topicEditButton->setIcon(SmallIcon("edit-rename")); + ui.topicLineEdit->setWordWrapEnabled(true); + ui.topicLineEdit->installEventFilter(this); + + connect(ui.topicLabel, SIGNAL(clickableActivated(Clickable)), SLOT(clickableActivated(Clickable))); + connect(ui.topicLineEdit, SIGNAL(noTextEntered()), SLOT(on_topicLineEdit_textEntered())); + + UiSettings s("TopicWidget"); + s.notify("DynamicResize", this, SLOT(updateResizeMode())); + s.notify("ResizeOnHover", this, SLOT(updateResizeMode())); + updateResizeMode(); + + UiStyleSettings fs("Fonts"); + fs.notify("UseCustomTopicWidgetFont", this, SLOT(setUseCustomFont(QVariant))); + fs.notify("TopicWidget", this, SLOT(setCustomFont(QVariant))); + if (fs.value("UseCustomTopicWidgetFont", false).toBool()) + setCustomFont(fs.value("TopicWidget", QFont())); + + _mouseEntered = false; + _readonly = false; } -void TopicWidget::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { - Q_UNUSED(previous); - setTopic(current); + +void TopicWidget::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) +{ + Q_UNUSED(previous); + setTopic(current); } -void TopicWidget::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { - QItemSelectionRange changedArea(topLeft, bottomRight); - QModelIndex currentTopicIndex = selectionModel()->currentIndex().sibling(selectionModel()->currentIndex().row(), 1); - if(changedArea.contains(currentTopicIndex)) - setTopic(selectionModel()->currentIndex()); + +void TopicWidget::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) +{ + QItemSelectionRange changedArea(topLeft, bottomRight); + QModelIndex currentTopicIndex = selectionModel()->currentIndex().sibling(selectionModel()->currentIndex().row(), 1); + if (changedArea.contains(currentTopicIndex)) + setTopic(selectionModel()->currentIndex()); }; -void TopicWidget::setUseCustomFont(const QVariant &v) { - if(v.toBool()) { - UiStyleSettings fs("Fonts"); - setCustomFont(fs.value("TopicWidget").value()); - } else - setCustomFont(QFont()); +void TopicWidget::setUseCustomFont(const QVariant &v) +{ + if (v.toBool()) { + UiStyleSettings fs("Fonts"); + setCustomFont(fs.value("TopicWidget").value()); + } + else + setCustomFont(QFont()); } -void TopicWidget::setCustomFont(const QVariant &v) { - UiStyleSettings fs("Fonts"); - if(!fs.value("UseCustomTopicWidgetFont", false).toBool()) - return; - setCustomFont(v.value()); +void TopicWidget::setCustomFont(const QVariant &v) +{ + UiStyleSettings fs("Fonts"); + if (!fs.value("UseCustomTopicWidgetFont", false).toBool()) + return; + + setCustomFont(v.value()); } -void TopicWidget::setCustomFont(const QFont &f) { - QFont font = f; - if(font.family().isEmpty()) - font = QApplication::font(); - ui.topicLineEdit->setCustomFont(font); - ui.topicLabel->setCustomFont(font); +void TopicWidget::setCustomFont(const QFont &f) +{ + QFont font = f; + if (font.family().isEmpty()) + font = QApplication::font(); + + ui.topicLineEdit->setCustomFont(font); + ui.topicLabel->setCustomFont(font); } -void TopicWidget::setTopic(const QModelIndex &index) { - QString newtopic; - bool readonly = true; - - BufferId id = index.data(NetworkModel::BufferIdRole).value(); - if(id.isValid()) { - QModelIndex index0 = index.sibling(index.row(), 0); - const Network *network = Client::network(Client::networkModel()->networkId(id)); - - switch(Client::networkModel()->bufferType(id)) { - case BufferInfo::StatusBuffer: - if(network) { - newtopic = QString("%1 (%2) | %3 | %4") - .arg(Qt::escape(network->networkName())) - .arg(Qt::escape(network->currentServer())) - .arg(tr("Users: %1").arg(network->ircUsers().count())) - .arg(tr("Lag: %1 msecs").arg(network->latency())); - } else { - newtopic = index0.data(Qt::DisplayRole).toString(); - } - break; - - case BufferInfo::ChannelBuffer: - newtopic = index.sibling(index.row(), 1).data().toString(); - readonly = false; - break; - - case BufferInfo::QueryBuffer: - { - QString nickname = index0.data(Qt::DisplayRole).toString(); - if(network) { - const IrcUser *user = network->ircUser(nickname); - if(user) { - newtopic = QString("%1%2%3 | %4@%5").arg(nickname) - .arg(user->userModes().isEmpty() ? QString() : QString(" (+%1)").arg(user->userModes())) - .arg(user->realName().isEmpty() ? QString() : QString(" | %1").arg(user->realName())) - .arg(user->user()) - .arg(user->host()); - } else { // no such user - newtopic = nickname; - } - } else { // no valid Network-Obj. - newtopic = nickname; + +void TopicWidget::setTopic(const QModelIndex &index) +{ + QString newtopic; + bool readonly = true; + + BufferId id = index.data(NetworkModel::BufferIdRole).value(); + if (id.isValid()) { + QModelIndex index0 = index.sibling(index.row(), 0); + const Network *network = Client::network(Client::networkModel()->networkId(id)); + + switch (Client::networkModel()->bufferType(id)) { + case BufferInfo::StatusBuffer: + if (network) { + newtopic = QString("%1 (%2) | %3 | %4") + .arg(Qt::escape(network->networkName())) + .arg(Qt::escape(network->currentServer())) + .arg(tr("Users: %1").arg(network->ircUsers().count())) + .arg(tr("Lag: %1 msecs").arg(network->latency())); + } + else { + newtopic = index0.data(Qt::DisplayRole).toString(); + } + break; + + case BufferInfo::ChannelBuffer: + newtopic = index.sibling(index.row(), 1).data().toString(); + readonly = false; + break; + + case BufferInfo::QueryBuffer: + { + QString nickname = index0.data(Qt::DisplayRole).toString(); + if (network) { + const IrcUser *user = network->ircUser(nickname); + if (user) { + newtopic = QString("%1%2%3 | %4@%5").arg(nickname) + .arg(user->userModes().isEmpty() ? QString() : QString(" (+%1)").arg(user->userModes())) + .arg(user->realName().isEmpty() ? QString() : QString(" | %1").arg(user->realName())) + .arg(user->user()) + .arg(user->host()); + } + else { // no such user + newtopic = nickname; + } + } + else { // no valid Network-Obj. + newtopic = nickname; + } + break; + } + default: + newtopic = index0.data(Qt::DisplayRole).toString(); } - break; - } - default: - newtopic = index0.data(Qt::DisplayRole).toString(); } - } - _topic = newtopic; - _readonly = readonly; + _topic = newtopic; + _readonly = readonly; - ui.topicEditButton->setVisible(!_readonly); - ui.topicLabel->setText(newtopic); - ui.topicLineEdit->setPlainText(newtopic); - switchPlain(); + ui.topicEditButton->setVisible(!_readonly); + ui.topicLabel->setText(newtopic); + ui.topicLineEdit->setPlainText(newtopic); + switchPlain(); } -void TopicWidget::setReadOnly(const bool &readonly) { - if(_readonly == readonly) - return; +void TopicWidget::setReadOnly(const bool &readonly) +{ + if (_readonly == readonly) + return; - _readonly = readonly; + _readonly = readonly; } -void TopicWidget::updateResizeMode() { - StyledLabel::ResizeMode mode = StyledLabel::NoResize; - UiSettings s("TopicWidget"); - if(s.value("DynamicResize", true).toBool()) { - if(s.value("ResizeOnHover", true).toBool()) - mode = StyledLabel::ResizeOnHover; - else - mode = StyledLabel::DynamicResize; - } - ui.topicLabel->setResizeMode(mode); +void TopicWidget::updateResizeMode() +{ + StyledLabel::ResizeMode mode = StyledLabel::NoResize; + UiSettings s("TopicWidget"); + if (s.value("DynamicResize", true).toBool()) { + if (s.value("ResizeOnHover", true).toBool()) + mode = StyledLabel::ResizeOnHover; + else + mode = StyledLabel::DynamicResize; + } + + ui.topicLabel->setResizeMode(mode); } -void TopicWidget::clickableActivated(const Clickable &click) { - NetworkId networkId = selectionModel()->currentIndex().data(NetworkModel::NetworkIdRole).value(); - click.activate(networkId, _topic); + +void TopicWidget::clickableActivated(const Clickable &click) +{ + NetworkId networkId = selectionModel()->currentIndex().data(NetworkModel::NetworkIdRole).value(); + click.activate(networkId, _topic); } -void TopicWidget::on_topicLineEdit_textEntered() { - QModelIndex currentIdx = currentIndex(); - if(currentIdx.isValid() && currentIdx.data(NetworkModel::BufferTypeRole) == BufferInfo::ChannelBuffer) { - BufferInfo bufferInfo = currentIdx.data(NetworkModel::BufferInfoRole).value(); - if(ui.topicLineEdit->text().isEmpty()) - Client::userInput(bufferInfo, QString("/quote TOPIC %1 :").arg(bufferInfo.bufferName())); - else - Client::userInput(bufferInfo, QString("/topic %1").arg(ui.topicLineEdit->text())); - } - switchPlain(); + +void TopicWidget::on_topicLineEdit_textEntered() +{ + QModelIndex currentIdx = currentIndex(); + if (currentIdx.isValid() && currentIdx.data(NetworkModel::BufferTypeRole) == BufferInfo::ChannelBuffer) { + BufferInfo bufferInfo = currentIdx.data(NetworkModel::BufferInfoRole).value(); + if (ui.topicLineEdit->text().isEmpty()) + Client::userInput(bufferInfo, QString("/quote TOPIC %1 :").arg(bufferInfo.bufferName())); + else + Client::userInput(bufferInfo, QString("/topic %1").arg(ui.topicLineEdit->text())); + } + switchPlain(); } -void TopicWidget::on_topicEditButton_clicked() { - switchEditable(); + +void TopicWidget::on_topicEditButton_clicked() +{ + switchEditable(); } -void TopicWidget::switchEditable() { - ui.stackedWidget->setCurrentIndex(1); - ui.topicLineEdit->setFocus(); - ui.topicLineEdit->moveCursor(QTextCursor::End,QTextCursor::MoveAnchor); - updateGeometry(); + +void TopicWidget::switchEditable() +{ + ui.stackedWidget->setCurrentIndex(1); + ui.topicLineEdit->setFocus(); + ui.topicLineEdit->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor); + updateGeometry(); } -void TopicWidget::switchPlain() { - ui.stackedWidget->setCurrentIndex(0); - ui.topicLineEdit->setPlainText(_topic); - updateGeometry(); - emit switchedPlain(); + +void TopicWidget::switchPlain() +{ + ui.stackedWidget->setCurrentIndex(0); + ui.topicLineEdit->setPlainText(_topic); + updateGeometry(); + emit switchedPlain(); } -// filter for the input widget to switch back to normal mode -bool TopicWidget::eventFilter(QObject *obj, QEvent *event) { - if(event->type() == QEvent::FocusOut && !_mouseEntered) { - switchPlain(); - return true; - } +// filter for the input widget to switch back to normal mode +bool TopicWidget::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::FocusOut && !_mouseEntered) { + switchPlain(); + return true; + } - if(event->type() == QEvent::Enter) { - _mouseEntered = true; - } + if (event->type() == QEvent::Enter) { + _mouseEntered = true; + } - if(event->type() == QEvent::Leave) { - _mouseEntered = false; - } + if (event->type() == QEvent::Leave) { + _mouseEntered = false; + } - if(event->type() != QEvent::KeyRelease) - return QObject::eventFilter(obj, event); + if (event->type() != QEvent::KeyRelease) + return QObject::eventFilter(obj, event); - QKeyEvent *keyEvent = static_cast(event); + QKeyEvent *keyEvent = static_cast(event); - if(keyEvent->key() == Qt::Key_Escape) { - switchPlain(); - return true; - } + if (keyEvent->key() == Qt::Key_Escape) { + switchPlain(); + return true; + } - return false; + return false; } diff --git a/src/qtui/topicwidget.h b/src/qtui/topicwidget.h index c390549e..e8005576 100644 --- a/src/qtui/topicwidget.h +++ b/src/qtui/topicwidget.h @@ -25,43 +25,43 @@ #include "ui_topicwidget.h" -class TopicWidget : public AbstractItemView { - Q_OBJECT +class TopicWidget : public AbstractItemView +{ + Q_OBJECT public: - TopicWidget(QWidget *parent = 0); + TopicWidget(QWidget *parent = 0); - void setTopic(const QModelIndex& index); - void setCustomFont(const QFont &); - void setReadOnly(const bool &readonly); + void setTopic(const QModelIndex &index); + void setCustomFont(const QFont &); + void setReadOnly(const bool &readonly); - virtual bool eventFilter(QObject *obj, QEvent *event); - inline bool isReadOnly() const { return _readonly; } + virtual bool eventFilter(QObject *obj, QEvent *event); + inline bool isReadOnly() const { return _readonly; } - signals: +signals: void switchedPlain(); protected slots: - virtual void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); - virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + virtual void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); + virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); private slots: - void on_topicLineEdit_textEntered(); - void on_topicEditButton_clicked(); - void switchEditable(); - void switchPlain(); - void clickableActivated(const Clickable &); - void updateResizeMode(); - void setCustomFont(const QVariant &); - void setUseCustomFont(const QVariant &); + void on_topicLineEdit_textEntered(); + void on_topicEditButton_clicked(); + void switchEditable(); + void switchPlain(); + void clickableActivated(const Clickable &); + void updateResizeMode(); + void setCustomFont(const QVariant &); + void setUseCustomFont(const QVariant &); private: - Ui::TopicWidget ui; - - QString _topic; - bool _mouseEntered; - bool _readonly; + Ui::TopicWidget ui; + QString _topic; + bool _mouseEntered; + bool _readonly; }; diff --git a/src/qtui/verticaldock.cpp b/src/qtui/verticaldock.cpp index 69c2eaf1..9ad37e4f 100644 --- a/src/qtui/verticaldock.cpp +++ b/src/qtui/verticaldock.cpp @@ -27,70 +27,82 @@ #include VerticalDockTitle::VerticalDockTitle(QDockWidget *parent) - : QWidget(parent) + : QWidget(parent) { } -QSize VerticalDockTitle::sizeHint() const { - return QSize(8, 15); + +QSize VerticalDockTitle::sizeHint() const +{ + return QSize(8, 15); } -QSize VerticalDockTitle::minimumSizeHint() const { - return QSize(8, 10); + +QSize VerticalDockTitle::minimumSizeHint() const +{ + return QSize(8, 10); } -void VerticalDockTitle::paintEvent(QPaintEvent *event) { - Q_UNUSED(event); - QPainter painter(this); - - if(rect().isValid() && rect().height() > minimumSizeHint().height()) { - for(int i = 0; i < 2; i++) { - QPoint topLeft = rect().topLeft() + QPoint(3 + i*2, 2); - QPoint bottomRight = rect().topLeft() + QPoint(3 + i*2, rect().height() - 2); - qDrawShadeLine(&painter, topLeft, bottomRight, palette()); +void VerticalDockTitle::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + + QPainter painter(this); + + if (rect().isValid() && rect().height() > minimumSizeHint().height()) { + for (int i = 0; i < 2; i++) { + QPoint topLeft = rect().topLeft() + QPoint(3 + i*2, 2); + QPoint bottomRight = rect().topLeft() + QPoint(3 + i*2, rect().height() - 2); + qDrawShadeLine(&painter, topLeft, bottomRight, palette()); + } } - } } + // ============================== // Vertical Dock // ============================== VerticalDock::VerticalDock(const QString &title, QWidget *parent, Qt::WindowFlags flags) - : QDockWidget(title, parent, flags) + : QDockWidget(title, parent, flags) { - setDefaultTitleWidget(); + setDefaultTitleWidget(); } + VerticalDock::VerticalDock(QWidget *parent, Qt::WindowFlags flags) - : QDockWidget(parent, flags) + : QDockWidget(parent, flags) { - setDefaultTitleWidget(); - setContentsMargins(0, 0, 0, 0); + setDefaultTitleWidget(); + setContentsMargins(0, 0, 0, 0); } -void VerticalDock::setDefaultTitleWidget() { - QWidget *oldDockTitle = titleBarWidget(); - QWidget *newDockTitle = new VerticalDockTitle(this); - setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea); - setFeatures(features() | QDockWidget::DockWidgetVerticalTitleBar); - setTitleBarWidget(newDockTitle); - - if(oldDockTitle) - oldDockTitle->deleteLater(); +void VerticalDock::setDefaultTitleWidget() +{ + QWidget *oldDockTitle = titleBarWidget(); + QWidget *newDockTitle = new VerticalDockTitle(this); + + setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea); + setFeatures(features() | QDockWidget::DockWidgetVerticalTitleBar); + setTitleBarWidget(newDockTitle); + + if (oldDockTitle) + oldDockTitle->deleteLater(); } -void VerticalDock::showTitle(bool show) { - QWidget *oldDockTitle = titleBarWidget(); - QWidget *newDockTitle = 0; - - if(show) - newDockTitle = new VerticalDockTitle(this); - else - newDockTitle = new EmptyDockTitle(this); - - setTitleBarWidget(newDockTitle); - if(oldDockTitle) - oldDockTitle->deleteLater(); + +void VerticalDock::showTitle(bool show) +{ + QWidget *oldDockTitle = titleBarWidget(); + QWidget *newDockTitle = 0; + + if (show) + newDockTitle = new VerticalDockTitle(this); + else + newDockTitle = new EmptyDockTitle(this); + + setTitleBarWidget(newDockTitle); + if (oldDockTitle) + oldDockTitle->deleteLater(); } diff --git a/src/qtui/verticaldock.h b/src/qtui/verticaldock.h index ba616ff9..e62f58ea 100644 --- a/src/qtui/verticaldock.h +++ b/src/qtui/verticaldock.h @@ -24,44 +24,47 @@ #include #include -class VerticalDockTitle : public QWidget { - Q_OBJECT +class VerticalDockTitle : public QWidget +{ + Q_OBJECT public: - VerticalDockTitle(QDockWidget *parent); + VerticalDockTitle(QDockWidget *parent); - virtual QSize sizeHint() const; - virtual QSize minimumSizeHint() const; - void show(bool show_); + virtual QSize sizeHint() const; + virtual QSize minimumSizeHint() const; + void show(bool show_); protected: - virtual void paintEvent(QPaintEvent *event); + virtual void paintEvent(QPaintEvent *event); private: - bool _show; + bool _show; }; -class EmptyDockTitle : public QWidget { - Q_OBJECT + +class EmptyDockTitle : public QWidget +{ + Q_OBJECT public: - inline EmptyDockTitle(QDockWidget *parent) : QWidget(parent) {} + inline EmptyDockTitle(QDockWidget *parent) : QWidget(parent) {} - inline virtual QSize sizeHint() const { return QSize(0,0); } + inline virtual QSize sizeHint() const { return QSize(0, 0); } }; -class VerticalDock : public QDockWidget { - Q_OBJECT +class VerticalDock : public QDockWidget +{ + Q_OBJECT public: - VerticalDock(const QString &title, QWidget *parent = 0, Qt::WindowFlags flags = 0); - VerticalDock(QWidget *parent = 0, Qt::WindowFlags flags = 0); + VerticalDock(const QString &title, QWidget *parent = 0, Qt::WindowFlags flags = 0); + VerticalDock(QWidget *parent = 0, Qt::WindowFlags flags = 0); - void showTitle(bool show); - void setDefaultTitleWidget(); + void showTitle(bool show); + void setDefaultTitleWidget(); }; #endif // VERTICALDOCKTITLE_H - diff --git a/src/qtui/webpreviewitem.cpp b/src/qtui/webpreviewitem.cpp index f674166c..1d27c961 100644 --- a/src/qtui/webpreviewitem.cpp +++ b/src/qtui/webpreviewitem.cpp @@ -28,34 +28,37 @@ #include WebPreviewItem::WebPreviewItem(const QUrl &url) - : QGraphicsItem(0), // needs to be a top level item as we otherwise cannot guarantee that it's on top of other chatlines + : QGraphicsItem(0), // needs to be a top level item as we otherwise cannot guarantee that it's on top of other chatlines _boundingRect(0, 0, 400, 300) { - qreal frameWidth = 5; - - QWebView *webView = new QWebView; - webView->settings()->setAttribute(QWebSettings::JavascriptEnabled, false); - webView->load(url); - webView->resize(1000, 750); - QGraphicsProxyWidget *proxyItem = new QGraphicsProxyWidget(this); - proxyItem->setWidget(webView); - proxyItem->setAcceptHoverEvents(false); - - qreal xScale = (_boundingRect.width() - 2 * frameWidth) / webView->width(); - qreal yScale = (_boundingRect.height() - 2 * frameWidth) / webView->height(); - proxyItem->scale(xScale, yScale); - proxyItem->setPos(frameWidth, frameWidth); - - setZValue(30); + qreal frameWidth = 5; + + QWebView *webView = new QWebView; + webView->settings()->setAttribute(QWebSettings::JavascriptEnabled, false); + webView->load(url); + webView->resize(1000, 750); + QGraphicsProxyWidget *proxyItem = new QGraphicsProxyWidget(this); + proxyItem->setWidget(webView); + proxyItem->setAcceptHoverEvents(false); + + qreal xScale = (_boundingRect.width() - 2 * frameWidth) / webView->width(); + qreal yScale = (_boundingRect.height() - 2 * frameWidth) / webView->height(); + proxyItem->scale(xScale, yScale); + proxyItem->setPos(frameWidth, frameWidth); + + setZValue(30); } -void WebPreviewItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { - Q_UNUSED(option); Q_UNUSED(widget); - painter->setClipRect(boundingRect()); - painter->setPen(QPen(Qt::black, 5)); - painter->setBrush(Qt::black); - painter->setRenderHints(QPainter::Antialiasing); - painter->drawRoundedRect(boundingRect(), 10, 10); + +void WebPreviewItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(option); Q_UNUSED(widget); + painter->setClipRect(boundingRect()); + painter->setPen(QPen(Qt::black, 5)); + painter->setBrush(Qt::black); + painter->setRenderHints(QPainter::Antialiasing); + painter->drawRoundedRect(boundingRect(), 10, 10); } + #endif //#ifdef HAVE_WEBKIT diff --git a/src/qtui/webpreviewitem.h b/src/qtui/webpreviewitem.h index c5bcbb66..2e72c717 100644 --- a/src/qtui/webpreviewitem.h +++ b/src/qtui/webpreviewitem.h @@ -25,15 +25,18 @@ #include -class WebPreviewItem : public QGraphicsItem { +class WebPreviewItem : public QGraphicsItem +{ public: - WebPreviewItem(const QUrl &url); - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - virtual inline QRectF boundingRect() const { return _boundingRect; } + WebPreviewItem(const QUrl &url); + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); + virtual inline QRectF boundingRect() const { return _boundingRect; } private: - QRectF _boundingRect; + QRectF _boundingRect; }; + + #endif //#ifdef HAVE_WEBKIT #endif //WEBPREVIEWITEM_H diff --git a/src/uisupport/abstractbuffercontainer.cpp b/src/uisupport/abstractbuffercontainer.cpp index b002d499..e8f505db 100644 --- a/src/uisupport/abstractbuffercontainer.cpp +++ b/src/uisupport/abstractbuffercontainer.cpp @@ -24,48 +24,56 @@ #include "networkmodel.h" AbstractBufferContainer::AbstractBufferContainer(QWidget *parent) - : AbstractItemView(parent), + : AbstractItemView(parent), _currentBuffer(0) { } -AbstractBufferContainer::~AbstractBufferContainer() { + +AbstractBufferContainer::~AbstractBufferContainer() +{ } -void AbstractBufferContainer::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { - Q_ASSERT(model()); - if(!parent.isValid()) { - // ok this means that whole networks are about to be removed - // we can't determine which buffers are affect, so we hope that all nets are removed - // this is the most common case (for example disconnecting from the core or terminating the client) - if(model()->rowCount(parent) != end - start + 1) - return; - - foreach(BufferId id, _chatViews.keys()) { - removeChatView(id); + +void AbstractBufferContainer::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) +{ + Q_ASSERT(model()); + if (!parent.isValid()) { + // ok this means that whole networks are about to be removed + // we can't determine which buffers are affect, so we hope that all nets are removed + // this is the most common case (for example disconnecting from the core or terminating the client) + if (model()->rowCount(parent) != end - start + 1) + return; + + foreach(BufferId id, _chatViews.keys()) { + removeChatView(id); + } + _chatViews.clear(); } - _chatViews.clear(); - } else { - // check if there are explicitly buffers removed - for(int i = start; i <= end; i++) { - QVariant variant = parent.child(i,0).data(NetworkModel::BufferIdRole); - if(!variant.isValid()) - continue; - - BufferId bufferId = variant.value(); - removeBuffer(bufferId); + else { + // check if there are explicitly buffers removed + for (int i = start; i <= end; i++) { + QVariant variant = parent.child(i, 0).data(NetworkModel::BufferIdRole); + if (!variant.isValid()) + continue; + + BufferId bufferId = variant.value(); + removeBuffer(bufferId); + } } - } } -void AbstractBufferContainer::removeBuffer(BufferId bufferId) { - if(!_chatViews.contains(bufferId)) - return; - removeChatView(bufferId); - _chatViews.take(bufferId); +void AbstractBufferContainer::removeBuffer(BufferId bufferId) +{ + if (!_chatViews.contains(bufferId)) + return; + + removeChatView(bufferId); + _chatViews.take(bufferId); } + /* Switching to first buffer is now handled in MainWin::clientNetworkUpdated() @@ -85,38 +93,41 @@ void AbstractBufferContainer::rowsInserted(const QModelIndex &parent, int start, } */ -void AbstractBufferContainer::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { - Q_UNUSED(previous) - - BufferId newBufferId = current.data(NetworkModel::BufferIdRole).value(); - // To be able to reset the selected buffer, we don't check if buffer/index is valid here - if(currentBuffer() != newBufferId) { - setCurrentBuffer(newBufferId); - emit currentChanged(newBufferId); - emit currentChanged(current); - } +void AbstractBufferContainer::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) +{ + Q_UNUSED(previous) + + BufferId newBufferId = current.data(NetworkModel::BufferIdRole).value(); + // To be able to reset the selected buffer, we don't check if buffer/index is valid here + if (currentBuffer() != newBufferId) { + setCurrentBuffer(newBufferId); + emit currentChanged(newBufferId); + emit currentChanged(current); + } } -void AbstractBufferContainer::setCurrentBuffer(BufferId bufferId) { - BufferId prevBufferId = currentBuffer(); - if(prevBufferId.isValid() && _chatViews.contains(prevBufferId)) { - MsgId msgId = _chatViews.value(prevBufferId)->lastMsgId(); - Client::setBufferLastSeenMsg(prevBufferId, msgId); - } - if(!bufferId.isValid()) { - _currentBuffer = 0; - showChatView(0); - return; - } +void AbstractBufferContainer::setCurrentBuffer(BufferId bufferId) +{ + BufferId prevBufferId = currentBuffer(); + if (prevBufferId.isValid() && _chatViews.contains(prevBufferId)) { + MsgId msgId = _chatViews.value(prevBufferId)->lastMsgId(); + Client::setBufferLastSeenMsg(prevBufferId, msgId); + } + + if (!bufferId.isValid()) { + _currentBuffer = 0; + showChatView(0); + return; + } - if(!_chatViews.contains(bufferId)) - _chatViews[bufferId] = createChatView(bufferId); + if (!_chatViews.contains(bufferId)) + _chatViews[bufferId] = createChatView(bufferId); - _currentBuffer = bufferId; - showChatView(bufferId); - Client::networkModel()->clearBufferActivity(bufferId); - Client::setBufferLastSeenMsg(bufferId, _chatViews[bufferId]->lastMsgId()); - Client::backlogManager()->checkForBacklog(bufferId); - setFocus(); + _currentBuffer = bufferId; + showChatView(bufferId); + Client::networkModel()->clearBufferActivity(bufferId); + Client::setBufferLastSeenMsg(bufferId, _chatViews[bufferId]->lastMsgId()); + Client::backlogManager()->checkForBacklog(bufferId); + setFocus(); } diff --git a/src/uisupport/abstractbuffercontainer.h b/src/uisupport/abstractbuffercontainer.h index 51b9b9ad..249af25a 100644 --- a/src/uisupport/abstractbuffercontainer.h +++ b/src/uisupport/abstractbuffercontainer.h @@ -28,60 +28,63 @@ class AbstractChatView; class AbstractUiMsg; class Buffer; -class AbstractBufferContainer : public AbstractItemView { - Q_OBJECT +class AbstractBufferContainer : public AbstractItemView +{ + Q_OBJECT public: - AbstractBufferContainer(QWidget *parent); - virtual ~AbstractBufferContainer(); + AbstractBufferContainer(QWidget *parent); + virtual ~AbstractBufferContainer(); - inline BufferId currentBuffer() const { return _currentBuffer; } + inline BufferId currentBuffer() const { return _currentBuffer; } signals: - void currentChanged(BufferId); - void currentChanged(const QModelIndex &); + void currentChanged(BufferId); + void currentChanged(const QModelIndex &); protected: - //! Create an AbstractChatView for the given BufferId and add it to the UI if necessary - virtual AbstractChatView *createChatView(BufferId) = 0; + //! Create an AbstractChatView for the given BufferId and add it to the UI if necessary + virtual AbstractChatView *createChatView(BufferId) = 0; - //! Remove a chat view from the UI and delete it - /** This method shall remove the view from the UI (for example, from a QStackedWidget) if appropriate. - * It also shall delete the object afterwards. - * \param view The chat view to be removed and deleted - */ - virtual void removeChatView(BufferId) = 0; + //! Remove a chat view from the UI and delete it + /** This method shall remove the view from the UI (for example, from a QStackedWidget) if appropriate. + * It also shall delete the object afterwards. + * \param view The chat view to be removed and deleted + */ + virtual void removeChatView(BufferId) = 0; - //! If true, the marker line will be set automatically on buffer switch - /** \return Whether the marker line should be set on buffer switch - */ - virtual inline bool autoMarkerLine() const { return true; } + //! If true, the marker line will be set automatically on buffer switch + /** \return Whether the marker line should be set on buffer switch + */ + virtual inline bool autoMarkerLine() const { return true; } protected slots: - virtual void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); - virtual void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); + virtual void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); + virtual void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); - //! Show the given chat view - /** This method is called when the given chat view should be displayed. Use this e.g. for - * selecting the appropriate page in a QStackedWidget. - * \param view The chat view to be displayed. May be 0 if no chat view is selected. - */ - virtual void showChatView(BufferId) = 0; + //! Show the given chat view + /** This method is called when the given chat view should be displayed. Use this e.g. for + * selecting the appropriate page in a QStackedWidget. + * \param view The chat view to be displayed. May be 0 if no chat view is selected. + */ + virtual void showChatView(BufferId) = 0; private slots: - void removeBuffer(BufferId bufferId); - void setCurrentBuffer(BufferId bufferId); + void removeBuffer(BufferId bufferId); + void setCurrentBuffer(BufferId bufferId); private: - BufferId _currentBuffer; - QHash _chatViews; + BufferId _currentBuffer; + QHash _chatViews; }; -class AbstractChatView { +class AbstractChatView +{ public: - virtual ~AbstractChatView() {}; - virtual MsgId lastMsgId() const = 0; + virtual ~AbstractChatView() {}; + virtual MsgId lastMsgId() const = 0; }; + #endif diff --git a/src/uisupport/abstractitemview.cpp b/src/uisupport/abstractitemview.cpp index c3290cb5..dced67b3 100644 --- a/src/uisupport/abstractitemview.cpp +++ b/src/uisupport/abstractitemview.cpp @@ -21,35 +21,36 @@ #include "abstractitemview.h" AbstractItemView::AbstractItemView(QWidget *parent) - : QWidget(parent), + : QWidget(parent), _model(0), _selectionModel(0) { } -void AbstractItemView::setModel(QAbstractItemModel *model) { - if(_model) { - disconnect(_model, 0, this, 0); - } - _model = model; - connect(model, SIGNAL(dataChanged(QModelIndex, QModelIndex)), - this, SLOT(dataChanged(QModelIndex, QModelIndex))); - connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)), - this, SLOT(rowsAboutToBeRemoved(QModelIndex, int, int))); - connect(model, SIGNAL(rowsInserted(QModelIndex, int, int)), - this, SLOT(rowsInserted(QModelIndex, int, int))); -} +void AbstractItemView::setModel(QAbstractItemModel *model) +{ + if (_model) { + disconnect(_model, 0, this, 0); + } + _model = model; + connect(model, SIGNAL(dataChanged(QModelIndex, QModelIndex)), + this, SLOT(dataChanged(QModelIndex, QModelIndex))); + connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)), + this, SLOT(rowsAboutToBeRemoved(QModelIndex, int, int))); + connect(model, SIGNAL(rowsInserted(QModelIndex, int, int)), + this, SLOT(rowsInserted(QModelIndex, int, int))); +} -void AbstractItemView::setSelectionModel(QItemSelectionModel *selectionModel) { - if(_selectionModel) { - disconnect(_selectionModel, 0, this, 0); - } - _selectionModel = selectionModel; - connect(selectionModel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), - this, SLOT(currentChanged(QModelIndex, QModelIndex))); - connect(selectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), - this, SLOT(selectionChanged(QItemSelection, QItemSelection))); +void AbstractItemView::setSelectionModel(QItemSelectionModel *selectionModel) +{ + if (_selectionModel) { + disconnect(_selectionModel, 0, this, 0); + } + _selectionModel = selectionModel; + connect(selectionModel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), + this, SLOT(currentChanged(QModelIndex, QModelIndex))); + connect(selectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), + this, SLOT(selectionChanged(QItemSelection, QItemSelection))); } - diff --git a/src/uisupport/abstractitemview.h b/src/uisupport/abstractitemview.h index 1ddcd440..fe2c8d00 100644 --- a/src/uisupport/abstractitemview.h +++ b/src/uisupport/abstractitemview.h @@ -29,33 +29,35 @@ #include #include -class AbstractItemView : public QWidget { - Q_OBJECT +class AbstractItemView : public QWidget +{ + Q_OBJECT public: - AbstractItemView(QWidget *parent = 0); + AbstractItemView(QWidget *parent = 0); - inline QAbstractItemModel *model() { return _model; } - void setModel(QAbstractItemModel *model); + inline QAbstractItemModel *model() { return _model; } + void setModel(QAbstractItemModel *model); - inline QItemSelectionModel *selectionModel() const { return _selectionModel; } - void setSelectionModel(QItemSelectionModel *selectionModel); + inline QItemSelectionModel *selectionModel() const { return _selectionModel; } + void setSelectionModel(QItemSelectionModel *selectionModel); - inline QModelIndex currentIndex() const { return _selectionModel->currentIndex(); } + inline QModelIndex currentIndex() const { return _selectionModel->currentIndex(); } protected slots: - virtual void closeEditor(QWidget *, QAbstractItemDelegate::EndEditHint) {}; - virtual void commitData(QWidget *) {}; - virtual void currentChanged(const QModelIndex &, const QModelIndex &) {}; - virtual void dataChanged(const QModelIndex &, const QModelIndex &) {}; - virtual void editorDestroyed(QObject *) {}; - virtual void rowsAboutToBeRemoved(const QModelIndex &, int, int) {}; - virtual void rowsInserted(const QModelIndex &, int, int) {}; - virtual void selectionChanged(const QItemSelection &, const QItemSelection &) {}; + virtual void closeEditor(QWidget *, QAbstractItemDelegate::EndEditHint) {}; + virtual void commitData(QWidget *) {}; + virtual void currentChanged(const QModelIndex &, const QModelIndex &) {}; + virtual void dataChanged(const QModelIndex &, const QModelIndex &) {}; + virtual void editorDestroyed(QObject *) {}; + virtual void rowsAboutToBeRemoved(const QModelIndex &, int, int) {}; + virtual void rowsInserted(const QModelIndex &, int, int) {}; + virtual void selectionChanged(const QItemSelection &, const QItemSelection &) {}; protected: - QPointer _model; - QPointer _selectionModel; + QPointer _model; + QPointer _selectionModel; }; + #endif // ABSTRACTITEMVIEW_H diff --git a/src/uisupport/abstractnotificationbackend.h b/src/uisupport/abstractnotificationbackend.h index 3685da21..d1f4b798 100644 --- a/src/uisupport/abstractnotificationbackend.h +++ b/src/uisupport/abstractnotificationbackend.h @@ -28,45 +28,46 @@ class SettingsPage; -class AbstractNotificationBackend : public QObject { - Q_OBJECT +class AbstractNotificationBackend : public QObject +{ + Q_OBJECT public: - enum NotificationType { - Highlight = 0x01, - PrivMsg = 0x02, - HighlightFocused = 0x11, - PrivMsgFocused = 0x12 - }; + enum NotificationType { + Highlight = 0x01, + PrivMsg = 0x02, + HighlightFocused = 0x11, + PrivMsgFocused = 0x12 + }; - struct Notification { - uint notificationId; - BufferId bufferId; - NotificationType type; - QString sender; - QString message; + struct Notification { + uint notificationId; + BufferId bufferId; + NotificationType type; + QString sender; + QString message; - Notification(uint id_, BufferId buf_, NotificationType type_, const QString &sender_, const QString &msg_) - : notificationId(id_), bufferId(buf_), type(type_), sender(sender_), message(msg_) {}; - }; + Notification(uint id_, BufferId buf_, NotificationType type_, const QString &sender_, const QString &msg_) + : notificationId(id_), bufferId(buf_), type(type_), sender(sender_), message(msg_) {}; + }; - inline AbstractNotificationBackend(QObject *parent) : QObject(parent) {}; - virtual ~AbstractNotificationBackend() {}; + inline AbstractNotificationBackend(QObject *parent) : QObject(parent) {}; + virtual ~AbstractNotificationBackend() {}; - virtual void notify(const Notification &) = 0; - virtual void close(uint notificationId) { Q_UNUSED(notificationId); } + virtual void notify(const Notification &) = 0; + virtual void close(uint notificationId) { Q_UNUSED(notificationId); } - //! Factory to create a configuration widget suitable for a specific notification backend - /** - * AbstractNotification will not take ownership of that configWidget! - * In case you need to communicate with the configWidget directly, make your connections here - */ - virtual SettingsPage *createConfigWidget() const = 0; + //! Factory to create a configuration widget suitable for a specific notification backend + /** + * AbstractNotification will not take ownership of that configWidget! + * In case you need to communicate with the configWidget directly, make your connections here + */ + virtual SettingsPage *createConfigWidget() const = 0; signals: - //! May be emitted by the notification to tell the MainWin to raise itself - void activated(uint notificationId = 0); - + //! May be emitted by the notification to tell the MainWin to raise itself + void activated(uint notificationId = 0); }; + #endif diff --git a/src/uisupport/action.cpp b/src/uisupport/action.cpp index 665a5e1b..7c207346 100644 --- a/src/uisupport/action.cpp +++ b/src/uisupport/action.cpp @@ -26,85 +26,102 @@ Action::Action(QObject *parent) #ifdef HAVE_KDE -: KAction(parent) + : KAction(parent) #else -: QWidgetAction(parent) + : QWidgetAction(parent) #endif { - init(); + init(); } + Action::Action(const QString &text, QObject *parent, const QObject *receiver, const char *slot, const QKeySequence &shortcut) #ifdef HAVE_KDE -: KAction(parent) + : KAction(parent) #else -: QWidgetAction(parent) + : QWidgetAction(parent) #endif { - init(); - setText(text); - setShortcut(shortcut); - if(receiver && slot) - connect(this, SIGNAL(triggered()), receiver, slot); + init(); + setText(text); + setShortcut(shortcut); + if (receiver && slot) + connect(this, SIGNAL(triggered()), receiver, slot); } + Action::Action(const QIcon &icon, const QString &text, QObject *parent, const QObject *receiver, const char *slot, const QKeySequence &shortcut) #ifdef HAVE_KDE -: KAction(parent) + : KAction(parent) #else -: QWidgetAction(parent) + : QWidgetAction(parent) #endif { - init(); - setIcon(icon); - setText(text); - setShortcut(shortcut); - if(receiver && slot) - connect(this, SIGNAL(triggered()), receiver, slot); + init(); + setIcon(icon); + setText(text); + setShortcut(shortcut); + if (receiver && slot) + connect(this, SIGNAL(triggered()), receiver, slot); } + #ifdef HAVE_KDE -void Action::init() { } +void Action::init() {} #else -void Action::init() { - connect(this, SIGNAL(triggered(bool)), this, SLOT(slotTriggered())); +void Action::init() +{ + connect(this, SIGNAL(triggered(bool)), this, SLOT(slotTriggered())); - setProperty("isShortcutConfigurable", true); + setProperty("isShortcutConfigurable", true); } -void Action::slotTriggered() { - emit triggered(QApplication::mouseButtons(), QApplication::keyboardModifiers()); + +void Action::slotTriggered() +{ + emit triggered(QApplication::mouseButtons(), QApplication::keyboardModifiers()); } -bool Action::isShortcutConfigurable() const { - return property("isShortcutConfigurable").toBool(); + +bool Action::isShortcutConfigurable() const +{ + return property("isShortcutConfigurable").toBool(); } -void Action::setShortcutConfigurable(bool b) { - setProperty("isShortcutConfigurable", b); + +void Action::setShortcutConfigurable(bool b) +{ + setProperty("isShortcutConfigurable", b); } -QKeySequence Action::shortcut(ShortcutTypes type) const { - Q_ASSERT(type); - if(type == DefaultShortcut) - return property("defaultShortcut").value(); - if(shortcuts().count()) return shortcuts().value(0); - return QKeySequence(); +QKeySequence Action::shortcut(ShortcutTypes type) const +{ + Q_ASSERT(type); + if (type == DefaultShortcut) + return property("defaultShortcut").value(); + + if (shortcuts().count()) return shortcuts().value(0); + return QKeySequence(); } -void Action::setShortcut(const QShortcut &shortcut, ShortcutTypes type) { - setShortcut(shortcut.key(), type); + +void Action::setShortcut(const QShortcut &shortcut, ShortcutTypes type) +{ + setShortcut(shortcut.key(), type); } -void Action::setShortcut(const QKeySequence &key, ShortcutTypes type) { - Q_ASSERT(type); - if(type & DefaultShortcut) - setProperty("defaultShortcut", key); +void Action::setShortcut(const QKeySequence &key, ShortcutTypes type) +{ + Q_ASSERT(type); + + if (type & DefaultShortcut) + setProperty("defaultShortcut", key); - if(type & ActiveShortcut) - QAction::setShortcut(key); + if (type & ActiveShortcut) + QAction::setShortcut(key); } + #endif /* HAVE_KDE */ diff --git a/src/uisupport/action.h b/src/uisupport/action.h index bbf00d2a..146f5ae3 100644 --- a/src/uisupport/action.h +++ b/src/uisupport/action.h @@ -32,17 +32,18 @@ /** This declares/implements a subset of KAction's API (notably we've left out global shortcuts * for now), which should make it easy to plug in KDE support later on. */ -class Action : public QWidgetAction { - Q_OBJECT - - Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut) - Q_PROPERTY(bool shortcutConfigurable READ isShortcutConfigurable WRITE setShortcutConfigurable) - Q_FLAGS(ShortcutType) - - public: - enum ShortcutType { - ActiveShortcut = 0x01, - DefaultShortcut = 0x02 +class Action : public QWidgetAction +{ + Q_OBJECT + + Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut) + Q_PROPERTY(bool shortcutConfigurable READ isShortcutConfigurable WRITE setShortcutConfigurable) + Q_FLAGS(ShortcutType) + +public : + enum ShortcutType { + ActiveShortcut = 0x01, + DefaultShortcut = 0x02 }; Q_DECLARE_FLAGS(ShortcutTypes, ShortcutType) @@ -57,32 +58,36 @@ class Action : public QWidgetAction { bool isShortcutConfigurable() const; void setShortcutConfigurable(bool configurable); - signals: +signals: void triggered(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers); - private: +private: void init(); - private slots: +private slots: void slotTriggered(); }; + Q_DECLARE_OPERATORS_FOR_FLAGS(Action::ShortcutTypes) #else /* HAVE_KDE */ #include -class Action : public KAction { - Q_OBJECT +class Action : public KAction +{ + Q_OBJECT - public: +public: explicit Action(QObject *parent); Action(const QString &text, QObject *parent, const QObject *receiver = 0, const char *slot = 0, const QKeySequence &shortcut = 0); Action(const QIcon &icon, const QString &text, QObject *parent, const QObject *receiver = 0, const char *slot = 0, const QKeySequence &shortcut = 0); - private: +private: void init(); }; + + #endif #endif diff --git a/src/uisupport/actioncollection.cpp b/src/uisupport/actioncollection.cpp index c553554b..0583ce57 100644 --- a/src/uisupport/actioncollection.cpp +++ b/src/uisupport/actioncollection.cpp @@ -30,222 +30,268 @@ #include "action.h" #include "uisettings.h" -ActionCollection::ActionCollection(QObject *parent) : QObject(parent) { - _connectTriggered = _connectHovered = false; +ActionCollection::ActionCollection(QObject *parent) : QObject(parent) +{ + _connectTriggered = _connectHovered = false; } -ActionCollection::~ActionCollection() { +ActionCollection::~ActionCollection() +{ } -void ActionCollection::clear() { - _actionByName.clear(); - qDeleteAll(_actions); - _actions.clear(); -} -QAction *ActionCollection::action(const QString &name) const { - return _actionByName.value(name, 0); +void ActionCollection::clear() +{ + _actionByName.clear(); + qDeleteAll(_actions); + _actions.clear(); } -QList ActionCollection::actions() const { - return _actions; -} -Action *ActionCollection::addAction(const QString &name, Action *action) { - QAction *act = addAction(name, static_cast(action)); - Q_UNUSED(act); - Q_ASSERT(act == action); - return action; +QAction *ActionCollection::action(const QString &name) const +{ + return _actionByName.value(name, 0); } -Action *ActionCollection::addAction(const QString &name, const QObject *receiver, const char *member) { - Action *a = new Action(this); - if(receiver && member) - connect(a, SIGNAL(triggered(bool)), receiver, member); - return addAction(name, a); + +QList ActionCollection::actions() const +{ + return _actions; } -QAction *ActionCollection::addAction(const QString &name, QAction *action) { - if(!action) + +Action *ActionCollection::addAction(const QString &name, Action *action) +{ + QAction *act = addAction(name, static_cast(action)); + Q_UNUSED(act); + Q_ASSERT(act == action); return action; +} - const QString origName = action->objectName(); - QString indexName = name; - if(indexName.isEmpty()) - indexName = action->objectName(); - else - action->setObjectName(indexName); - if(indexName.isEmpty()) - indexName = indexName.sprintf("unnamed-%p", (void *)action); +Action *ActionCollection::addAction(const QString &name, const QObject *receiver, const char *member) +{ + Action *a = new Action(this); + if (receiver && member) + connect(a, SIGNAL(triggered(bool)), receiver, member); + return addAction(name, a); +} - // do we already have this action? - if(_actionByName.value(indexName, 0) == action) - return action; - // or maybe another action under this name? - if(QAction *oldAction = _actionByName.value(indexName)) - takeAction(oldAction); - // do we already have this action under a different name? - int oldIndex = _actions.indexOf(action); - if(oldIndex != -1) { - _actionByName.remove(origName); - _actions.removeAt(oldIndex); - } +QAction *ActionCollection::addAction(const QString &name, QAction *action) +{ + if (!action) + return action; + + const QString origName = action->objectName(); + QString indexName = name; + + if (indexName.isEmpty()) + indexName = action->objectName(); + else + action->setObjectName(indexName); + if (indexName.isEmpty()) + indexName = indexName.sprintf("unnamed-%p", (void *)action); + + // do we already have this action? + if (_actionByName.value(indexName, 0) == action) + return action; + // or maybe another action under this name? + if (QAction *oldAction = _actionByName.value(indexName)) + takeAction(oldAction); + + // do we already have this action under a different name? + int oldIndex = _actions.indexOf(action); + if (oldIndex != -1) { + _actionByName.remove(origName); + _actions.removeAt(oldIndex); + } - // add action - _actionByName.insert(indexName, action); - _actions.append(action); + // add action + _actionByName.insert(indexName, action); + _actions.append(action); - foreach(QWidget *widget, _associatedWidgets) { - widget->addAction(action); - } + foreach(QWidget *widget, _associatedWidgets) { + widget->addAction(action); + } - connect(action, SIGNAL(destroyed(QObject *)), SLOT(actionDestroyed(QObject *))); - if(_connectHovered) - connect(action, SIGNAL(hovered()), SLOT(slotActionHovered())); - if(_connectTriggered) - connect(action, SIGNAL(triggered(bool)), SLOT(slotActionTriggered())); + connect(action, SIGNAL(destroyed(QObject *)), SLOT(actionDestroyed(QObject *))); + if (_connectHovered) + connect(action, SIGNAL(hovered()), SLOT(slotActionHovered())); + if (_connectTriggered) + connect(action, SIGNAL(triggered(bool)), SLOT(slotActionTriggered())); - emit inserted(action); - return action; + emit inserted(action); + return action; } -void ActionCollection::removeAction(QAction *action) { - delete takeAction(action); + +void ActionCollection::removeAction(QAction *action) +{ + delete takeAction(action); } -QAction *ActionCollection::takeAction(QAction *action) { - if(!unlistAction(action)) - return 0; - foreach(QWidget *widget, _associatedWidgets) { - widget->removeAction(action); - } +QAction *ActionCollection::takeAction(QAction *action) +{ + if (!unlistAction(action)) + return 0; + + foreach(QWidget *widget, _associatedWidgets) { + widget->removeAction(action); + } - action->disconnect(this); - return action; + action->disconnect(this); + return action; } -void ActionCollection::readSettings() { - ShortcutSettings s; - QStringList savedShortcuts = s.savedShortcuts(); - foreach(const QString &name, _actionByName.keys()) { - if(!savedShortcuts.contains(name)) - continue; - Action *action = qobject_cast(_actionByName.value(name)); - if(action) - action->setShortcut(s.loadShortcut(name), Action::ActiveShortcut); - } +void ActionCollection::readSettings() +{ + ShortcutSettings s; + QStringList savedShortcuts = s.savedShortcuts(); + + foreach(const QString &name, _actionByName.keys()) { + if (!savedShortcuts.contains(name)) + continue; + Action *action = qobject_cast(_actionByName.value(name)); + if (action) + action->setShortcut(s.loadShortcut(name), Action::ActiveShortcut); + } } -void ActionCollection::writeSettings() const { - ShortcutSettings s; - foreach(const QString &name, _actionByName.keys()) { - Action *action = qobject_cast(_actionByName.value(name)); - if(!action) - continue; - if(!action->isShortcutConfigurable()) - continue; - if(action->shortcut(Action::ActiveShortcut) == action->shortcut(Action::DefaultShortcut)) - continue; - s.saveShortcut(name, action->shortcut(Action::ActiveShortcut)); - } + +void ActionCollection::writeSettings() const +{ + ShortcutSettings s; + foreach(const QString &name, _actionByName.keys()) { + Action *action = qobject_cast(_actionByName.value(name)); + if (!action) + continue; + if (!action->isShortcutConfigurable()) + continue; + if (action->shortcut(Action::ActiveShortcut) == action->shortcut(Action::DefaultShortcut)) + continue; + s.saveShortcut(name, action->shortcut(Action::ActiveShortcut)); + } } -void ActionCollection::slotActionTriggered() { - QAction *action = qobject_cast(sender()); - if(action) - emit actionTriggered(action); + +void ActionCollection::slotActionTriggered() +{ + QAction *action = qobject_cast(sender()); + if (action) + emit actionTriggered(action); } -void ActionCollection::slotActionHovered() { - QAction *action = qobject_cast(sender()); - if(action) - emit actionHovered(action); + +void ActionCollection::slotActionHovered() +{ + QAction *action = qobject_cast(sender()); + if (action) + emit actionHovered(action); } -void ActionCollection::actionDestroyed(QObject *obj) { - // remember that this is not an QAction anymore at this point - QAction *action = static_cast(obj); - unlistAction(action); +void ActionCollection::actionDestroyed(QObject *obj) +{ + // remember that this is not an QAction anymore at this point + QAction *action = static_cast(obj); + + unlistAction(action); } -void ActionCollection::connectNotify(const char *signal) { - if(_connectHovered && _connectTriggered) - return; - if(QMetaObject::normalizedSignature(SIGNAL(actionHovered(QAction*))) == signal) { - if(!_connectHovered) { - _connectHovered = true; - foreach (QAction* action, actions()) - connect(action, SIGNAL(hovered()), SLOT(slotActionHovered())); +void ActionCollection::connectNotify(const char *signal) +{ + if (_connectHovered && _connectTriggered) + return; + + if (QMetaObject::normalizedSignature(SIGNAL(actionHovered(QAction *))) == signal) { + if (!_connectHovered) { + _connectHovered = true; + foreach(QAction* action, actions()) + connect(action, SIGNAL(hovered()), SLOT(slotActionHovered())); + } } - } else if(QMetaObject::normalizedSignature(SIGNAL(actionTriggered(QAction*))) == signal) { - if(!_connectTriggered) { - _connectTriggered = true; - foreach (QAction* action, actions()) - connect(action, SIGNAL(triggered(bool)), SLOT(slotActionTriggered())); + else if (QMetaObject::normalizedSignature(SIGNAL(actionTriggered(QAction *))) == signal) { + if (!_connectTriggered) { + _connectTriggered = true; + foreach(QAction* action, actions()) + connect(action, SIGNAL(triggered(bool)), SLOT(slotActionTriggered())); + } } - } - QObject::connectNotify(signal); + QObject::connectNotify(signal); } -void ActionCollection::associateWidget(QWidget *widget) const { - foreach(QAction *action, actions()) { - if(!widget->actions().contains(action)) - widget->addAction(action); - } + +void ActionCollection::associateWidget(QWidget *widget) const +{ + foreach(QAction *action, actions()) { + if (!widget->actions().contains(action)) + widget->addAction(action); + } } -void ActionCollection::addAssociatedWidget(QWidget *widget) { - if(!_associatedWidgets.contains(widget)) { - widget->addActions(actions()); - _associatedWidgets.append(widget); - connect(widget, SIGNAL(destroyed(QObject *)), SLOT(associatedWidgetDestroyed(QObject *))); - } + +void ActionCollection::addAssociatedWidget(QWidget *widget) +{ + if (!_associatedWidgets.contains(widget)) { + widget->addActions(actions()); + _associatedWidgets.append(widget); + connect(widget, SIGNAL(destroyed(QObject *)), SLOT(associatedWidgetDestroyed(QObject *))); + } } -void ActionCollection::removeAssociatedWidget(QWidget *widget) { - foreach(QAction *action, actions()) + +void ActionCollection::removeAssociatedWidget(QWidget *widget) +{ + foreach(QAction *action, actions()) widget->removeAction(action); - _associatedWidgets.removeAll(widget); - disconnect(widget, SIGNAL(destroyed(QObject *)), this, SLOT(associatedWidgetDestroyed(QObject *))); + _associatedWidgets.removeAll(widget); + disconnect(widget, SIGNAL(destroyed(QObject *)), this, SLOT(associatedWidgetDestroyed(QObject *))); } -QList ActionCollection::associatedWidgets() const { - return _associatedWidgets; + +QList ActionCollection::associatedWidgets() const +{ + return _associatedWidgets; } -void ActionCollection::clearAssociatedWidgets() { - foreach(QWidget *widget, _associatedWidgets) + +void ActionCollection::clearAssociatedWidgets() +{ + foreach(QWidget *widget, _associatedWidgets) foreach(QAction *action, actions()) - widget->removeAction(action); + widget->removeAction(action); - _associatedWidgets.clear(); + _associatedWidgets.clear(); } -void ActionCollection::associatedWidgetDestroyed(QObject *obj) { - _associatedWidgets.removeAll(static_cast(obj)); + +void ActionCollection::associatedWidgetDestroyed(QObject *obj) +{ + _associatedWidgets.removeAll(static_cast(obj)); } -bool ActionCollection::unlistAction(QAction *action) { - // This might be called with a partly destroyed QAction! - int index = _actions.indexOf(action); - if(index == -1) return false; +bool ActionCollection::unlistAction(QAction *action) +{ + // This might be called with a partly destroyed QAction! - QString name = action->objectName(); - _actionByName.remove(name); - _actions.removeAt(index); + int index = _actions.indexOf(action); + if (index == -1) return false; - // TODO: remove from ActionCategory if we ever get that + QString name = action->objectName(); + _actionByName.remove(name); + _actions.removeAt(index); - return true; + // TODO: remove from ActionCategory if we ever get that + + return true; } + #endif /* HAVE_KDE */ diff --git a/src/uisupport/actioncollection.h b/src/uisupport/actioncollection.h index ced9249b..a285d4db 100644 --- a/src/uisupport/actioncollection.h +++ b/src/uisupport/actioncollection.h @@ -36,10 +36,11 @@ class QWidget; class Action; class QAction; -class ActionCollection : public QObject { - Q_OBJECT +class ActionCollection : public QObject +{ + Q_OBJECT - public: +public: explicit ActionCollection(QObject *parent); virtual ~ActionCollection(); @@ -79,29 +80,31 @@ class ActionCollection : public QObject { /// Create new action under the given name, add it to the collection and connect its triggered(bool) signal to the specified receiver. template - ActionType *add(const QString &name, const QObject *receiver = 0, const char *member = 0) { - ActionType *a = new ActionType(this); - if(receiver && member) - connect(a, SIGNAL(triggered(bool)), receiver, member); - addAction(name, a); - return a; + ActionType *add(const QString &name, const QObject *receiver = 0, const char *member = 0) + { + ActionType *a = new ActionType(this); + if (receiver && member) + connect(a, SIGNAL(triggered(bool)), receiver, member); + addAction(name, a); + return a; } - signals: + +signals: void inserted(QAction *action); void actionHovered(QAction *action); void actionTriggered(QAction *action); - protected slots: +protected slots: virtual void connectNotify(const char *signal); virtual void slotActionTriggered(); - private slots: +private slots: void slotActionHovered(); void actionDestroyed(QObject *); void associatedWidgetDestroyed(QObject *); - private: +private: bool unlistAction(QAction *); QMap _actionByName; @@ -112,6 +115,7 @@ class ActionCollection : public QObject { bool _connectTriggered; }; + int ActionCollection::count() const { return actions().count(); } bool ActionCollection::isEmpty() const { return actions().count(); } @@ -119,13 +123,15 @@ bool ActionCollection::isEmpty() const { return actions().count(); } #include -class ActionCollection : public KActionCollection { - Q_OBJECT +class ActionCollection : public KActionCollection +{ + Q_OBJECT - public: +public: explicit ActionCollection(QObject *parent) : KActionCollection(parent) {}; - }; + + #endif #endif diff --git a/src/uisupport/bufferhotlistfilter.cpp b/src/uisupport/bufferhotlistfilter.cpp index 1c262271..6297639d 100644 --- a/src/uisupport/bufferhotlistfilter.cpp +++ b/src/uisupport/bufferhotlistfilter.cpp @@ -23,47 +23,52 @@ #include "networkmodel.h" BufferHotListFilter::BufferHotListFilter(QAbstractItemModel *source, QObject *parent) - : QSortFilterProxyModel(parent) + : QSortFilterProxyModel(parent) { - setSourceModel(source); - setDynamicSortFilter(true); - sort(0, Qt::DescendingOrder); // enable sorting... this is "usually" triggered by a enabling setSortingEnabled(true) on a view; + setSourceModel(source); + setDynamicSortFilter(true); + sort(0, Qt::DescendingOrder); // enable sorting... this is "usually" triggered by a enabling setSortingEnabled(true) on a view; } -bool BufferHotListFilter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { - Q_ASSERT(sourceModel()); - QModelIndex source_index = sourceModel()->index(source_row, 0, source_parent); - MsgId firstUnreadMsgId = sourceModel()->data(source_index, NetworkModel::BufferFirstUnreadMsgIdRole).value(); - if(!firstUnreadMsgId.isValid()) - return false; +bool BufferHotListFilter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const +{ + Q_ASSERT(sourceModel()); + QModelIndex source_index = sourceModel()->index(source_row, 0, source_parent); + + MsgId firstUnreadMsgId = sourceModel()->data(source_index, NetworkModel::BufferFirstUnreadMsgIdRole).value(); + if (!firstUnreadMsgId.isValid()) + return false; - // filter out statusbuffers (it's accessable as networkitem) - BufferInfo::Type bufferType = (BufferInfo::Type)sourceModel()->data(source_index, NetworkModel::BufferTypeRole).toInt(); - if(bufferType == BufferInfo::StatusBuffer) { - NetworkModel::ItemType itemType = (NetworkModel::ItemType)sourceModel()->data(source_index, NetworkModel::ItemTypeRole).toInt(); - return itemType == NetworkModel::NetworkItemType; - } + // filter out statusbuffers (it's accessable as networkitem) + BufferInfo::Type bufferType = (BufferInfo::Type)sourceModel()->data(source_index, NetworkModel::BufferTypeRole).toInt(); + if (bufferType == BufferInfo::StatusBuffer) { + NetworkModel::ItemType itemType = (NetworkModel::ItemType)sourceModel()->data(source_index, NetworkModel::ItemTypeRole).toInt(); + return itemType == NetworkModel::NetworkItemType; + } - return true; + return true; } -bool BufferHotListFilter::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const { - int leftActivity = sourceModel()->data(source_left, NetworkModel::BufferActivityRole).toInt(); - int rightActivity = sourceModel()->data(source_right, NetworkModel::BufferActivityRole).toInt(); - if(leftActivity != rightActivity) - return leftActivity < rightActivity; - MsgId leftUnreadMsgId = sourceModel()->data(source_left, NetworkModel::BufferFirstUnreadMsgIdRole).value(); - MsgId rightUnreadMsgId = sourceModel()->data(source_right, NetworkModel::BufferFirstUnreadMsgIdRole).value(); - return leftUnreadMsgId > rightUnreadMsgId; // newer messages are treated to be "less" +bool BufferHotListFilter::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const +{ + int leftActivity = sourceModel()->data(source_left, NetworkModel::BufferActivityRole).toInt(); + int rightActivity = sourceModel()->data(source_right, NetworkModel::BufferActivityRole).toInt(); + if (leftActivity != rightActivity) + return leftActivity < rightActivity; + + MsgId leftUnreadMsgId = sourceModel()->data(source_left, NetworkModel::BufferFirstUnreadMsgIdRole).value(); + MsgId rightUnreadMsgId = sourceModel()->data(source_right, NetworkModel::BufferFirstUnreadMsgIdRole).value(); + return leftUnreadMsgId > rightUnreadMsgId; // newer messages are treated to be "less" } + // QVariant BufferHotListFilter::data(const QModelIndex &index, int role) const { // QVariant d = QSortFilterProxyModel::data(index, role); // if(role == Qt::DisplayRole) { -// int activity = QSortFilterProxyModel::data(index, NetworkModel::BufferActivityRole).toInt(); +// int activity = QSortFilterProxyModel::data(index, NetworkModel::BufferActivityRole).toInt(); // MsgId unreadMsgId = QSortFilterProxyModel::data(index, NetworkModel::BufferFirstUnreadMsgIdRole).value(); // return QString("%1 %2 %3").arg(d.toString()).arg(activity).arg(unreadMsgId.toInt()); // } diff --git a/src/uisupport/bufferhotlistfilter.h b/src/uisupport/bufferhotlistfilter.h index 72a7f3fb..fe643576 100644 --- a/src/uisupport/bufferhotlistfilter.h +++ b/src/uisupport/bufferhotlistfilter.h @@ -23,18 +23,20 @@ #include -class BufferHotListFilter : public QSortFilterProxyModel { - Q_OBJECT +class BufferHotListFilter : public QSortFilterProxyModel +{ + Q_OBJECT public: - BufferHotListFilter(QAbstractItemModel *source, QObject *parent = 0); + BufferHotListFilter(QAbstractItemModel *source, QObject *parent = 0); - virtual inline int columnCount(const QModelIndex &) const { return 1; } + virtual inline int columnCount(const QModelIndex &) const { return 1; } // QVariant data(const QModelIndex &index, int role) const; protected: - virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; - virtual bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const; + virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; + virtual bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const; }; + #endif //BUFFERHOTLISTFILTER_H diff --git a/src/uisupport/bufferview.cpp b/src/uisupport/bufferview.cpp index 1a183577..3d5b9d94 100644 --- a/src/uisupport/bufferview.cpp +++ b/src/uisupport/bufferview.cpp @@ -47,585 +47,661 @@ // Please be carefull when reimplementing methods which are used to inform the view about changes to the data // to be on the safe side: call QTreeView's method aswell BufferView::BufferView(QWidget *parent) - : QTreeView(parent) + : QTreeView(parent) { - connect(this, SIGNAL(collapsed(const QModelIndex &)), SLOT(storeExpandedState(const QModelIndex &))); - connect(this, SIGNAL(expanded(const QModelIndex &)), SLOT(storeExpandedState(const QModelIndex &))); + connect(this, SIGNAL(collapsed(const QModelIndex &)), SLOT(storeExpandedState(const QModelIndex &))); + connect(this, SIGNAL(expanded(const QModelIndex &)), SLOT(storeExpandedState(const QModelIndex &))); - setSelectionMode(QAbstractItemView::ExtendedSelection); + setSelectionMode(QAbstractItemView::ExtendedSelection); - QAbstractItemDelegate *oldDelegate = itemDelegate(); - BufferViewDelegate *tristateDelegate = new BufferViewDelegate(this); - setItemDelegate(tristateDelegate); - delete oldDelegate; + QAbstractItemDelegate *oldDelegate = itemDelegate(); + BufferViewDelegate *tristateDelegate = new BufferViewDelegate(this); + setItemDelegate(tristateDelegate); + delete oldDelegate; } -void BufferView::init() { - header()->setContextMenuPolicy(Qt::ActionsContextMenu); - hideColumn(1); - hideColumn(2); - setIndentation(10); - expandAll(); +void BufferView::init() +{ + header()->setContextMenuPolicy(Qt::ActionsContextMenu); + hideColumn(1); + hideColumn(2); + setIndentation(10); - header()->hide(); // nobody seems to use this anyway + expandAll(); - // breaks with Qt 4.8 - if(QString("4.8.0") > qVersion()) // FIXME breaks with Qt versions >= 4.10! - setAnimated(true); + header()->hide(); // nobody seems to use this anyway - // FIXME This is to workaround bug #663 - setUniformRowHeights(true); + // breaks with Qt 4.8 + if (QString("4.8.0") > qVersion()) // FIXME breaks with Qt versions >= 4.10! + setAnimated(true); + + // FIXME This is to workaround bug #663 + setUniformRowHeights(true); #ifndef QT_NO_DRAGANDDROP - setDragEnabled(true); - setAcceptDrops(true); - setDropIndicatorShown(true); + setDragEnabled(true); + setAcceptDrops(true); + setDropIndicatorShown(true); #endif - setSortingEnabled(true); - sortByColumn(0, Qt::AscendingOrder); + setSortingEnabled(true); + sortByColumn(0, Qt::AscendingOrder); - // activated() fails on X11 and Qtopia at least + // activated() fails on X11 and Qtopia at least #if defined Q_WS_QWS || defined Q_WS_X11 - disconnect(this, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(joinChannel(QModelIndex))); - connect(this, SIGNAL(doubleClicked(QModelIndex)), SLOT(joinChannel(QModelIndex))); + disconnect(this, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(joinChannel(QModelIndex))); + connect(this, SIGNAL(doubleClicked(QModelIndex)), SLOT(joinChannel(QModelIndex))); #else - // afaik this is better on Mac and Windows - disconnect(this, SIGNAL(activated(QModelIndex)), this, SLOT(joinChannel(QModelIndex))); - connect(this, SIGNAL(activated(QModelIndex)), SLOT(joinChannel(QModelIndex))); + // afaik this is better on Mac and Windows + disconnect(this, SIGNAL(activated(QModelIndex)), this, SLOT(joinChannel(QModelIndex))); + connect(this, SIGNAL(activated(QModelIndex)), SLOT(joinChannel(QModelIndex))); #endif } -void BufferView::setModel(QAbstractItemModel *model) { - delete selectionModel(); - - QTreeView::setModel(model); - init(); - // remove old Actions - QList oldactions = header()->actions(); - foreach(QAction *action, oldactions) { - header()->removeAction(action); - action->deleteLater(); - } - - if(!model) - return; - - QString sectionName; - QAction *showSection; - for(int i = 1; i < model->columnCount(); i++) { - sectionName = (model->headerData(i, Qt::Horizontal, Qt::DisplayRole)).toString(); - showSection = new QAction(sectionName, header()); - showSection->setCheckable(true); - showSection->setChecked(!isColumnHidden(i)); - showSection->setProperty("column", i); - connect(showSection, SIGNAL(toggled(bool)), this, SLOT(toggleHeader(bool))); - header()->addAction(showSection); - } - - connect(model, SIGNAL(layoutChanged()), this, SLOT(on_layoutChanged())); -} - -void BufferView::setFilteredModel(QAbstractItemModel *model_, BufferViewConfig *config) { - BufferViewFilter *filter = qobject_cast(model()); - if(filter) { - filter->setConfig(config); + +void BufferView::setModel(QAbstractItemModel *model) +{ + delete selectionModel(); + + QTreeView::setModel(model); + init(); + // remove old Actions + QList oldactions = header()->actions(); + foreach(QAction *action, oldactions) { + header()->removeAction(action); + action->deleteLater(); + } + + if (!model) + return; + + QString sectionName; + QAction *showSection; + for (int i = 1; i < model->columnCount(); i++) { + sectionName = (model->headerData(i, Qt::Horizontal, Qt::DisplayRole)).toString(); + showSection = new QAction(sectionName, header()); + showSection->setCheckable(true); + showSection->setChecked(!isColumnHidden(i)); + showSection->setProperty("column", i); + connect(showSection, SIGNAL(toggled(bool)), this, SLOT(toggleHeader(bool))); + header()->addAction(showSection); + } + + connect(model, SIGNAL(layoutChanged()), this, SLOT(on_layoutChanged())); +} + + +void BufferView::setFilteredModel(QAbstractItemModel *model_, BufferViewConfig *config) +{ + BufferViewFilter *filter = qobject_cast(model()); + if (filter) { + filter->setConfig(config); + setConfig(config); + return; + } + + if (model()) { + disconnect(this, 0, model(), 0); + disconnect(model(), 0, this, 0); + } + + if (!model_) { + setModel(model_); + } + else { + BufferViewFilter *filter = new BufferViewFilter(model_, config); + setModel(filter); + connect(filter, SIGNAL(configChanged()), this, SLOT(on_configChanged())); + } setConfig(config); - return; - } - - if(model()) { - disconnect(this, 0, model(), 0); - disconnect(model(), 0, this, 0); - } - - if(!model_) { - setModel(model_); - } else { - BufferViewFilter *filter = new BufferViewFilter(model_, config); - setModel(filter); - connect(filter, SIGNAL(configChanged()), this, SLOT(on_configChanged())); - } - setConfig(config); -} - -void BufferView::setSelectionModel(QItemSelectionModel *selectionModel) { - if(QTreeView::selectionModel()) - disconnect(selectionModel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), - model(), SIGNAL(checkPreviousCurrentForRemoval(QModelIndex, QModelIndex))); - - QTreeView::setSelectionModel(selectionModel); - BufferViewFilter *filter = qobject_cast(model()); - if(filter) { - connect(selectionModel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), +} + + +void BufferView::setSelectionModel(QItemSelectionModel *selectionModel) +{ + if (QTreeView::selectionModel()) + disconnect(selectionModel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), + model(), SIGNAL(checkPreviousCurrentForRemoval(QModelIndex, QModelIndex))); + + QTreeView::setSelectionModel(selectionModel); + BufferViewFilter *filter = qobject_cast(model()); + if (filter) { + connect(selectionModel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), filter, SLOT(checkPreviousCurrentForRemoval(QModelIndex, QModelIndex))); - } + } } -void BufferView::setConfig(BufferViewConfig *config) { - if(_config == config) - return; - if(_config) { - disconnect(_config, 0, this, 0); - } +void BufferView::setConfig(BufferViewConfig *config) +{ + if (_config == config) + return; - _config = config; - if(config) { - connect(config, SIGNAL(networkIdSet(const NetworkId &)), this, SLOT(setRootIndexForNetworkId(const NetworkId &))); - setRootIndexForNetworkId(config->networkId()); - } else { - setIndentation(10); - setRootIndex(QModelIndex()); - } + if (_config) { + disconnect(_config, 0, this, 0); + } + + _config = config; + if (config) { + connect(config, SIGNAL(networkIdSet(const NetworkId &)), this, SLOT(setRootIndexForNetworkId(const NetworkId &))); + setRootIndexForNetworkId(config->networkId()); + } + else { + setIndentation(10); + setRootIndex(QModelIndex()); + } } -void BufferView::setRootIndexForNetworkId(const NetworkId &networkId) { - if(!networkId.isValid() || !model()) { - setIndentation(10); - setRootIndex(QModelIndex()); - } else { - setIndentation(5); - int networkCount = model()->rowCount(); - QModelIndex child; - for(int i = 0; i < networkCount; i++) { - child = model()->index(i, 0); - if(networkId == model()->data(child, NetworkModel::NetworkIdRole).value()) - setRootIndex(child); + +void BufferView::setRootIndexForNetworkId(const NetworkId &networkId) +{ + if (!networkId.isValid() || !model()) { + setIndentation(10); + setRootIndex(QModelIndex()); + } + else { + setIndentation(5); + int networkCount = model()->rowCount(); + QModelIndex child; + for (int i = 0; i < networkCount; i++) { + child = model()->index(i, 0); + if (networkId == model()->data(child, NetworkModel::NetworkIdRole).value()) + setRootIndex(child); + } } - } } -void BufferView::joinChannel(const QModelIndex &index) { - BufferInfo::Type bufferType = (BufferInfo::Type)index.data(NetworkModel::BufferTypeRole).value(); - if(bufferType != BufferInfo::ChannelBuffer) - return; +void BufferView::joinChannel(const QModelIndex &index) +{ + BufferInfo::Type bufferType = (BufferInfo::Type)index.data(NetworkModel::BufferTypeRole).value(); + + if (bufferType != BufferInfo::ChannelBuffer) + return; - BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value(); + BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value(); - Client::userInput(bufferInfo, QString("/JOIN %1").arg(bufferInfo.bufferName())); + Client::userInput(bufferInfo, QString("/JOIN %1").arg(bufferInfo.bufferName())); } -void BufferView::keyPressEvent(QKeyEvent *event) { - if(event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete) { - event->accept(); - removeSelectedBuffers(); - } - QTreeView::keyPressEvent(event); + +void BufferView::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete) { + event->accept(); + removeSelectedBuffers(); + } + QTreeView::keyPressEvent(event); } -void BufferView::dropEvent(QDropEvent *event) { - QModelIndex index = indexAt(event->pos()); - QRect indexRect = visualRect(index); - QPoint cursorPos = event->pos(); +void BufferView::dropEvent(QDropEvent *event) +{ + QModelIndex index = indexAt(event->pos()); + + QRect indexRect = visualRect(index); + QPoint cursorPos = event->pos(); - // check if we're really _on_ the item and not indicating a move to just above or below the item - const int margin = 2; - if(cursorPos.y() - indexRect.top() < margin - || indexRect.bottom() - cursorPos.y() < margin) - return QTreeView::dropEvent(event); + // check if we're really _on_ the item and not indicating a move to just above or below the item + const int margin = 2; + if (cursorPos.y() - indexRect.top() < margin + || indexRect.bottom() - cursorPos.y() < margin) + return QTreeView::dropEvent(event); - QList< QPair > bufferList = Client::networkModel()->mimeDataToBufferList(event->mimeData()); - if(bufferList.count() != 1) - return QTreeView::dropEvent(event); + QList > bufferList = Client::networkModel()->mimeDataToBufferList(event->mimeData()); + if (bufferList.count() != 1) + return QTreeView::dropEvent(event); - NetworkId networkId = bufferList[0].first; - BufferId bufferId2 = bufferList[0].second; + NetworkId networkId = bufferList[0].first; + BufferId bufferId2 = bufferList[0].second; - if(index.data(NetworkModel::ItemTypeRole) != NetworkModel::BufferItemType) - return QTreeView::dropEvent(event); + if (index.data(NetworkModel::ItemTypeRole) != NetworkModel::BufferItemType) + return QTreeView::dropEvent(event); - if(index.data(NetworkModel::BufferTypeRole) != BufferInfo::QueryBuffer) - return QTreeView::dropEvent(event); + if (index.data(NetworkModel::BufferTypeRole) != BufferInfo::QueryBuffer) + return QTreeView::dropEvent(event); - if(index.data(NetworkModel::NetworkIdRole).value() != networkId) - return QTreeView::dropEvent(event); + if (index.data(NetworkModel::NetworkIdRole).value() != networkId) + return QTreeView::dropEvent(event); - BufferId bufferId1 = index.data(NetworkModel::BufferIdRole).value(); - if(bufferId1 == bufferId2) - return QTreeView::dropEvent(event); + BufferId bufferId1 = index.data(NetworkModel::BufferIdRole).value(); + if (bufferId1 == bufferId2) + return QTreeView::dropEvent(event); - int res = QMessageBox::question(0, tr("Merge buffers permanently?"), - tr("Do you want to merge the buffer \"%1\" permanently into buffer \"%2\"?\n This cannot be reversed!").arg(Client::networkModel()->bufferName(bufferId2)).arg(Client::networkModel()->bufferName(bufferId1)), - QMessageBox::Yes|QMessageBox::No, QMessageBox::No); - if(res == QMessageBox::Yes) { - Client::mergeBuffersPermanently(bufferId1, bufferId2); - } + int res = QMessageBox::question(0, tr("Merge buffers permanently?"), + tr("Do you want to merge the buffer \"%1\" permanently into buffer \"%2\"?\n This cannot be reversed!").arg(Client::networkModel()->bufferName(bufferId2)).arg(Client::networkModel()->bufferName(bufferId1)), + QMessageBox::Yes|QMessageBox::No, QMessageBox::No); + if (res == QMessageBox::Yes) { + Client::mergeBuffersPermanently(bufferId1, bufferId2); + } } -void BufferView::removeSelectedBuffers(bool permanently) { - if(!config()) - return; - BufferId bufferId; - QSet removedRows; - foreach(QModelIndex index, selectionModel()->selectedIndexes()) { - if(index.data(NetworkModel::ItemTypeRole) != NetworkModel::BufferItemType) - continue; +void BufferView::removeSelectedBuffers(bool permanently) +{ + if (!config()) + return; - bufferId = index.data(NetworkModel::BufferIdRole).value(); - if(removedRows.contains(bufferId)) - continue; + BufferId bufferId; + QSet removedRows; + foreach(QModelIndex index, selectionModel()->selectedIndexes()) { + if (index.data(NetworkModel::ItemTypeRole) != NetworkModel::BufferItemType) + continue; - removedRows << bufferId; - } + bufferId = index.data(NetworkModel::BufferIdRole).value(); + if (removedRows.contains(bufferId)) + continue; - foreach(BufferId bufferId, removedRows) { - if(permanently) - config()->requestRemoveBufferPermanently(bufferId); - else - config()->requestRemoveBuffer(bufferId); - } + removedRows << bufferId; + } + + foreach(BufferId bufferId, removedRows) { + if (permanently) + config()->requestRemoveBufferPermanently(bufferId); + else + config()->requestRemoveBuffer(bufferId); + } } -void BufferView::rowsInserted(const QModelIndex &parent, int start, int end) { - QTreeView::rowsInserted(parent, start, end); - // ensure that newly inserted network nodes are expanded per default - if(parent.data(NetworkModel::ItemTypeRole) != NetworkModel::NetworkItemType) - return; +void BufferView::rowsInserted(const QModelIndex &parent, int start, int end) +{ + QTreeView::rowsInserted(parent, start, end); + + // ensure that newly inserted network nodes are expanded per default + if (parent.data(NetworkModel::ItemTypeRole) != NetworkModel::NetworkItemType) + return; - setExpandedState(parent); + setExpandedState(parent); } -void BufferView::on_layoutChanged() { - int numNets = model()->rowCount(QModelIndex()); - for(int row = 0; row < numNets; row++) { - QModelIndex networkIdx = model()->index(row, 0, QModelIndex()); - setExpandedState(networkIdx); - } + +void BufferView::on_layoutChanged() +{ + int numNets = model()->rowCount(QModelIndex()); + for (int row = 0; row < numNets; row++) { + QModelIndex networkIdx = model()->index(row, 0, QModelIndex()); + setExpandedState(networkIdx); + } } -void BufferView::on_configChanged() { - Q_ASSERT(model()); - // expand all active networks... collapse inactive ones... unless manually changed - QModelIndex networkIdx; - NetworkId networkId; - for(int row = 0; row < model()->rowCount(); row++) { - networkIdx = model()->index(row, 0); - if(model()->rowCount(networkIdx) == 0) - continue; +void BufferView::on_configChanged() +{ + Q_ASSERT(model()); - networkId = model()->data(networkIdx, NetworkModel::NetworkIdRole).value(); - if(!networkId.isValid()) - continue; + // expand all active networks... collapse inactive ones... unless manually changed + QModelIndex networkIdx; + NetworkId networkId; + for (int row = 0; row < model()->rowCount(); row++) { + networkIdx = model()->index(row, 0); + if (model()->rowCount(networkIdx) == 0) + continue; - setExpandedState(networkIdx); - } + networkId = model()->data(networkIdx, NetworkModel::NetworkIdRole).value(); + if (!networkId.isValid()) + continue; - if(config()) { - // update selection to current one - Client::bufferModel()->synchronizeView(this); - } + setExpandedState(networkIdx); + } + + if (config()) { + // update selection to current one + Client::bufferModel()->synchronizeView(this); + } } -void BufferView::storeExpandedState(const QModelIndex &networkIdx) { - NetworkId networkId = model()->data(networkIdx, NetworkModel::NetworkIdRole).value(); - int oldState = 0; - if(isExpanded(networkIdx)) - oldState |= WasExpanded; - if(model()->data(networkIdx, NetworkModel::ItemActiveRole).toBool()) - oldState |= WasActive; +void BufferView::storeExpandedState(const QModelIndex &networkIdx) +{ + NetworkId networkId = model()->data(networkIdx, NetworkModel::NetworkIdRole).value(); + + int oldState = 0; + if (isExpanded(networkIdx)) + oldState |= WasExpanded; + if (model()->data(networkIdx, NetworkModel::ItemActiveRole).toBool()) + oldState |= WasActive; - _expandedState[networkId] = oldState; + _expandedState[networkId] = oldState; } -void BufferView::setExpandedState(const QModelIndex &networkIdx) { - if(model()->data(networkIdx, NetworkModel::ItemTypeRole) != NetworkModel::NetworkItemType) - return; - if(model()->rowCount(networkIdx) == 0) - return; +void BufferView::setExpandedState(const QModelIndex &networkIdx) +{ + if (model()->data(networkIdx, NetworkModel::ItemTypeRole) != NetworkModel::NetworkItemType) + return; + + if (model()->rowCount(networkIdx) == 0) + return; - NetworkId networkId = model()->data(networkIdx, NetworkModel::NetworkIdRole).value(); + NetworkId networkId = model()->data(networkIdx, NetworkModel::NetworkIdRole).value(); - bool networkActive = model()->data(networkIdx, NetworkModel::ItemActiveRole).toBool(); - bool expandNetwork = networkActive; - if(_expandedState.contains(networkId)) { - int oldState = _expandedState[networkId]; - if((bool)(oldState & WasActive) == networkActive) - expandNetwork = (bool)(oldState & WasExpanded); - } + bool networkActive = model()->data(networkIdx, NetworkModel::ItemActiveRole).toBool(); + bool expandNetwork = networkActive; + if (_expandedState.contains(networkId)) { + int oldState = _expandedState[networkId]; + if ((bool)(oldState & WasActive) == networkActive) + expandNetwork = (bool)(oldState & WasExpanded); + } - if(expandNetwork != isExpanded(networkIdx)) { - update(networkIdx); - setExpanded(networkIdx, expandNetwork); - } - storeExpandedState(networkIdx); // this call is needed to keep track of the isActive state + if (expandNetwork != isExpanded(networkIdx)) { + update(networkIdx); + setExpanded(networkIdx, expandNetwork); + } + storeExpandedState(networkIdx); // this call is needed to keep track of the isActive state } -void BufferView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { - QTreeView::dataChanged(topLeft, bottomRight); - // determine how many items have been changed and if any of them is a networkitem - // which just swichted from active to inactive or vice versa - if(topLeft.data(NetworkModel::ItemTypeRole) != NetworkModel::NetworkItemType) - return; +void BufferView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) +{ + QTreeView::dataChanged(topLeft, bottomRight); + + // determine how many items have been changed and if any of them is a networkitem + // which just swichted from active to inactive or vice versa + if (topLeft.data(NetworkModel::ItemTypeRole) != NetworkModel::NetworkItemType) + return; - for(int i = topLeft.row(); i <= bottomRight.row(); i++) { - QModelIndex networkIdx = topLeft.sibling(i, 0); - setExpandedState(networkIdx); - } + for (int i = topLeft.row(); i <= bottomRight.row(); i++) { + QModelIndex networkIdx = topLeft.sibling(i, 0); + setExpandedState(networkIdx); + } } -void BufferView::toggleHeader(bool checked) { - QAction *action = qobject_cast(sender()); - header()->setSectionHidden((action->property("column")).toInt(), !checked); + +void BufferView::toggleHeader(bool checked) +{ + QAction *action = qobject_cast(sender()); + header()->setSectionHidden((action->property("column")).toInt(), !checked); } -void BufferView::contextMenuEvent(QContextMenuEvent *event) { - QModelIndex index = indexAt(event->pos()); - if(!index.isValid()) - index = rootIndex(); - QMenu contextMenu(this); +void BufferView::contextMenuEvent(QContextMenuEvent *event) +{ + QModelIndex index = indexAt(event->pos()); + if (!index.isValid()) + index = rootIndex(); + + QMenu contextMenu(this); - if(index.isValid()) { - addActionsToMenu(&contextMenu, index); - } + if (index.isValid()) { + addActionsToMenu(&contextMenu, index); + } - addFilterActions(&contextMenu, index); + addFilterActions(&contextMenu, index); - if(!contextMenu.actions().isEmpty()) - contextMenu.exec(QCursor::pos()); + if (!contextMenu.actions().isEmpty()) + contextMenu.exec(QCursor::pos()); } -void BufferView::addActionsToMenu(QMenu *contextMenu, const QModelIndex &index) { - QModelIndexList indexList = selectedIndexes(); - // make sure the item we clicked on is first - indexList.removeAll(index); - indexList.prepend(index); - GraphicalUi::contextMenuActionProvider()->addActions(contextMenu, indexList, this, "menuActionTriggered", (bool)config()); +void BufferView::addActionsToMenu(QMenu *contextMenu, const QModelIndex &index) +{ + QModelIndexList indexList = selectedIndexes(); + // make sure the item we clicked on is first + indexList.removeAll(index); + indexList.prepend(index); + + GraphicalUi::contextMenuActionProvider()->addActions(contextMenu, indexList, this, "menuActionTriggered", (bool)config()); } -void BufferView::addFilterActions(QMenu *contextMenu, const QModelIndex &index) { - BufferViewFilter *filter = qobject_cast(model()); - if(filter) { - QList filterActions = filter->actions(index); - if(!filterActions.isEmpty()) { - contextMenu->addSeparator(); - foreach(QAction *action, filterActions) { - contextMenu->addAction(action); - } + +void BufferView::addFilterActions(QMenu *contextMenu, const QModelIndex &index) +{ + BufferViewFilter *filter = qobject_cast(model()); + if (filter) { + QList filterActions = filter->actions(index); + if (!filterActions.isEmpty()) { + contextMenu->addSeparator(); + foreach(QAction *action, filterActions) { + contextMenu->addAction(action); + } + } } - } } -void BufferView::menuActionTriggered(QAction *result) { - ContextMenuActionProvider::ActionType type = (ContextMenuActionProvider::ActionType)result->data().toInt(); - switch(type) { + +void BufferView::menuActionTriggered(QAction *result) +{ + ContextMenuActionProvider::ActionType type = (ContextMenuActionProvider::ActionType)result->data().toInt(); + switch (type) { case ContextMenuActionProvider::HideBufferTemporarily: - removeSelectedBuffers(); - break; + removeSelectedBuffers(); + break; case ContextMenuActionProvider::HideBufferPermanently: - removeSelectedBuffers(true); - break; + removeSelectedBuffers(true); + break; default: - return; - } + return; + } } -void BufferView::nextBuffer() { - changeBuffer(Forward); -} -void BufferView::previousBuffer() { - changeBuffer(Backward); +void BufferView::nextBuffer() +{ + changeBuffer(Forward); } -void BufferView::changeBuffer(Direction direction) { - QModelIndex currentIndex = selectionModel()->currentIndex(); - QModelIndex resultingIndex; - if(currentIndex.parent().isValid()) { - //If we are a child node just switch among siblings unless it's the first/last child - resultingIndex = currentIndex.sibling(currentIndex.row() + direction, 0); +void BufferView::previousBuffer() +{ + changeBuffer(Backward); +} + - if(!resultingIndex.isValid()) { - QModelIndex parent = currentIndex.parent(); - if(direction == Backward) - resultingIndex = parent; - else - resultingIndex = parent.sibling(parent.row() + direction, 0); +void BufferView::changeBuffer(Direction direction) +{ + QModelIndex currentIndex = selectionModel()->currentIndex(); + QModelIndex resultingIndex; + + if (currentIndex.parent().isValid()) { + //If we are a child node just switch among siblings unless it's the first/last child + resultingIndex = currentIndex.sibling(currentIndex.row() + direction, 0); + + if (!resultingIndex.isValid()) { + QModelIndex parent = currentIndex.parent(); + if (direction == Backward) + resultingIndex = parent; + else + resultingIndex = parent.sibling(parent.row() + direction, 0); + } } - } else { - //If we have a toplevel node, try and get an adjacent child - if(direction == Backward) { - QModelIndex newParent = currentIndex.sibling(currentIndex.row() - 1, 0); - if(model()->hasChildren(newParent)) - resultingIndex = newParent.child(model()->rowCount(newParent) - 1, 0); - else - resultingIndex = newParent; - } else { - if(model()->hasChildren(currentIndex)) - resultingIndex = currentIndex.child(0, 0); - else - resultingIndex = currentIndex.sibling(currentIndex.row() + 1, 0); + else { + //If we have a toplevel node, try and get an adjacent child + if (direction == Backward) { + QModelIndex newParent = currentIndex.sibling(currentIndex.row() - 1, 0); + if (model()->hasChildren(newParent)) + resultingIndex = newParent.child(model()->rowCount(newParent) - 1, 0); + else + resultingIndex = newParent; + } + else { + if (model()->hasChildren(currentIndex)) + resultingIndex = currentIndex.child(0, 0); + else + resultingIndex = currentIndex.sibling(currentIndex.row() + 1, 0); + } } - } - if(!resultingIndex.isValid()) - return; + if (!resultingIndex.isValid()) + return; - selectionModel()->setCurrentIndex( resultingIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows ); - selectionModel()->select( resultingIndex, QItemSelectionModel::ClearAndSelect ); + selectionModel()->setCurrentIndex(resultingIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + selectionModel()->select(resultingIndex, QItemSelectionModel::ClearAndSelect); } -void BufferView::wheelEvent(QWheelEvent* event) { - if(ItemViewSettings().mouseWheelChangesBuffer() == (bool)(event->modifiers() & Qt::AltModifier)) - return QTreeView::wheelEvent(event); - int rowDelta = ( event->delta() > 0 ) ? -1 : 1; - changeBuffer((Direction)rowDelta); +void BufferView::wheelEvent(QWheelEvent *event) +{ + if (ItemViewSettings().mouseWheelChangesBuffer() == (bool)(event->modifiers() & Qt::AltModifier)) + return QTreeView::wheelEvent(event); + + int rowDelta = (event->delta() > 0) ? -1 : 1; + changeBuffer((Direction)rowDelta); } -void BufferView::hideCurrentBuffer() { - QModelIndex index = selectionModel()->currentIndex(); - if(index.data(NetworkModel::ItemTypeRole) != NetworkModel::BufferItemType) - return; - BufferId bufferId = index.data(NetworkModel::BufferIdRole).value(); +void BufferView::hideCurrentBuffer() +{ + QModelIndex index = selectionModel()->currentIndex(); + if (index.data(NetworkModel::ItemTypeRole) != NetworkModel::BufferItemType) + return; - //The check above means we won't be looking at a network, which should always be the first row, so we can just go backwards. - changeBuffer(Backward); + BufferId bufferId = index.data(NetworkModel::BufferIdRole).value(); - /*if(removedRows.contains(bufferId)) - continue; + //The check above means we won't be looking at a network, which should always be the first row, so we can just go backwards. + changeBuffer(Backward); - removedRows << bufferId;*/ - /*if(permanently) - config()->requestRemoveBufferPermanently(bufferId); - else*/ - config()->requestRemoveBuffer(bufferId); + /*if(removedRows.contains(bufferId)) + continue; + + removedRows << bufferId;*/ + /*if(permanently) + config()->requestRemoveBufferPermanently(bufferId); + else*/ + config()->requestRemoveBuffer(bufferId); } -QSize BufferView::sizeHint() const { - return QTreeView::sizeHint(); - if(!model()) +QSize BufferView::sizeHint() const +{ return QTreeView::sizeHint(); - if(model()->rowCount() == 0) - return QSize(120, 50); + if (!model()) + return QTreeView::sizeHint(); + + if (model()->rowCount() == 0) + return QSize(120, 50); - int columnSize = 0; - for(int i = 0; i < model()->columnCount(); i++) { - if(!isColumnHidden(i)) - columnSize += sizeHintForColumn(i); - } - return QSize(columnSize, 50); + int columnSize = 0; + for (int i = 0; i < model()->columnCount(); i++) { + if (!isColumnHidden(i)) + columnSize += sizeHintForColumn(i); + } + return QSize(columnSize, 50); } // **************************************** // BufferViewDelgate // **************************************** -class ColorsChangedEvent : public QEvent { +class ColorsChangedEvent : public QEvent +{ public: - ColorsChangedEvent() : QEvent(QEvent::User) {}; + ColorsChangedEvent() : QEvent(QEvent::User) {}; }; + BufferViewDelegate::BufferViewDelegate(QObject *parent) - : QStyledItemDelegate(parent) + : QStyledItemDelegate(parent) { } -void BufferViewDelegate::customEvent(QEvent *event) { - if(event->type() != QEvent::User) - return; - event->accept(); +void BufferViewDelegate::customEvent(QEvent *event) +{ + if (event->type() != QEvent::User) + return; + + event->accept(); } -bool BufferViewDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) { - if(event->type() != QEvent::MouseButtonRelease) - return QStyledItemDelegate::editorEvent(event, model, option, index); - if(!(model->flags(index) & Qt::ItemIsUserCheckable)) - return QStyledItemDelegate::editorEvent(event, model, option, index); +bool BufferViewDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) +{ + if (event->type() != QEvent::MouseButtonRelease) + return QStyledItemDelegate::editorEvent(event, model, option, index); + + if (!(model->flags(index) & Qt::ItemIsUserCheckable)) + return QStyledItemDelegate::editorEvent(event, model, option, index); - QVariant value = index.data(Qt::CheckStateRole); - if(!value.isValid()) - return QStyledItemDelegate::editorEvent(event, model, option, index); + QVariant value = index.data(Qt::CheckStateRole); + if (!value.isValid()) + return QStyledItemDelegate::editorEvent(event, model, option, index); - QStyleOptionViewItemV4 viewOpt(option); - initStyleOption(&viewOpt, index); + QStyleOptionViewItemV4 viewOpt(option); + initStyleOption(&viewOpt, index); - QRect checkRect = viewOpt.widget->style()->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &viewOpt, viewOpt.widget); - QMouseEvent *me = static_cast(event); + QRect checkRect = viewOpt.widget->style()->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &viewOpt, viewOpt.widget); + QMouseEvent *me = static_cast(event); - if(me->button() != Qt::LeftButton || !checkRect.contains(me->pos())) - return QStyledItemDelegate::editorEvent(event, model, option, index); + if (me->button() != Qt::LeftButton || !checkRect.contains(me->pos())) + return QStyledItemDelegate::editorEvent(event, model, option, index); - Qt::CheckState state = static_cast(value.toInt()); - if(state == Qt::Unchecked) - state = Qt::PartiallyChecked; - else if(state == Qt::PartiallyChecked) - state = Qt::Checked; - else - state = Qt::Unchecked; - model->setData(index, state, Qt::CheckStateRole); - return true; + Qt::CheckState state = static_cast(value.toInt()); + if (state == Qt::Unchecked) + state = Qt::PartiallyChecked; + else if (state == Qt::PartiallyChecked) + state = Qt::Checked; + else + state = Qt::Unchecked; + model->setData(index, state, Qt::CheckStateRole); + return true; } + // ============================== // BufferView Dock // ============================== BufferViewDock::BufferViewDock(BufferViewConfig *config, QWidget *parent) - : QDockWidget(parent), + : QDockWidget(parent), _active(false), _title(config->bufferViewName()) { - setObjectName("BufferViewDock-" + QString::number(config->bufferViewId())); - toggleViewAction()->setData(config->bufferViewId()); - setAllowedAreas(Qt::RightDockWidgetArea|Qt::LeftDockWidgetArea); - connect(config, SIGNAL(bufferViewNameSet(const QString &)), this, SLOT(bufferViewRenamed(const QString &))); - updateTitle(); + setObjectName("BufferViewDock-" + QString::number(config->bufferViewId())); + toggleViewAction()->setData(config->bufferViewId()); + setAllowedAreas(Qt::RightDockWidgetArea|Qt::LeftDockWidgetArea); + connect(config, SIGNAL(bufferViewNameSet(const QString &)), this, SLOT(bufferViewRenamed(const QString &))); + updateTitle(); +} + + +void BufferViewDock::updateTitle() +{ + QString title = _title; + if (isActive()) + title.prepend(QString::fromUtf8("• ")); + setWindowTitle(title); } -void BufferViewDock::updateTitle() { - QString title = _title; - if(isActive()) - title.prepend(QString::fromUtf8("• ")); - setWindowTitle(title); + +void BufferViewDock::setActive(bool active) +{ + if (active != isActive()) { + _active = active; + updateTitle(); + if (active) + raise(); // for tabbed docks + } } -void BufferViewDock::setActive(bool active) { - if(active != isActive()) { - _active = active; + +void BufferViewDock::bufferViewRenamed(const QString &newName) +{ + _title = newName; updateTitle(); - if(active) - raise(); // for tabbed docks - } + toggleViewAction()->setText(newName); } -void BufferViewDock::bufferViewRenamed(const QString &newName) { - _title = newName; - updateTitle(); - toggleViewAction()->setText(newName); -} -int BufferViewDock::bufferViewId() const { - BufferView *view = bufferView(); - if(!view) - return 0; +int BufferViewDock::bufferViewId() const +{ + BufferView *view = bufferView(); + if (!view) + return 0; - if(view->config()) - return view->config()->bufferViewId(); - else - return 0; + if (view->config()) + return view->config()->bufferViewId(); + else + return 0; } -BufferViewConfig *BufferViewDock::config() const { - BufferView *view = bufferView(); - if(!view) - return 0; - else - return view->config(); + +BufferViewConfig *BufferViewDock::config() const +{ + BufferView *view = bufferView(); + if (!view) + return 0; + else + return view->config(); } diff --git a/src/uisupport/bufferview.h b/src/uisupport/bufferview.h index 011deaba..1ff1178f 100644 --- a/src/uisupport/bufferview.h +++ b/src/uisupport/bufferview.h @@ -37,114 +37,119 @@ /***************************************** * The TreeView showing the Buffers *****************************************/ -class BufferView : public QTreeView { - Q_OBJECT +class BufferView : public QTreeView +{ + Q_OBJECT public: - enum Direction { - Forward = 1, - Backward = -1 - }; + enum Direction { + Forward = 1, + Backward = -1 + }; - BufferView(QWidget *parent = 0); - void init(); + BufferView(QWidget *parent = 0); + void init(); - void setModel(QAbstractItemModel *model); - void setFilteredModel(QAbstractItemModel *model, BufferViewConfig *config); - virtual void setSelectionModel(QItemSelectionModel *selectionModel); + void setModel(QAbstractItemModel *model); + void setFilteredModel(QAbstractItemModel *model, BufferViewConfig *config); + virtual void setSelectionModel(QItemSelectionModel *selectionModel); - void setConfig(BufferViewConfig *config); - inline BufferViewConfig *config() { return _config; } + void setConfig(BufferViewConfig *config); + inline BufferViewConfig *config() { return _config; } - void addActionsToMenu(QMenu *menu, const QModelIndex &index); - void addFilterActions(QMenu *contextMenu, const QModelIndex &index); + void addActionsToMenu(QMenu *menu, const QModelIndex &index); + void addFilterActions(QMenu *contextMenu, const QModelIndex &index); public slots: - void setRootIndexForNetworkId(const NetworkId &networkId); - void removeSelectedBuffers(bool permanently = false); - void menuActionTriggered(QAction *); - void nextBuffer(); - void previousBuffer(); - void hideCurrentBuffer(); + void setRootIndexForNetworkId(const NetworkId &networkId); + void removeSelectedBuffers(bool permanently = false); + void menuActionTriggered(QAction *); + void nextBuffer(); + void previousBuffer(); + void hideCurrentBuffer(); signals: - void removeBuffer(const QModelIndex &); - void removeBufferPermanently(const QModelIndex &); + void removeBuffer(const QModelIndex &); + void removeBufferPermanently(const QModelIndex &); protected: - virtual void keyPressEvent(QKeyEvent *); - virtual void dropEvent(QDropEvent *event); - virtual void rowsInserted(const QModelIndex & parent, int start, int end); - virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); - virtual void wheelEvent(QWheelEvent *); - virtual QSize sizeHint() const; - virtual void focusInEvent(QFocusEvent *event) { QAbstractScrollArea::focusInEvent(event); } - virtual void contextMenuEvent(QContextMenuEvent *event); + virtual void keyPressEvent(QKeyEvent *); + virtual void dropEvent(QDropEvent *event); + virtual void rowsInserted(const QModelIndex &parent, int start, int end); + virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + virtual void wheelEvent(QWheelEvent *); + virtual QSize sizeHint() const; + virtual void focusInEvent(QFocusEvent *event) { QAbstractScrollArea::focusInEvent(event); } + virtual void contextMenuEvent(QContextMenuEvent *event); private slots: - void joinChannel(const QModelIndex &index); - void toggleHeader(bool checked); + void joinChannel(const QModelIndex &index); + void toggleHeader(bool checked); - void storeExpandedState(const QModelIndex &networkIdx); - void setExpandedState(const QModelIndex &networkIdx); + void storeExpandedState(const QModelIndex &networkIdx); + void setExpandedState(const QModelIndex &networkIdx); - void on_configChanged(); - void on_layoutChanged(); + void on_configChanged(); + void on_layoutChanged(); - void changeBuffer(Direction direction); + void changeBuffer(Direction direction); private: - QPointer _config; - - enum ExpandedState { - WasExpanded = 0x01, - WasActive = 0x02 - }; - QHash _expandedState; + QPointer _config; + enum ExpandedState { + WasExpanded = 0x01, + WasActive = 0x02 + }; + QHash _expandedState; }; + // ****************************** // BufferViewDelgate // ****************************** -class BufferViewDelegate : public QStyledItemDelegate { - Q_OBJECT +class BufferViewDelegate : public QStyledItemDelegate +{ + Q_OBJECT public: - BufferViewDelegate(QObject *parent = 0); - bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index); + BufferViewDelegate(QObject *parent = 0); + bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index); protected: - virtual void customEvent(QEvent *event); + virtual void customEvent(QEvent *event); }; + // ============================== // BufferView Dock // ============================== -class BufferViewDock : public QDockWidget { - Q_OBJECT - Q_PROPERTY(bool active READ isActive WRITE setActive STORED true) +class BufferViewDock : public QDockWidget +{ + Q_OBJECT + Q_PROPERTY(bool active READ isActive WRITE setActive STORED true) -public: - BufferViewDock(BufferViewConfig *config, QWidget *parent); +public : + BufferViewDock(BufferViewConfig *config, QWidget *parent); - int bufferViewId() const; - BufferViewConfig *config() const; - inline BufferView *bufferView() const { return qobject_cast(widget()); } - inline bool isActive() const { return _active; } + int bufferViewId() const; + BufferViewConfig *config() const; + inline BufferView *bufferView() const { return qobject_cast(widget()); } + inline bool isActive() const { return _active; } public slots: - void setActive(bool active = true); + void setActive(bool active = true); private slots: - void bufferViewRenamed(const QString &newName); - void updateTitle(); + void bufferViewRenamed(const QString &newName); + void updateTitle(); private: - bool _active; - QString _title; + bool _active; + QString _title; }; + #endif diff --git a/src/uisupport/bufferviewfilter.cpp b/src/uisupport/bufferviewfilter.cpp index 3732d2d2..2919be61 100644 --- a/src/uisupport/bufferviewfilter.cpp +++ b/src/uisupport/bufferviewfilter.cpp @@ -34,72 +34,79 @@ #include "networkmodel.h" #include "uistyle.h" -class CheckRemovalEvent : public QEvent { +class CheckRemovalEvent : public QEvent +{ public: - CheckRemovalEvent(const QModelIndex &source_index) : QEvent(QEvent::User), index(source_index) {}; - QPersistentModelIndex index; + CheckRemovalEvent(const QModelIndex &source_index) : QEvent(QEvent::User), index(source_index) {}; + QPersistentModelIndex index; }; + /***************************************** * The Filter for the Tree View *****************************************/ BufferViewFilter::BufferViewFilter(QAbstractItemModel *model, BufferViewConfig *config) - : QSortFilterProxyModel(model), + : QSortFilterProxyModel(model), _config(0), _sortOrder(Qt::AscendingOrder), _showServerQueries(false), _editMode(false), _enableEditMode(tr("Show / Hide Chats"), this) { - setConfig(config); - setSourceModel(model); + setConfig(config); + setSourceModel(model); - setDynamicSortFilter(true); + setDynamicSortFilter(true); - connect(this, SIGNAL(_dataChanged(const QModelIndex &, const QModelIndex &)), - this, SLOT(_q_sourceDataChanged(QModelIndex,QModelIndex))); + connect(this, SIGNAL(_dataChanged(const QModelIndex &, const QModelIndex &)), + this, SLOT(_q_sourceDataChanged(QModelIndex, QModelIndex))); - _enableEditMode.setCheckable(true); - _enableEditMode.setChecked(_editMode); - connect(&_enableEditMode, SIGNAL(toggled(bool)), this, SLOT(enableEditMode(bool))); + _enableEditMode.setCheckable(true); + _enableEditMode.setChecked(_editMode); + connect(&_enableEditMode, SIGNAL(toggled(bool)), this, SLOT(enableEditMode(bool))); - BufferSettings defaultSettings; - defaultSettings.notify("ServerNoticesTarget", this, SLOT(showServerQueriesChanged())); - showServerQueriesChanged(); + BufferSettings defaultSettings; + defaultSettings.notify("ServerNoticesTarget", this, SLOT(showServerQueriesChanged())); + showServerQueriesChanged(); } -void BufferViewFilter::setConfig(BufferViewConfig *config) { - if(_config == config) - return; - if(_config) { - disconnect(_config, 0, this, 0); - } +void BufferViewFilter::setConfig(BufferViewConfig *config) +{ + if (_config == config) + return; - _config = config; + if (_config) { + disconnect(_config, 0, this, 0); + } - if(!config) { - invalidate(); - setObjectName(""); - return; - } - - if(config->isInitialized()) { - configInitialized(); - } else { - // we use a queued connection here since manipulating the connection list of a sending object - // doesn't seem to be such a good idea while executing a connected slots. - connect(config, SIGNAL(initDone()), this, SLOT(configInitialized()), Qt::QueuedConnection); - invalidate(); - } + _config = config; + + if (!config) { + invalidate(); + setObjectName(""); + return; + } + + if (config->isInitialized()) { + configInitialized(); + } + else { + // we use a queued connection here since manipulating the connection list of a sending object + // doesn't seem to be such a good idea while executing a connected slots. + connect(config, SIGNAL(initDone()), this, SLOT(configInitialized()), Qt::QueuedConnection); + invalidate(); + } } -void BufferViewFilter::configInitialized() { - if(!config()) - return; + +void BufferViewFilter::configInitialized() +{ + if (!config()) + return; // connect(config(), SIGNAL(bufferViewNameSet(const QString &)), this, SLOT(invalidate())); - connect(config(), SIGNAL(configChanged()), this, SLOT(invalidate())); + connect(config(), SIGNAL(configChanged()), this, SLOT(invalidate())); // connect(config(), SIGNAL(networkIdSet(const NetworkId &)), this, SLOT(invalidate())); // connect(config(), SIGNAL(addNewBuffersAutomaticallySet(bool)), this, SLOT(invalidate())); // connect(config(), SIGNAL(sortAlphabeticallySet(bool)), this, SLOT(invalidate())); @@ -112,422 +119,468 @@ void BufferViewFilter::configInitialized() { // connect(config(), SIGNAL(bufferRemoved(const BufferId &)), this, SLOT(invalidate())); // connect(config(), SIGNAL(bufferPermanentlyRemoved(const BufferId &)), this, SLOT(invalidate())); - disconnect(config(), SIGNAL(initDone()), this, SLOT(configInitialized())); + disconnect(config(), SIGNAL(initDone()), this, SLOT(configInitialized())); - setObjectName(config()->bufferViewName()); + setObjectName(config()->bufferViewName()); - invalidate(); - emit configChanged(); + invalidate(); + emit configChanged(); } -void BufferViewFilter::showServerQueriesChanged() { - BufferSettings bufferSettings; - bool showQueries = (bufferSettings.serverNoticesTarget() & BufferSettings::DefaultBuffer); - if(_showServerQueries != showQueries) { - _showServerQueries = showQueries; - invalidate(); - } +void BufferViewFilter::showServerQueriesChanged() +{ + BufferSettings bufferSettings; + + bool showQueries = (bufferSettings.serverNoticesTarget() & BufferSettings::DefaultBuffer); + if (_showServerQueries != showQueries) { + _showServerQueries = showQueries; + invalidate(); + } } -QList BufferViewFilter::actions(const QModelIndex &index) { - Q_UNUSED(index) - QList actionList; - actionList << &_enableEditMode; - return actionList; + +QList BufferViewFilter::actions(const QModelIndex &index) +{ + Q_UNUSED(index) + QList actionList; + actionList << &_enableEditMode; + return actionList; } -void BufferViewFilter::enableEditMode(bool enable) { - if(_editMode == enable) { - return; - } - _editMode = enable; - - if(!config()) - return; - - if(enable == false) { - addBuffers(QList::fromSet(_toAdd)); - QSet::const_iterator iter; - for(iter = _toTempRemove.constBegin(); iter != _toTempRemove.constEnd(); iter++) { - if(config()->temporarilyRemovedBuffers().contains(*iter)) - continue; - config()->requestRemoveBuffer(*iter); + +void BufferViewFilter::enableEditMode(bool enable) +{ + if (_editMode == enable) { + return; } - for(iter = _toRemove.constBegin(); iter != _toRemove.constEnd(); iter++) { - if(config()->removedBuffers().contains(*iter)) - continue; - config()->requestRemoveBufferPermanently(*iter); + _editMode = enable; + + if (!config()) + return; + + if (enable == false) { + addBuffers(QList::fromSet(_toAdd)); + QSet::const_iterator iter; + for (iter = _toTempRemove.constBegin(); iter != _toTempRemove.constEnd(); iter++) { + if (config()->temporarilyRemovedBuffers().contains(*iter)) + continue; + config()->requestRemoveBuffer(*iter); + } + for (iter = _toRemove.constBegin(); iter != _toRemove.constEnd(); iter++) { + if (config()->removedBuffers().contains(*iter)) + continue; + config()->requestRemoveBufferPermanently(*iter); + } } - } - _toAdd.clear(); - _toTempRemove.clear(); - _toRemove.clear(); + _toAdd.clear(); + _toTempRemove.clear(); + _toRemove.clear(); - invalidate(); + invalidate(); } -Qt::ItemFlags BufferViewFilter::flags(const QModelIndex &index) const { - QModelIndex source_index = mapToSource(index); - Qt::ItemFlags flags = sourceModel()->flags(source_index); - if(config()) { - NetworkModel::ItemType itemType = (NetworkModel::ItemType)sourceModel()->data(source_index, NetworkModel::ItemTypeRole).toInt(); - BufferInfo::Type bufferType = (BufferInfo::Type)sourceModel()->data(source_index, NetworkModel::BufferTypeRole).toInt(); - if(source_index == QModelIndex() || itemType == NetworkModel::NetworkItemType) { - flags |= Qt::ItemIsDropEnabled; - } else if(_editMode) { - flags |= Qt::ItemIsUserCheckable | Qt::ItemIsTristate; - } - - // prohibit dragging of most items. and most drop places - // only query to query is allowed for merging - if(bufferType != BufferInfo::QueryBuffer) { - ClientBufferViewConfig *clientConf = qobject_cast(config()); - if(clientConf && clientConf->isLocked()) { - flags &= ~(Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled); - } +Qt::ItemFlags BufferViewFilter::flags(const QModelIndex &index) const +{ + QModelIndex source_index = mapToSource(index); + Qt::ItemFlags flags = sourceModel()->flags(source_index); + if (config()) { + NetworkModel::ItemType itemType = (NetworkModel::ItemType)sourceModel()->data(source_index, NetworkModel::ItemTypeRole).toInt(); + BufferInfo::Type bufferType = (BufferInfo::Type)sourceModel()->data(source_index, NetworkModel::BufferTypeRole).toInt(); + if (source_index == QModelIndex() || itemType == NetworkModel::NetworkItemType) { + flags |= Qt::ItemIsDropEnabled; + } + else if (_editMode) { + flags |= Qt::ItemIsUserCheckable | Qt::ItemIsTristate; + } + + // prohibit dragging of most items. and most drop places + // only query to query is allowed for merging + if (bufferType != BufferInfo::QueryBuffer) { + ClientBufferViewConfig *clientConf = qobject_cast(config()); + if (clientConf && clientConf->isLocked()) { + flags &= ~(Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled); + } + } } - } - return flags; + return flags; } -bool BufferViewFilter::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) { - if(!config() || !NetworkModel::mimeContainsBufferList(data)) - return QSortFilterProxyModel::dropMimeData(data, action, row, column, parent); - - NetworkId droppedNetworkId; - QModelIndex source_parent = mapToSource(parent); - if(sourceModel()->data(source_parent, NetworkModel::ItemTypeRole) == NetworkModel::NetworkItemType) - droppedNetworkId = sourceModel()->data(source_parent, NetworkModel::NetworkIdRole).value(); - - QList< QPair > bufferList = NetworkModel::mimeDataToBufferList(data); - BufferId bufferId; - NetworkId networkId; - int pos; - for(int i = 0; i < bufferList.count(); i++) { - networkId = bufferList[i].first; - bufferId = bufferList[i].second; - if(droppedNetworkId == networkId) { - if(row < 0) - row = 0; - - if(row < rowCount(parent)) { - QModelIndex source_child = mapToSource(index(row, 0, parent)); - BufferId beforeBufferId = sourceModel()->data(source_child, NetworkModel::BufferIdRole).value(); - pos = config()->bufferList().indexOf(beforeBufferId); - if(_sortOrder == Qt::DescendingOrder) - pos++; - } else { - if(_sortOrder == Qt::AscendingOrder) - pos = config()->bufferList().count(); - else - pos = 0; - } - - if(config()->bufferList().contains(bufferId) && !config()->sortAlphabetically()) { - if(config()->bufferList().indexOf(bufferId) < pos) - pos--; - ClientBufferViewConfig *clientConf = qobject_cast(config()); - if(!clientConf || !clientConf->isLocked()) - config()->requestMoveBuffer(bufferId, pos); - } else { - config()->requestAddBuffer(bufferId, pos); - } - } else { - addBuffer(bufferId); +bool BufferViewFilter::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) +{ + if (!config() || !NetworkModel::mimeContainsBufferList(data)) + return QSortFilterProxyModel::dropMimeData(data, action, row, column, parent); + + NetworkId droppedNetworkId; + QModelIndex source_parent = mapToSource(parent); + if (sourceModel()->data(source_parent, NetworkModel::ItemTypeRole) == NetworkModel::NetworkItemType) + droppedNetworkId = sourceModel()->data(source_parent, NetworkModel::NetworkIdRole).value(); + + QList > bufferList = NetworkModel::mimeDataToBufferList(data); + BufferId bufferId; + NetworkId networkId; + int pos; + for (int i = 0; i < bufferList.count(); i++) { + networkId = bufferList[i].first; + bufferId = bufferList[i].second; + if (droppedNetworkId == networkId) { + if (row < 0) + row = 0; + + if (row < rowCount(parent)) { + QModelIndex source_child = mapToSource(index(row, 0, parent)); + BufferId beforeBufferId = sourceModel()->data(source_child, NetworkModel::BufferIdRole).value(); + pos = config()->bufferList().indexOf(beforeBufferId); + if (_sortOrder == Qt::DescendingOrder) + pos++; + } + else { + if (_sortOrder == Qt::AscendingOrder) + pos = config()->bufferList().count(); + else + pos = 0; + } + + if (config()->bufferList().contains(bufferId) && !config()->sortAlphabetically()) { + if (config()->bufferList().indexOf(bufferId) < pos) + pos--; + ClientBufferViewConfig *clientConf = qobject_cast(config()); + if (!clientConf || !clientConf->isLocked()) + config()->requestMoveBuffer(bufferId, pos); + } + else { + config()->requestAddBuffer(bufferId, pos); + } + } + else { + addBuffer(bufferId); + } } - } - return true; + return true; } -void BufferViewFilter::sort(int column, Qt::SortOrder order) { - _sortOrder = order; - QSortFilterProxyModel::sort(column, order); + +void BufferViewFilter::sort(int column, Qt::SortOrder order) +{ + _sortOrder = order; + QSortFilterProxyModel::sort(column, order); } -void BufferViewFilter::addBuffer(const BufferId &bufferId) const { - if(!config() || config()->bufferList().contains(bufferId)) - return; - int pos = config()->bufferList().count(); - bool lt; - for(int i = 0; i < config()->bufferList().count(); i++) { - if(config() && config()->sortAlphabetically()) - lt = bufferIdLessThan(bufferId, config()->bufferList()[i]); - else - lt = bufferId < config()->bufferList()[i]; +void BufferViewFilter::addBuffer(const BufferId &bufferId) const +{ + if (!config() || config()->bufferList().contains(bufferId)) + return; + + int pos = config()->bufferList().count(); + bool lt; + for (int i = 0; i < config()->bufferList().count(); i++) { + if (config() && config()->sortAlphabetically()) + lt = bufferIdLessThan(bufferId, config()->bufferList()[i]); + else + lt = bufferId < config()->bufferList()[i]; - if(lt) { - pos = i; - break; + if (lt) { + pos = i; + break; + } } - } - config()->requestAddBuffer(bufferId, pos); + config()->requestAddBuffer(bufferId, pos); } -void BufferViewFilter::addBuffers(const QList &bufferIds) const { - if(!config()) - return; - - QList bufferList = config()->bufferList(); - foreach(BufferId bufferId, bufferIds) { - if(bufferList.contains(bufferId)) - continue; - int pos = bufferList.count(); - bool lt; - for(int i = 0; i < bufferList.count(); i++) { - if(config() && config()->sortAlphabetically()) - lt = bufferIdLessThan(bufferId, bufferList[i]); - else - lt = bufferId < config()->bufferList()[i]; - - if(lt) { - pos = i; - bufferList.insert(pos, bufferId); - break; - } +void BufferViewFilter::addBuffers(const QList &bufferIds) const +{ + if (!config()) + return; + + QList bufferList = config()->bufferList(); + foreach(BufferId bufferId, bufferIds) { + if (bufferList.contains(bufferId)) + continue; + + int pos = bufferList.count(); + bool lt; + for (int i = 0; i < bufferList.count(); i++) { + if (config() && config()->sortAlphabetically()) + lt = bufferIdLessThan(bufferId, bufferList[i]); + else + lt = bufferId < config()->bufferList()[i]; + + if (lt) { + pos = i; + bufferList.insert(pos, bufferId); + break; + } + } + config()->requestAddBuffer(bufferId, pos); } - config()->requestAddBuffer(bufferId, pos); - } } -bool BufferViewFilter::filterAcceptBuffer(const QModelIndex &source_bufferIndex) const { - // no config -> "all buffers" -> accept everything - if(!config()) - return true; - BufferId bufferId = sourceModel()->data(source_bufferIndex, NetworkModel::BufferIdRole).value(); - Q_ASSERT(bufferId.isValid()); +bool BufferViewFilter::filterAcceptBuffer(const QModelIndex &source_bufferIndex) const +{ + // no config -> "all buffers" -> accept everything + if (!config()) + return true; + + BufferId bufferId = sourceModel()->data(source_bufferIndex, NetworkModel::BufferIdRole).value(); + Q_ASSERT(bufferId.isValid()); + + int activityLevel = sourceModel()->data(source_bufferIndex, NetworkModel::BufferActivityRole).toInt(); + + if (!config()->bufferList().contains(bufferId) && !_editMode) { + // add the buffer if... + if (config()->isInitialized() + && !config()->removedBuffers().contains(bufferId) // it hasn't been manually removed and either + && ((config()->addNewBuffersAutomatically() && !config()->temporarilyRemovedBuffers().contains(bufferId)) // is totally unknown to us (a new buffer)... + || (config()->temporarilyRemovedBuffers().contains(bufferId) && activityLevel > BufferInfo::OtherActivity))) { // or was just temporarily hidden and has a new message waiting for us. + addBuffer(bufferId); + } + // note: adding the buffer to the valid list does not temper with the following filters ("show only channels" and stuff) + return false; + } + + if (config()->networkId().isValid() && config()->networkId() != sourceModel()->data(source_bufferIndex, NetworkModel::NetworkIdRole).value()) + return false; - int activityLevel = sourceModel()->data(source_bufferIndex, NetworkModel::BufferActivityRole).toInt(); + int allowedBufferTypes = config()->allowedBufferTypes(); + if (!config()->networkId().isValid()) + allowedBufferTypes &= ~BufferInfo::StatusBuffer; + int bufferType = sourceModel()->data(source_bufferIndex, NetworkModel::BufferTypeRole).toInt(); + if (!(allowedBufferTypes & bufferType)) + return false; - if(!config()->bufferList().contains(bufferId) && !_editMode) { - // add the buffer if... - if(config()->isInitialized() - && !config()->removedBuffers().contains(bufferId) // it hasn't been manually removed and either - && ((config()->addNewBuffersAutomatically() && !config()->temporarilyRemovedBuffers().contains(bufferId)) // is totally unknown to us (a new buffer)... - || (config()->temporarilyRemovedBuffers().contains(bufferId) && activityLevel > BufferInfo::OtherActivity))) { // or was just temporarily hidden and has a new message waiting for us. - addBuffer(bufferId); + if (bufferType & BufferInfo::QueryBuffer && !_showServerQueries && sourceModel()->data(source_bufferIndex, Qt::DisplayRole).toString().contains('.')) { + return false; } - // note: adding the buffer to the valid list does not temper with the following filters ("show only channels" and stuff) - return false; - } - - if(config()->networkId().isValid() && config()->networkId() != sourceModel()->data(source_bufferIndex, NetworkModel::NetworkIdRole).value()) - return false; - - int allowedBufferTypes = config()->allowedBufferTypes(); - if(!config()->networkId().isValid()) - allowedBufferTypes &= ~BufferInfo::StatusBuffer; - int bufferType = sourceModel()->data(source_bufferIndex, NetworkModel::BufferTypeRole).toInt(); - if(!(allowedBufferTypes & bufferType)) - return false; - - if(bufferType & BufferInfo::QueryBuffer && !_showServerQueries && sourceModel()->data(source_bufferIndex, Qt::DisplayRole).toString().contains('.')) { - return false; - } - - // the following dynamic filters may not trigger if the buffer is currently selected. - QModelIndex currentIndex = Client::bufferModel()->standardSelectionModel()->currentIndex(); - if(bufferId == Client::bufferModel()->data(currentIndex, NetworkModel::BufferIdRole).value()) - return true; - if(config()->hideInactiveBuffers() && !sourceModel()->data(source_bufferIndex, NetworkModel::ItemActiveRole).toBool() && activityLevel <= BufferInfo::OtherActivity) - return false; + // the following dynamic filters may not trigger if the buffer is currently selected. + QModelIndex currentIndex = Client::bufferModel()->standardSelectionModel()->currentIndex(); + if (bufferId == Client::bufferModel()->data(currentIndex, NetworkModel::BufferIdRole).value()) + return true; - if(config()->minimumActivity() > activityLevel) - return false; + if (config()->hideInactiveBuffers() && !sourceModel()->data(source_bufferIndex, NetworkModel::ItemActiveRole).toBool() && activityLevel <= BufferInfo::OtherActivity) + return false; - return true; -} + if (config()->minimumActivity() > activityLevel) + return false; -bool BufferViewFilter::filterAcceptNetwork(const QModelIndex &source_index) const { - if(!config()) return true; +} - if(!config()->networkId().isValid()) { - return true; - } else { - return config()->networkId() == sourceModel()->data(source_index, NetworkModel::NetworkIdRole).value(); - } + +bool BufferViewFilter::filterAcceptNetwork(const QModelIndex &source_index) const +{ + if (!config()) + return true; + + if (!config()->networkId().isValid()) { + return true; + } + else { + return config()->networkId() == sourceModel()->data(source_index, NetworkModel::NetworkIdRole).value(); + } } -bool BufferViewFilter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { - QModelIndex child = sourceModel()->index(source_row, 0, source_parent); - - if(!child.isValid()) { - qWarning() << "filterAcceptsRow has been called with an invalid Child"; - return false; - } - - NetworkModel::ItemType childType = (NetworkModel::ItemType)sourceModel()->data(child, NetworkModel::ItemTypeRole).toInt(); - switch(childType) { - case NetworkModel::NetworkItemType: - return filterAcceptNetwork(child); - case NetworkModel::BufferItemType: - return filterAcceptBuffer(child); - default: - return false; - } + +bool BufferViewFilter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const +{ + QModelIndex child = sourceModel()->index(source_row, 0, source_parent); + + if (!child.isValid()) { + qWarning() << "filterAcceptsRow has been called with an invalid Child"; + return false; + } + + NetworkModel::ItemType childType = (NetworkModel::ItemType)sourceModel()->data(child, NetworkModel::ItemTypeRole).toInt(); + switch (childType) { + case NetworkModel::NetworkItemType: + return filterAcceptNetwork(child); + case NetworkModel::BufferItemType: + return filterAcceptBuffer(child); + default: + return false; + } } -bool BufferViewFilter::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const { - int leftItemType = sourceModel()->data(source_left, NetworkModel::ItemTypeRole).toInt(); - int rightItemType = sourceModel()->data(source_right, NetworkModel::ItemTypeRole).toInt(); - int itemType = leftItemType & rightItemType; - switch(itemType) { - case NetworkModel::NetworkItemType: - return networkLessThan(source_left, source_right); - case NetworkModel::BufferItemType: - return bufferLessThan(source_left, source_right); - default: - return QSortFilterProxyModel::lessThan(source_left, source_right); - } + +bool BufferViewFilter::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const +{ + int leftItemType = sourceModel()->data(source_left, NetworkModel::ItemTypeRole).toInt(); + int rightItemType = sourceModel()->data(source_right, NetworkModel::ItemTypeRole).toInt(); + int itemType = leftItemType & rightItemType; + switch (itemType) { + case NetworkModel::NetworkItemType: + return networkLessThan(source_left, source_right); + case NetworkModel::BufferItemType: + return bufferLessThan(source_left, source_right); + default: + return QSortFilterProxyModel::lessThan(source_left, source_right); + } } -bool BufferViewFilter::bufferLessThan(const QModelIndex &source_left, const QModelIndex &source_right) const { - BufferId leftBufferId = sourceModel()->data(source_left, NetworkModel::BufferIdRole).value(); - BufferId rightBufferId = sourceModel()->data(source_right, NetworkModel::BufferIdRole).value(); - if(config()) { - int leftPos = config()->bufferList().indexOf(leftBufferId); - int rightPos = config()->bufferList().indexOf(rightBufferId); - if(leftPos == -1 && rightPos == -1) - return QSortFilterProxyModel::lessThan(source_left, source_right); - if(leftPos == -1 || rightPos == -1) - return !(leftPos < rightPos); - return leftPos < rightPos; - } else - return bufferIdLessThan(leftBufferId, rightBufferId); + +bool BufferViewFilter::bufferLessThan(const QModelIndex &source_left, const QModelIndex &source_right) const +{ + BufferId leftBufferId = sourceModel()->data(source_left, NetworkModel::BufferIdRole).value(); + BufferId rightBufferId = sourceModel()->data(source_right, NetworkModel::BufferIdRole).value(); + if (config()) { + int leftPos = config()->bufferList().indexOf(leftBufferId); + int rightPos = config()->bufferList().indexOf(rightBufferId); + if (leftPos == -1 && rightPos == -1) + return QSortFilterProxyModel::lessThan(source_left, source_right); + if (leftPos == -1 || rightPos == -1) + return !(leftPos < rightPos); + return leftPos < rightPos; + } + else + return bufferIdLessThan(leftBufferId, rightBufferId); } -bool BufferViewFilter::networkLessThan(const QModelIndex &source_left, const QModelIndex &source_right) const { - // NetworkId leftNetworkId = sourceModel()->data(source_left, NetworkModel::NetworkIdRole).value(); - // NetworkId rightNetworkId = sourceModel()->data(source_right, NetworkModel::NetworkIdRole).value(); - return QSortFilterProxyModel::lessThan(source_left, source_right); +bool BufferViewFilter::networkLessThan(const QModelIndex &source_left, const QModelIndex &source_right) const +{ + // NetworkId leftNetworkId = sourceModel()->data(source_left, NetworkModel::NetworkIdRole).value(); + // NetworkId rightNetworkId = sourceModel()->data(source_right, NetworkModel::NetworkIdRole).value(); + + return QSortFilterProxyModel::lessThan(source_left, source_right); } -QVariant BufferViewFilter::data(const QModelIndex &index, int role) const { - switch(role) { - case Qt::FontRole: - case Qt::ForegroundRole: - case Qt::BackgroundRole: - case Qt::DecorationRole: - if((config() && config()->disableDecoration())) - return QVariant(); - return GraphicalUi::uiStyle()->bufferViewItemData(mapToSource(index), role); - case Qt::CheckStateRole: - return checkedState(index); - default: - return QSortFilterProxyModel::data(index, role); - } + +QVariant BufferViewFilter::data(const QModelIndex &index, int role) const +{ + switch (role) { + case Qt::FontRole: + case Qt::ForegroundRole: + case Qt::BackgroundRole: + case Qt::DecorationRole: + if ((config() && config()->disableDecoration())) + return QVariant(); + return GraphicalUi::uiStyle()->bufferViewItemData(mapToSource(index), role); + case Qt::CheckStateRole: + return checkedState(index); + default: + return QSortFilterProxyModel::data(index, role); + } } -QVariant BufferViewFilter::checkedState(const QModelIndex &index) const { - if(!_editMode || !config()) - return QVariant(); - QModelIndex source_index = mapToSource(index); - if(source_index == QModelIndex() || sourceModel()->data(source_index, NetworkModel::ItemTypeRole) == NetworkModel::NetworkItemType) - return QVariant(); +QVariant BufferViewFilter::checkedState(const QModelIndex &index) const +{ + if (!_editMode || !config()) + return QVariant(); - BufferId bufferId = sourceModel()->data(source_index, NetworkModel::BufferIdRole).value(); - if(_toAdd.contains(bufferId)) - return Qt::Checked; + QModelIndex source_index = mapToSource(index); + if (source_index == QModelIndex() || sourceModel()->data(source_index, NetworkModel::ItemTypeRole) == NetworkModel::NetworkItemType) + return QVariant(); - if(_toTempRemove.contains(bufferId)) - return Qt::PartiallyChecked; + BufferId bufferId = sourceModel()->data(source_index, NetworkModel::BufferIdRole).value(); + if (_toAdd.contains(bufferId)) + return Qt::Checked; - if(_toRemove.contains(bufferId)) - return Qt::Unchecked; + if (_toTempRemove.contains(bufferId)) + return Qt::PartiallyChecked; + + if (_toRemove.contains(bufferId)) + return Qt::Unchecked; - if(config()->bufferList().contains(bufferId)) - return Qt::Checked; + if (config()->bufferList().contains(bufferId)) + return Qt::Checked; - if(config()->temporarilyRemovedBuffers().contains(bufferId)) - return Qt::PartiallyChecked; + if (config()->temporarilyRemovedBuffers().contains(bufferId)) + return Qt::PartiallyChecked; - return Qt::Unchecked; + return Qt::Unchecked; } -bool BufferViewFilter::setData(const QModelIndex &index, const QVariant &value, int role) { - switch(role) { - case Qt::CheckStateRole: - return setCheckedState(index, Qt::CheckState(value.toInt())); - default: - return QSortFilterProxyModel::setData(index, value, role); - } + +bool BufferViewFilter::setData(const QModelIndex &index, const QVariant &value, int role) +{ + switch (role) { + case Qt::CheckStateRole: + return setCheckedState(index, Qt::CheckState(value.toInt())); + default: + return QSortFilterProxyModel::setData(index, value, role); + } } -bool BufferViewFilter::setCheckedState(const QModelIndex &index, Qt::CheckState state) { - QModelIndex source_index = mapToSource(index); - BufferId bufferId = sourceModel()->data(source_index, NetworkModel::BufferIdRole).value(); - if(!bufferId.isValid()) - return false; - - switch(state) { - case Qt::Unchecked: - _toAdd.remove(bufferId); - _toTempRemove.remove(bufferId); - _toRemove << bufferId; - break; - case Qt::PartiallyChecked: - _toAdd.remove(bufferId); - _toTempRemove << bufferId; - _toRemove.remove(bufferId); - break; - case Qt::Checked: - _toAdd << bufferId; - _toTempRemove.remove(bufferId); - _toRemove.remove(bufferId); - break; - default: - return false; - } - emit dataChanged(index, index); - return true; + +bool BufferViewFilter::setCheckedState(const QModelIndex &index, Qt::CheckState state) +{ + QModelIndex source_index = mapToSource(index); + BufferId bufferId = sourceModel()->data(source_index, NetworkModel::BufferIdRole).value(); + if (!bufferId.isValid()) + return false; + + switch (state) { + case Qt::Unchecked: + _toAdd.remove(bufferId); + _toTempRemove.remove(bufferId); + _toRemove << bufferId; + break; + case Qt::PartiallyChecked: + _toAdd.remove(bufferId); + _toTempRemove << bufferId; + _toRemove.remove(bufferId); + break; + case Qt::Checked: + _toAdd << bufferId; + _toTempRemove.remove(bufferId); + _toRemove.remove(bufferId); + break; + default: + return false; + } + emit dataChanged(index, index); + return true; } -void BufferViewFilter::checkPreviousCurrentForRemoval(const QModelIndex ¤t, const QModelIndex &previous) { - Q_UNUSED(current); - if(previous.isValid()) - QCoreApplication::postEvent(this, new CheckRemovalEvent(previous)); + +void BufferViewFilter::checkPreviousCurrentForRemoval(const QModelIndex ¤t, const QModelIndex &previous) +{ + Q_UNUSED(current); + if (previous.isValid()) + QCoreApplication::postEvent(this, new CheckRemovalEvent(previous)); } -void BufferViewFilter::customEvent(QEvent *event) { - if(event->type() != QEvent::User) - return; - CheckRemovalEvent *removalEvent = static_cast(event); - checkItemForRemoval(removalEvent->index); +void BufferViewFilter::customEvent(QEvent *event) +{ + if (event->type() != QEvent::User) + return; + + CheckRemovalEvent *removalEvent = static_cast(event); + checkItemForRemoval(removalEvent->index); - event->accept(); + event->accept(); } -void BufferViewFilter::checkItemsForRemoval(const QModelIndex &topLeft, const QModelIndex &bottomRight) { - QModelIndex source_topLeft = mapToSource(topLeft); - QModelIndex source_bottomRight = mapToSource(bottomRight); - emit _dataChanged(source_topLeft, source_bottomRight); -} -bool BufferViewFilter::bufferIdLessThan(const BufferId &left, const BufferId &right) { - Q_CHECK_PTR(Client::networkModel()); - if(!Client::networkModel()) - return true; +void BufferViewFilter::checkItemsForRemoval(const QModelIndex &topLeft, const QModelIndex &bottomRight) +{ + QModelIndex source_topLeft = mapToSource(topLeft); + QModelIndex source_bottomRight = mapToSource(bottomRight); + emit _dataChanged(source_topLeft, source_bottomRight); +} - QModelIndex leftIndex = Client::networkModel()->bufferIndex(left); - QModelIndex rightIndex = Client::networkModel()->bufferIndex(right); - int leftType = Client::networkModel()->data(leftIndex, NetworkModel::BufferTypeRole).toInt(); - int rightType = Client::networkModel()->data(rightIndex, NetworkModel::BufferTypeRole).toInt(); +bool BufferViewFilter::bufferIdLessThan(const BufferId &left, const BufferId &right) +{ + Q_CHECK_PTR(Client::networkModel()); + if (!Client::networkModel()) + return true; - if(leftType != rightType) - return leftType < rightType; - else - return QString::compare(Client::networkModel()->data(leftIndex, Qt::DisplayRole).toString(), Client::networkModel()->data(rightIndex, Qt::DisplayRole).toString(), Qt::CaseInsensitive) < 0; -} + QModelIndex leftIndex = Client::networkModel()->bufferIndex(left); + QModelIndex rightIndex = Client::networkModel()->bufferIndex(right); + int leftType = Client::networkModel()->data(leftIndex, NetworkModel::BufferTypeRole).toInt(); + int rightType = Client::networkModel()->data(rightIndex, NetworkModel::BufferTypeRole).toInt(); + if (leftType != rightType) + return leftType < rightType; + else + return QString::compare(Client::networkModel()->data(leftIndex, Qt::DisplayRole).toString(), Client::networkModel()->data(rightIndex, Qt::DisplayRole).toString(), Qt::CaseInsensitive) < 0; +} diff --git a/src/uisupport/bufferviewfilter.h b/src/uisupport/bufferviewfilter.h index 01812b9b..a9da1165 100644 --- a/src/uisupport/bufferviewfilter.h +++ b/src/uisupport/bufferviewfilter.h @@ -34,78 +34,81 @@ /***************************************** * Buffer View Filter *****************************************/ -class BufferViewFilter : public QSortFilterProxyModel { - Q_OBJECT +class BufferViewFilter : public QSortFilterProxyModel +{ + Q_OBJECT public: - enum Mode { - NoActive = 0x01, - NoInactive = 0x02, - SomeNets = 0x04, - AllNets = 0x08, - NoChannels = 0x10, - NoQueries = 0x20, - NoServers = 0x40, - FullCustom = 0x80 - }; - Q_DECLARE_FLAGS(Modes, Mode) + enum Mode { + NoActive = 0x01, + NoInactive = 0x02, + SomeNets = 0x04, + AllNets = 0x08, + NoChannels = 0x10, + NoQueries = 0x20, + NoServers = 0x40, + FullCustom = 0x80 + }; + Q_DECLARE_FLAGS(Modes, Mode) - BufferViewFilter(QAbstractItemModel *model, BufferViewConfig *config = 0); + BufferViewFilter(QAbstractItemModel *model, BufferViewConfig *config = 0); - virtual Qt::ItemFlags flags(const QModelIndex &index) const; - virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); + virtual Qt::ItemFlags flags(const QModelIndex &index) const; + virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); - QVariant data(const QModelIndex &index, int role) const; - QVariant checkedState(const QModelIndex &index) const; + QVariant data(const QModelIndex &index, int role) const; + QVariant checkedState(const QModelIndex &index) const; - bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); - bool setCheckedState(const QModelIndex &index, Qt::CheckState state); + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + bool setCheckedState(const QModelIndex &index, Qt::CheckState state); - void setConfig(BufferViewConfig *config); - inline BufferViewConfig *config() const { return _config; } + void setConfig(BufferViewConfig *config); + inline BufferViewConfig *config() const { return _config; } - virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); + virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); - QList actions(const QModelIndex &index); + QList actions(const QModelIndex &index); public slots: - void checkPreviousCurrentForRemoval(const QModelIndex ¤t, const QModelIndex &previous); - void checkItemForRemoval(const QModelIndex &index) { checkItemsForRemoval(index, index); } - void checkItemsForRemoval(const QModelIndex &topLeft, const QModelIndex &bottomRight); + void checkPreviousCurrentForRemoval(const QModelIndex ¤t, const QModelIndex &previous); + void checkItemForRemoval(const QModelIndex &index) { checkItemsForRemoval(index, index); } + void checkItemsForRemoval(const QModelIndex &topLeft, const QModelIndex &bottomRight); protected: - bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; - bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const; - bool bufferLessThan(const QModelIndex &source_left, const QModelIndex &source_right) const; - bool networkLessThan(const QModelIndex &source_left, const QModelIndex &source_right) const; - virtual void customEvent(QEvent *event); + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; + bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const; + bool bufferLessThan(const QModelIndex &source_left, const QModelIndex &source_right) const; + bool networkLessThan(const QModelIndex &source_left, const QModelIndex &source_right) const; + virtual void customEvent(QEvent *event); signals: - void _dataChanged(const QModelIndex &source_topLeft, const QModelIndex &source_bottomRight); - void configChanged(); + void _dataChanged(const QModelIndex &source_topLeft, const QModelIndex &source_bottomRight); + void configChanged(); private slots: - void configInitialized(); - void enableEditMode(bool enable); - void showServerQueriesChanged(); + void configInitialized(); + void enableEditMode(bool enable); + void showServerQueriesChanged(); private: - QPointer _config; - Qt::SortOrder _sortOrder; - - bool _showServerQueries; - bool _editMode; - QAction _enableEditMode; - QSet _toAdd; - QSet _toTempRemove; - QSet _toRemove; - - bool filterAcceptBuffer(const QModelIndex &) const; - bool filterAcceptNetwork(const QModelIndex &) const; - void addBuffer(const BufferId &bufferId) const; - void addBuffers(const QList &bufferIds) const; - static bool bufferIdLessThan(const BufferId &, const BufferId &); + QPointer _config; + Qt::SortOrder _sortOrder; + + bool _showServerQueries; + bool _editMode; + QAction _enableEditMode; + QSet _toAdd; + QSet _toTempRemove; + QSet _toRemove; + + bool filterAcceptBuffer(const QModelIndex &) const; + bool filterAcceptNetwork(const QModelIndex &) const; + void addBuffer(const BufferId &bufferId) const; + void addBuffers(const QList &bufferIds) const; + static bool bufferIdLessThan(const BufferId &, const BufferId &); }; + + Q_DECLARE_OPERATORS_FOR_FLAGS(BufferViewFilter::Modes) #endif // BUFFERVIEWFILTER_H_ diff --git a/src/uisupport/bufferviewoverlayfilter.cpp b/src/uisupport/bufferviewoverlayfilter.cpp index 4309ee91..cd918f78 100644 --- a/src/uisupport/bufferviewoverlayfilter.cpp +++ b/src/uisupport/bufferviewoverlayfilter.cpp @@ -25,82 +25,88 @@ #include "types.h" BufferViewOverlayFilter::BufferViewOverlayFilter(QAbstractItemModel *model, BufferViewOverlay *overlay) - : QSortFilterProxyModel(model), + : QSortFilterProxyModel(model), _overlay(0) { - setOverlay(overlay); - setSourceModel(model); + setOverlay(overlay); + setSourceModel(model); - setDynamicSortFilter(true); + setDynamicSortFilter(true); } -void BufferViewOverlayFilter::setOverlay(BufferViewOverlay *overlay) { - if(_overlay == overlay) - return; - if(_overlay) { - disconnect(_overlay, 0, this, 0); - } +void BufferViewOverlayFilter::setOverlay(BufferViewOverlay *overlay) +{ + if (_overlay == overlay) + return; - _overlay = overlay; + if (_overlay) { + disconnect(_overlay, 0, this, 0); + } - if(!overlay) { - invalidate(); - return; - } + _overlay = overlay; - connect(overlay, SIGNAL(destroyed()), this, SLOT(overlayDestroyed())); - connect(overlay, SIGNAL(hasChanged()), this, SLOT(invalidate())); - invalidate(); + if (!overlay) { + invalidate(); + return; + } + + connect(overlay, SIGNAL(destroyed()), this, SLOT(overlayDestroyed())); + connect(overlay, SIGNAL(hasChanged()), this, SLOT(invalidate())); + invalidate(); } -void BufferViewOverlayFilter::overlayDestroyed() { - setOverlay(0); + +void BufferViewOverlayFilter::overlayDestroyed() +{ + setOverlay(0); } -bool BufferViewOverlayFilter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { - if(!_overlay) - return false; - QModelIndex source_bufferIndex = sourceModel()->index(source_row, 0, source_parent); +bool BufferViewOverlayFilter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const +{ + if (!_overlay) + return false; + + QModelIndex source_bufferIndex = sourceModel()->index(source_row, 0, source_parent); - if(!source_bufferIndex.isValid()) { - qWarning() << "filterAcceptsRow has been called with an invalid Child"; - return false; - } + if (!source_bufferIndex.isValid()) { + qWarning() << "filterAcceptsRow has been called with an invalid Child"; + return false; + } - NetworkModel::ItemType itemType = (NetworkModel::ItemType)sourceModel()->data(source_bufferIndex, NetworkModel::ItemTypeRole).toInt(); + NetworkModel::ItemType itemType = (NetworkModel::ItemType)sourceModel()->data(source_bufferIndex, NetworkModel::ItemTypeRole).toInt(); - NetworkId networkId = sourceModel()->data(source_bufferIndex, NetworkModel::NetworkIdRole).value(); - if(!_overlay->networkIds().contains(networkId) && ! _overlay->allNetworks()) { - return false; - } else if(itemType == NetworkModel::NetworkItemType) { - // network items don't need further checks. - return true; - } + NetworkId networkId = sourceModel()->data(source_bufferIndex, NetworkModel::NetworkIdRole).value(); + if (!_overlay->networkIds().contains(networkId) && !_overlay->allNetworks()) { + return false; + } + else if (itemType == NetworkModel::NetworkItemType) { + // network items don't need further checks. + return true; + } - int activityLevel = sourceModel()->data(source_bufferIndex, NetworkModel::BufferActivityRole).toInt(); - if(_overlay->minimumActivity() > activityLevel) - return false; + int activityLevel = sourceModel()->data(source_bufferIndex, NetworkModel::BufferActivityRole).toInt(); + if (_overlay->minimumActivity() > activityLevel) + return false; - int bufferType = sourceModel()->data(source_bufferIndex, NetworkModel::BufferTypeRole).toInt(); - if(!(_overlay->allowedBufferTypes() & bufferType)) - return false; + int bufferType = sourceModel()->data(source_bufferIndex, NetworkModel::BufferTypeRole).toInt(); + if (!(_overlay->allowedBufferTypes() & bufferType)) + return false; - BufferId bufferId = sourceModel()->data(source_bufferIndex, NetworkModel::BufferIdRole).value(); - Q_ASSERT(bufferId.isValid()); + BufferId bufferId = sourceModel()->data(source_bufferIndex, NetworkModel::BufferIdRole).value(); + Q_ASSERT(bufferId.isValid()); - if(_overlay->bufferIds().contains(bufferId)) - return true; + if (_overlay->bufferIds().contains(bufferId)) + return true; - if(_overlay->tempRemovedBufferIds().contains(bufferId)) - return activityLevel > BufferInfo::OtherActivity; + if (_overlay->tempRemovedBufferIds().contains(bufferId)) + return activityLevel > BufferInfo::OtherActivity; - if(_overlay->removedBufferIds().contains(bufferId)) - return false; + if (_overlay->removedBufferIds().contains(bufferId)) + return false; - // the buffer is not known to us - qDebug() << "BufferViewOverlayFilter::filterAcceptsRow()" << bufferId << "is unknown!"; - return false; + // the buffer is not known to us + qDebug() << "BufferViewOverlayFilter::filterAcceptsRow()" << bufferId << "is unknown!"; + return false; } - diff --git a/src/uisupport/bufferviewoverlayfilter.h b/src/uisupport/bufferviewoverlayfilter.h index 706d3acb..523e3150 100644 --- a/src/uisupport/bufferviewoverlayfilter.h +++ b/src/uisupport/bufferviewoverlayfilter.h @@ -27,22 +27,24 @@ class BufferViewOverlay; -class BufferViewOverlayFilter : public QSortFilterProxyModel { - Q_OBJECT +class BufferViewOverlayFilter : public QSortFilterProxyModel +{ + Q_OBJECT public: - BufferViewOverlayFilter(QAbstractItemModel *model, BufferViewOverlay *overlay = 0); + BufferViewOverlayFilter(QAbstractItemModel *model, BufferViewOverlay *overlay = 0); - void setOverlay(BufferViewOverlay *overlay); + void setOverlay(BufferViewOverlay *overlay); protected: - bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; private slots: - void overlayDestroyed(); + void overlayDestroyed(); private: - BufferViewOverlay *_overlay; + BufferViewOverlay *_overlay; }; + #endif // BUFFERVIEWOVERLAYFILTER_H_ diff --git a/src/uisupport/clearablelineedit.cpp b/src/uisupport/clearablelineedit.cpp index 0c5b35ac..7592e16a 100644 --- a/src/uisupport/clearablelineedit.cpp +++ b/src/uisupport/clearablelineedit.cpp @@ -26,33 +26,37 @@ #include "iconloader.h" ClearableLineEdit::ClearableLineEdit(QWidget *parent) - : QLineEdit(parent) + : QLineEdit(parent) { - clearButton = new QToolButton(this); - clearButton->setIcon(SmallIcon("edit-clear-locationbar-rtl")); + clearButton = new QToolButton(this); + clearButton->setIcon(SmallIcon("edit-clear-locationbar-rtl")); #ifndef Q_WS_QWS - clearButton->setCursor(Qt::ArrowCursor); + clearButton->setCursor(Qt::ArrowCursor); #endif - clearButton->setStyleSheet("QToolButton { border: none; padding: 0px; }"); - clearButton->hide(); + clearButton->setStyleSheet("QToolButton { border: none; padding: 0px; }"); + clearButton->hide(); - connect(clearButton, SIGNAL(clicked()), this, SLOT(clear())); - connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(updateClearButton(const QString&))); + connect(clearButton, SIGNAL(clicked()), this, SLOT(clear())); + connect(this, SIGNAL(textChanged(const QString &)), this, SLOT(updateClearButton(const QString &))); - int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); - setStyleSheet(QString("QLineEdit { padding-right: %1px; } ").arg(clearButton->sizeHint().width() + frameWidth + 1)); - QSize msz = minimumSizeHint(); - setMinimumSize(qMax(msz.width(), clearButton->sizeHint().height() + frameWidth * 2 + 2), - qMax(msz.height(), clearButton->sizeHint().height() + frameWidth * 2 + 2)); + int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); + setStyleSheet(QString("QLineEdit { padding-right: %1px; } ").arg(clearButton->sizeHint().width() + frameWidth + 1)); + QSize msz = minimumSizeHint(); + setMinimumSize(qMax(msz.width(), clearButton->sizeHint().height() + frameWidth * 2 + 2), + qMax(msz.height(), clearButton->sizeHint().height() + frameWidth * 2 + 2)); } -void ClearableLineEdit::resizeEvent(QResizeEvent *) { - QSize size = clearButton->sizeHint(); - int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); - clearButton->move(rect().right() - frameWidth - size.width(), - (rect().bottom() + 1 - size.height())/2); + +void ClearableLineEdit::resizeEvent(QResizeEvent *) +{ + QSize size = clearButton->sizeHint(); + int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); + clearButton->move(rect().right() - frameWidth - size.width(), + (rect().bottom() + 1 - size.height())/2); } -void ClearableLineEdit::updateClearButton(const QString& text) { - clearButton->setVisible(!text.isEmpty()); + +void ClearableLineEdit::updateClearButton(const QString &text) +{ + clearButton->setVisible(!text.isEmpty()); } diff --git a/src/uisupport/clearablelineedit.h b/src/uisupport/clearablelineedit.h index 2bef8eba..bb8cae6c 100644 --- a/src/uisupport/clearablelineedit.h +++ b/src/uisupport/clearablelineedit.h @@ -25,20 +25,22 @@ class QToolButton; -class ClearableLineEdit : public QLineEdit { - Q_OBJECT +class ClearableLineEdit : public QLineEdit +{ + Q_OBJECT public: - ClearableLineEdit(QWidget *parent = 0); + ClearableLineEdit(QWidget *parent = 0); protected: - void resizeEvent(QResizeEvent *event); + void resizeEvent(QResizeEvent *event); private slots: - void updateClearButton(const QString &text); + void updateClearButton(const QString &text); private: - QToolButton *clearButton; + QToolButton *clearButton; }; + #endif // CLEARABLELINEEDIT_H diff --git a/src/uisupport/clickable.cpp b/src/uisupport/clickable.cpp index 0674d0e7..27dfd69d 100644 --- a/src/uisupport/clickable.cpp +++ b/src/uisupport/clickable.cpp @@ -26,97 +26,103 @@ #include "clickable.h" #include "client.h" -void Clickable::activate(NetworkId networkId, const QString &text) const { - if(!isValid()) - return; +void Clickable::activate(NetworkId networkId, const QString &text) const +{ + if (!isValid()) + return; - QString str = text.mid(start(), length()); + QString str = text.mid(start(), length()); - switch(type()) { + switch (type()) { case Clickable::Url: - if(!str.contains("://")) - str = "http://" + str; - QDesktopServices::openUrl(QUrl::fromEncoded(str.toUtf8(), QUrl::TolerantMode)); - break; + if (!str.contains("://")) + str = "http://" + str; + QDesktopServices::openUrl(QUrl::fromEncoded(str.toUtf8(), QUrl::TolerantMode)); + break; case Clickable::Channel: - Client::bufferModel()->switchToOrJoinBuffer(networkId, str); - break; + Client::bufferModel()->switchToOrJoinBuffer(networkId, str); + break; default: - break; - } + break; + } } + // NOTE: This method is not threadsafe and not reentrant! // (RegExps are not constant while matching, and they are static here for efficiency) -ClickableList ClickableList::fromString(const QString &str) { - // For matching URLs - static QString scheme("(?:(?:mailto:|(?:[+.-]?\\w)+://)|www(?=\\.\\S+\\.))"); - static QString authority("(?:(?:[,.;@:]?[-\\w]+)+\\.?|\\[[0-9a-f:.]+\\])(?::\\d+)?"); - static QString urlChars("(?:[,.;:]*[\\w~@/?&=+$()!%#*{}\\[\\]\\|'^-])"); - static QString urlEnd("(?:>|[,.;:\"]*\\s|\\b|$)"); - - static QRegExp regExp[] = { - // URL - // QRegExp(QString("((?:https?://|s?ftp://|irc://|mailto:|www\\.)%1+|%1+\\.[a-z]{2,4}(?:?=/%1+|\\b))%2").arg(urlChars, urlEnd)), - QRegExp(QString("\\b(%1%2(?:/%3*)?)%4").arg(scheme, authority, urlChars, urlEnd), Qt::CaseInsensitive), - - // Channel name - // We don't match for channel names starting with + or &, because that gives us a lot of false positives. - QRegExp("((?:#|![A-Z0-9]{5})[^,:\\s]+(?::[^,:\\s]+)?)\\b", Qt::CaseInsensitive) - - // TODO: Nicks, we'll need a filtering for only matching known nicknames further down if we do this - }; - - static const int regExpCount = 2; // number of regexps in the array above - - qint16 matches[] = { 0, 0, 0 }; - qint16 matchEnd[] = { 0, 0, 0 }; - - ClickableList result; - //QString str = data(ChatLineModel::DisplayRole).toString(); - - qint16 idx = 0; - qint16 minidx; - int type = -1; - - do { - type = -1; - minidx = str.length(); - for(int i = 0; i < regExpCount; i++) { - if(matches[i] < 0 || matchEnd[i] > str.length()) continue; - if(idx >= matchEnd[i]) { - matches[i] = regExp[i].indexIn(str, qMax(matchEnd[i], idx)); - if(matches[i] >= 0) matchEnd[i] = matches[i] + regExp[i].cap(1).length(); - } - if(matches[i] >= 0 && matches[i] < minidx) { - minidx = matches[i]; - type = i; - } - } - if(type >= 0) { - idx = matchEnd[type]; - QString match = str.mid(matches[type], matchEnd[type] - matches[type]); - if(type == Clickable::Url && str.at(idx-1) == ')') { // special case: closing paren only matches if we had an open one - if(!match.contains('(')) { - matchEnd[type]--; - match.chop(1); +ClickableList ClickableList::fromString(const QString &str) +{ + // For matching URLs + static QString scheme("(?:(?:mailto:|(?:[+.-]?\\w)+://)|www(?=\\.\\S+\\.))"); + static QString authority("(?:(?:[,.;@:]?[-\\w]+)+\\.?|\\[[0-9a-f:.]+\\])(?::\\d+)?"); + static QString urlChars("(?:[,.;:]*[\\w~@/?&=+$()!%#*{}\\[\\]\\|'^-])"); + static QString urlEnd("(?:>|[,.;:\"]*\\s|\\b|$)"); + + static QRegExp regExp[] = { + // URL + // QRegExp(QString("((?:https?://|s?ftp://|irc://|mailto:|www\\.)%1+|%1+\\.[a-z]{2,4}(?:?=/%1+|\\b))%2").arg(urlChars, urlEnd)), + QRegExp(QString("\\b(%1%2(?:/%3*)?)%4").arg(scheme, authority, urlChars, urlEnd), Qt::CaseInsensitive), + + // Channel name + // We don't match for channel names starting with + or &, because that gives us a lot of false positives. + QRegExp("((?:#|![A-Z0-9]{5})[^,:\\s]+(?::[^,:\\s]+)?)\\b", Qt::CaseInsensitive) + + // TODO: Nicks, we'll need a filtering for only matching known nicknames further down if we do this + }; + + static const int regExpCount = 2; // number of regexps in the array above + + qint16 matches[] = { 0, 0, 0 }; + qint16 matchEnd[] = { 0, 0, 0 }; + + ClickableList result; + //QString str = data(ChatLineModel::DisplayRole).toString(); + + qint16 idx = 0; + qint16 minidx; + int type = -1; + + do { + type = -1; + minidx = str.length(); + for (int i = 0; i < regExpCount; i++) { + if (matches[i] < 0 || matchEnd[i] > str.length()) continue; + if (idx >= matchEnd[i]) { + matches[i] = regExp[i].indexIn(str, qMax(matchEnd[i], idx)); + if (matches[i] >= 0) matchEnd[i] = matches[i] + regExp[i].cap(1).length(); + } + if (matches[i] >= 0 && matches[i] < minidx) { + minidx = matches[i]; + type = i; + } + } + if (type >= 0) { + idx = matchEnd[type]; + QString match = str.mid(matches[type], matchEnd[type] - matches[type]); + if (type == Clickable::Url && str.at(idx-1) == ')') { // special case: closing paren only matches if we had an open one + if (!match.contains('(')) { + matchEnd[type]--; + match.chop(1); + } + } + if (type == Clickable::Channel) { + // don't make clickable if it could be a #number + if (QRegExp("^#\\d+$").exactMatch(match)) + continue; + } + result.append(Clickable((Clickable::Type)type, matches[type], matchEnd[type] - matches[type])); } - } - if(type == Clickable::Channel) { - // don't make clickable if it could be a #number - if(QRegExp("^#\\d+$").exactMatch(match)) - continue; - } - result.append(Clickable((Clickable::Type)type, matches[type], matchEnd[type] - matches[type])); } - } while(type >= 0); - return result; + while (type >= 0); + return result; } -Clickable ClickableList::atCursorPos(int idx) { - foreach(const Clickable &click, *this) { - if(idx >= click.start() && idx < click.start() + click.length()) - return click; - } - return Clickable(); + +Clickable ClickableList::atCursorPos(int idx) +{ + foreach(const Clickable &click, *this) { + if (idx >= click.start() && idx < click.start() + click.length()) + return click; + } + return Clickable(); } diff --git a/src/uisupport/clickable.h b/src/uisupport/clickable.h index eb89a36c..efa0810b 100644 --- a/src/uisupport/clickable.h +++ b/src/uisupport/clickable.h @@ -27,42 +27,43 @@ class QModelIndex; -class Clickable { - +class Clickable +{ public: - // Don't change these enums without also changing dependent methods! - enum Type { - Invalid = -1, - Url = 0, - Channel = 1, - Nick = 2 - }; + // Don't change these enums without also changing dependent methods! + enum Type { + Invalid = -1, + Url = 0, + Channel = 1, + Nick = 2 + }; - explicit inline Clickable(Type type = Invalid, quint16 start = 0, quint16 length = 0) - : _type(type), _start(start), _length(length) - {} + explicit inline Clickable(Type type = Invalid, quint16 start = 0, quint16 length = 0) + : _type(type), _start(start), _length(length) + {} - inline Type type() const { return _type; } - inline quint16 start() const { return _start; } - inline quint16 length() const { return _length; } + inline Type type() const { return _type; } + inline quint16 start() const { return _start; } + inline quint16 length() const { return _length; } - inline bool isValid() const { return _type != Invalid; } + inline bool isValid() const { return _type != Invalid; } - void activate(NetworkId networkId, const QString &bufferName) const; + void activate(NetworkId networkId, const QString &bufferName) const; private: - Type _type; - quint16 _start; - quint16 _length; + Type _type; + quint16 _start; + quint16 _length; }; -class ClickableList : public QList { +class ClickableList : public QList +{ public: - static ClickableList fromString(const QString &); - - Clickable atCursorPos(int idx); + static ClickableList fromString(const QString &); + Clickable atCursorPos(int idx); }; + #endif // CLICKABLE_H_ diff --git a/src/uisupport/clickablelabel.cpp b/src/uisupport/clickablelabel.cpp index d3bc28c6..58d176af 100644 --- a/src/uisupport/clickablelabel.cpp +++ b/src/uisupport/clickablelabel.cpp @@ -24,15 +24,16 @@ #include ClickableLabel::ClickableLabel(QWidget *parent) - : QLabel(parent) + : QLabel(parent) { } -void ClickableLabel::mouseReleaseEvent(QMouseEvent *event) { - if(event->pos().x() > size().width() || event->pos().y() > size().height()) - return; +void ClickableLabel::mouseReleaseEvent(QMouseEvent *event) +{ + if (event->pos().x() > size().width() || event->pos().y() > size().height()) + return; - event->accept(); - emit clicked(); + event->accept(); + emit clicked(); } diff --git a/src/uisupport/clickablelabel.h b/src/uisupport/clickablelabel.h index df3e65ae..f38c5859 100644 --- a/src/uisupport/clickablelabel.h +++ b/src/uisupport/clickablelabel.h @@ -23,17 +23,19 @@ #include -class ClickableLabel : public QLabel { - Q_OBJECT +class ClickableLabel : public QLabel +{ + Q_OBJECT public: - ClickableLabel(QWidget *parent = 0); + ClickableLabel(QWidget *parent = 0); signals: - void clicked(); + void clicked(); protected: - void mouseReleaseEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); }; + #endif //CLICKABLELABEL_H diff --git a/src/uisupport/colorbutton.cpp b/src/uisupport/colorbutton.cpp index c42f1525..aaddc985 100644 --- a/src/uisupport/colorbutton.cpp +++ b/src/uisupport/colorbutton.cpp @@ -30,33 +30,40 @@ # include #endif -ColorButton::ColorButton(QWidget *parent) : QToolButton(parent) { - setText(""); - connect(this, SIGNAL(clicked()), SLOT(chooseColor())); +ColorButton::ColorButton(QWidget *parent) : QToolButton(parent) +{ + setText(""); + connect(this, SIGNAL(clicked()), SLOT(chooseColor())); } -void ColorButton::setColor(const QColor &color) { - _color = color; - QPixmap pixmap(QSize(32,32)); - pixmap.fill(color); - setIcon(pixmap); - emit colorChanged(color); +void ColorButton::setColor(const QColor &color) +{ + _color = color; + QPixmap pixmap(QSize(32, 32)); + pixmap.fill(color); + setIcon(pixmap); + + emit colorChanged(color); } -QColor ColorButton::color() const { - return _color; + +QColor ColorButton::color() const +{ + return _color; } -void ColorButton::chooseColor() { + +void ColorButton::chooseColor() +{ #ifdef HAVE_KDE - QColor c = color(); - KColorDialog::getColor(c, this); + QColor c = color(); + KColorDialog::getColor(c, this); #else - QColor c = QColorDialog::getColor(color(), this); + QColor c = QColorDialog::getColor(color(), this); #endif - if(c.isValid()) { - setColor(c); - } + if (c.isValid()) { + setColor(c); + } } diff --git a/src/uisupport/colorbutton.h b/src/uisupport/colorbutton.h index 0c9309fc..64353270 100644 --- a/src/uisupport/colorbutton.h +++ b/src/uisupport/colorbutton.h @@ -23,28 +23,30 @@ #include -class ColorButton : public QToolButton { - Q_OBJECT - Q_PROPERTY(QColor color READ color WRITE setColor USER true) +class ColorButton : public QToolButton +{ + Q_OBJECT + Q_PROPERTY(QColor color READ color WRITE setColor USER true) -public: - explicit ColorButton(QWidget *parent = 0); - explicit ColorButton(const QColor &c, QWidget *parent = 0); +public : + explicit ColorButton(QWidget *parent = 0); + explicit ColorButton(const QColor &c, QWidget *parent = 0); - void setColor(const QColor &color); - QColor color() const; + void setColor(const QColor &color); + QColor color() const; signals: - void colorChanged(const QColor &); + void colorChanged(const QColor &); protected: - //void paintEvent(QPaintEvent *event); + //void paintEvent(QPaintEvent *event); private slots: - void chooseColor(); + void chooseColor(); private: - QColor _color; + QColor _color; }; + #endif diff --git a/src/uisupport/contextmenuactionprovider.cpp b/src/uisupport/contextmenuactionprovider.cpp index 02542332..9ef7cd20 100644 --- a/src/uisupport/contextmenuactionprovider.cpp +++ b/src/uisupport/contextmenuactionprovider.cpp @@ -34,450 +34,488 @@ #include "client.h" #include "clientignorelistmanager.h" -ContextMenuActionProvider::ContextMenuActionProvider(QObject *parent) : NetworkModelController(parent) { - registerAction(NetworkConnect, SmallIcon("network-connect"), tr("Connect")); - registerAction(NetworkDisconnect, SmallIcon("network-disconnect"), tr("Disconnect")); - - registerAction(BufferJoin, SmallIcon("irc-join-channel"), tr("Join")); - registerAction(BufferPart, SmallIcon("irc-close-channel"), tr("Part")); - registerAction(BufferRemove, tr("Delete Chat(s)...")); - registerAction(BufferSwitchTo, tr("Go to Chat")); - - registerAction(HideJoin, tr("Joins"), true); - registerAction(HidePart, tr("Parts"), true); - registerAction(HideQuit, tr("Quits"), true); - registerAction(HideNick, tr("Nick Changes"), true); - registerAction(HideMode, tr("Mode Changes"), true); - registerAction(HideDayChange, tr("Day Changes"), true); - registerAction(HideTopic, tr("Topic Changes"), true); - registerAction(HideApplyToAll, tr("Set as Default...")); - registerAction(HideUseDefaults, tr("Use Defaults...")); - - registerAction(JoinChannel, SmallIcon("irc-join-channel"), tr("Join Channel...")); - - registerAction(NickQuery, tr("Start Query")); - registerAction(NickSwitchTo, tr("Show Query")); - registerAction(NickWhois, tr("Whois")); - - registerAction(NickCtcpVersion, tr("Version")); - registerAction(NickCtcpTime, tr("Time")); - registerAction(NickCtcpPing, tr("Ping")); - registerAction(NickCtcpClientinfo, tr("Client info")); - registerAction(NickIgnoreCustom, tr("Custom...")); - - // these texts are only dummies! don't think about tr() here! - registerAction(NickIgnoreUser, "*!ident@host.domain.tld"); - registerAction(NickIgnoreHost, "*!*@host.domain.tld"); - registerAction(NickIgnoreDomain, "*!ident@*.domain.tld"); - registerAction(NickIgnoreToggleEnabled0, "Enable", true); - registerAction(NickIgnoreToggleEnabled1, "Enable", true); - registerAction(NickIgnoreToggleEnabled2, "Enable", true); - registerAction(NickIgnoreToggleEnabled3, "Enable", true); - registerAction(NickIgnoreToggleEnabled4, "Enable", true); - - registerAction(NickOp, SmallIcon("irc-operator"), tr("Give Operator Status")); - registerAction(NickDeop, SmallIcon("irc-remove-operator"), tr("Take Operator Status")); - registerAction(NickHalfop, SmallIcon("irc-voice"), tr("Give Half-Operator Status")); - registerAction(NickDehalfop, SmallIcon("irc-unvoice"), tr("Take Half-Operator Status")); - registerAction(NickVoice, SmallIcon("irc-voice"), tr("Give Voice")); - registerAction(NickDevoice, SmallIcon("irc-unvoice"), tr("Take Voice")); - registerAction(NickKick, SmallIcon("im-kick-user"), tr("Kick From Channel")); - registerAction(NickBan, SmallIcon("im-ban-user"), tr("Ban From Channel")); - registerAction(NickKickBan, SmallIcon("im-ban-kick-user"), tr("Kick && Ban")); - - registerAction(HideBufferTemporarily, tr("Hide Chat(s) Temporarily")); - registerAction(HideBufferPermanently, tr("Hide Chat(s) Permanently")); - registerAction(ShowChannelList, tr("Show Channel List")); - registerAction(ShowIgnoreList, tr("Show Ignore List")); - - QMenu *hideEventsMenu = new QMenu(); - hideEventsMenu->addAction(action(HideJoin)); - hideEventsMenu->addAction(action(HidePart)); - hideEventsMenu->addAction(action(HideQuit)); - hideEventsMenu->addAction(action(HideNick)); - hideEventsMenu->addAction(action(HideMode)); - hideEventsMenu->addAction(action(HideTopic)); - hideEventsMenu->addAction(action(HideDayChange)); - hideEventsMenu->addSeparator(); - hideEventsMenu->addAction(action(HideApplyToAll)); - hideEventsMenu->addAction(action(HideUseDefaults)); - _hideEventsMenuAction = new Action(tr("Hide Events"), 0); - _hideEventsMenuAction->setMenu(hideEventsMenu); - - QMenu *nickCtcpMenu = new QMenu(); - nickCtcpMenu->addAction(action(NickCtcpPing)); - nickCtcpMenu->addAction(action(NickCtcpVersion)); - nickCtcpMenu->addAction(action(NickCtcpTime)); - nickCtcpMenu->addAction(action(NickCtcpClientinfo)); - _nickCtcpMenuAction = new Action(tr("CTCP"), 0); - _nickCtcpMenuAction->setMenu(nickCtcpMenu); - - QMenu *nickModeMenu = new QMenu(); - nickModeMenu->addAction(action(NickOp)); - nickModeMenu->addAction(action(NickDeop)); - // this is where the halfops will be placed if available - nickModeMenu->addAction(action(NickHalfop)); - nickModeMenu->addAction(action(NickDehalfop)); - nickModeMenu->addAction(action(NickVoice)); - nickModeMenu->addAction(action(NickDevoice)); - nickModeMenu->addSeparator(); - nickModeMenu->addAction(action(NickKick)); - nickModeMenu->addAction(action(NickBan)); - nickModeMenu->addAction(action(NickKickBan)); - _nickModeMenuAction = new Action(tr("Actions"), 0); - _nickModeMenuAction->setMenu(nickModeMenu); - - QMenu *ignoreMenu = new QMenu(); - _nickIgnoreMenuAction = new Action(tr("Ignore"), 0); - _nickIgnoreMenuAction->setMenu(ignoreMenu); - - // These are disabled actions used as descriptions - // They don't need any of the Action fancyness so we use plain QActions - _ignoreDescriptions << new QAction(tr("Add Ignore Rule"), this); - _ignoreDescriptions << new QAction(tr("Existing Rules"), this); - foreach(QAction *act, _ignoreDescriptions) +ContextMenuActionProvider::ContextMenuActionProvider(QObject *parent) : NetworkModelController(parent) +{ + registerAction(NetworkConnect, SmallIcon("network-connect"), tr("Connect")); + registerAction(NetworkDisconnect, SmallIcon("network-disconnect"), tr("Disconnect")); + + registerAction(BufferJoin, SmallIcon("irc-join-channel"), tr("Join")); + registerAction(BufferPart, SmallIcon("irc-close-channel"), tr("Part")); + registerAction(BufferRemove, tr("Delete Chat(s)...")); + registerAction(BufferSwitchTo, tr("Go to Chat")); + + registerAction(HideJoin, tr("Joins"), true); + registerAction(HidePart, tr("Parts"), true); + registerAction(HideQuit, tr("Quits"), true); + registerAction(HideNick, tr("Nick Changes"), true); + registerAction(HideMode, tr("Mode Changes"), true); + registerAction(HideDayChange, tr("Day Changes"), true); + registerAction(HideTopic, tr("Topic Changes"), true); + registerAction(HideApplyToAll, tr("Set as Default...")); + registerAction(HideUseDefaults, tr("Use Defaults...")); + + registerAction(JoinChannel, SmallIcon("irc-join-channel"), tr("Join Channel...")); + + registerAction(NickQuery, tr("Start Query")); + registerAction(NickSwitchTo, tr("Show Query")); + registerAction(NickWhois, tr("Whois")); + + registerAction(NickCtcpVersion, tr("Version")); + registerAction(NickCtcpTime, tr("Time")); + registerAction(NickCtcpPing, tr("Ping")); + registerAction(NickCtcpClientinfo, tr("Client info")); + registerAction(NickIgnoreCustom, tr("Custom...")); + + // these texts are only dummies! don't think about tr() here! + registerAction(NickIgnoreUser, "*!ident@host.domain.tld"); + registerAction(NickIgnoreHost, "*!*@host.domain.tld"); + registerAction(NickIgnoreDomain, "*!ident@*.domain.tld"); + registerAction(NickIgnoreToggleEnabled0, "Enable", true); + registerAction(NickIgnoreToggleEnabled1, "Enable", true); + registerAction(NickIgnoreToggleEnabled2, "Enable", true); + registerAction(NickIgnoreToggleEnabled3, "Enable", true); + registerAction(NickIgnoreToggleEnabled4, "Enable", true); + + registerAction(NickOp, SmallIcon("irc-operator"), tr("Give Operator Status")); + registerAction(NickDeop, SmallIcon("irc-remove-operator"), tr("Take Operator Status")); + registerAction(NickHalfop, SmallIcon("irc-voice"), tr("Give Half-Operator Status")); + registerAction(NickDehalfop, SmallIcon("irc-unvoice"), tr("Take Half-Operator Status")); + registerAction(NickVoice, SmallIcon("irc-voice"), tr("Give Voice")); + registerAction(NickDevoice, SmallIcon("irc-unvoice"), tr("Take Voice")); + registerAction(NickKick, SmallIcon("im-kick-user"), tr("Kick From Channel")); + registerAction(NickBan, SmallIcon("im-ban-user"), tr("Ban From Channel")); + registerAction(NickKickBan, SmallIcon("im-ban-kick-user"), tr("Kick && Ban")); + + registerAction(HideBufferTemporarily, tr("Hide Chat(s) Temporarily")); + registerAction(HideBufferPermanently, tr("Hide Chat(s) Permanently")); + registerAction(ShowChannelList, tr("Show Channel List")); + registerAction(ShowIgnoreList, tr("Show Ignore List")); + + QMenu *hideEventsMenu = new QMenu(); + hideEventsMenu->addAction(action(HideJoin)); + hideEventsMenu->addAction(action(HidePart)); + hideEventsMenu->addAction(action(HideQuit)); + hideEventsMenu->addAction(action(HideNick)); + hideEventsMenu->addAction(action(HideMode)); + hideEventsMenu->addAction(action(HideTopic)); + hideEventsMenu->addAction(action(HideDayChange)); + hideEventsMenu->addSeparator(); + hideEventsMenu->addAction(action(HideApplyToAll)); + hideEventsMenu->addAction(action(HideUseDefaults)); + _hideEventsMenuAction = new Action(tr("Hide Events"), 0); + _hideEventsMenuAction->setMenu(hideEventsMenu); + + QMenu *nickCtcpMenu = new QMenu(); + nickCtcpMenu->addAction(action(NickCtcpPing)); + nickCtcpMenu->addAction(action(NickCtcpVersion)); + nickCtcpMenu->addAction(action(NickCtcpTime)); + nickCtcpMenu->addAction(action(NickCtcpClientinfo)); + _nickCtcpMenuAction = new Action(tr("CTCP"), 0); + _nickCtcpMenuAction->setMenu(nickCtcpMenu); + + QMenu *nickModeMenu = new QMenu(); + nickModeMenu->addAction(action(NickOp)); + nickModeMenu->addAction(action(NickDeop)); + // this is where the halfops will be placed if available + nickModeMenu->addAction(action(NickHalfop)); + nickModeMenu->addAction(action(NickDehalfop)); + nickModeMenu->addAction(action(NickVoice)); + nickModeMenu->addAction(action(NickDevoice)); + nickModeMenu->addSeparator(); + nickModeMenu->addAction(action(NickKick)); + nickModeMenu->addAction(action(NickBan)); + nickModeMenu->addAction(action(NickKickBan)); + _nickModeMenuAction = new Action(tr("Actions"), 0); + _nickModeMenuAction->setMenu(nickModeMenu); + + QMenu *ignoreMenu = new QMenu(); + _nickIgnoreMenuAction = new Action(tr("Ignore"), 0); + _nickIgnoreMenuAction->setMenu(ignoreMenu); + + // These are disabled actions used as descriptions + // They don't need any of the Action fancyness so we use plain QActions + _ignoreDescriptions << new QAction(tr("Add Ignore Rule"), this); + _ignoreDescriptions << new QAction(tr("Existing Rules"), this); + foreach(QAction *act, _ignoreDescriptions) act->setEnabled(false); } -ContextMenuActionProvider::~ContextMenuActionProvider() { - _hideEventsMenuAction->menu()->deleteLater(); - _hideEventsMenuAction->deleteLater(); - _nickCtcpMenuAction->menu()->deleteLater(); - _nickCtcpMenuAction->deleteLater(); - _nickModeMenuAction->menu()->deleteLater(); - _nickModeMenuAction->deleteLater(); - _nickIgnoreMenuAction->menu()->deleteLater(); - _nickIgnoreMenuAction->deleteLater(); - qDeleteAll(_ignoreDescriptions); - _ignoreDescriptions.clear(); -} -void ContextMenuActionProvider::addActions(QMenu *menu, BufferId bufId, QObject *receiver, const char *method) { - if(!bufId.isValid()) - return; - addActions(menu, Client::networkModel()->bufferIndex(bufId), receiver, method); +ContextMenuActionProvider::~ContextMenuActionProvider() +{ + _hideEventsMenuAction->menu()->deleteLater(); + _hideEventsMenuAction->deleteLater(); + _nickCtcpMenuAction->menu()->deleteLater(); + _nickCtcpMenuAction->deleteLater(); + _nickModeMenuAction->menu()->deleteLater(); + _nickModeMenuAction->deleteLater(); + _nickIgnoreMenuAction->menu()->deleteLater(); + _nickIgnoreMenuAction->deleteLater(); + qDeleteAll(_ignoreDescriptions); + _ignoreDescriptions.clear(); } -void ContextMenuActionProvider::addActions(QMenu *menu, const QModelIndex &index, QObject *receiver, const char *method, bool isCustomBufferView) { - if(!index.isValid()) - return; - addActions(menu, QList() << index, 0, QString(), receiver, method, isCustomBufferView); -} -void ContextMenuActionProvider::addActions(QMenu *menu, MessageFilter *filter, BufferId msgBuffer, QObject *receiver, const char *slot) { - addActions(menu, filter, msgBuffer, QString(), receiver, slot); +void ContextMenuActionProvider::addActions(QMenu *menu, BufferId bufId, QObject *receiver, const char *method) +{ + if (!bufId.isValid()) + return; + addActions(menu, Client::networkModel()->bufferIndex(bufId), receiver, method); } -void ContextMenuActionProvider::addActions(QMenu *menu, MessageFilter *filter, BufferId msgBuffer, const QString &chanOrNick, QObject *receiver, const char *method) { - if(!filter) - return; - addActions(menu, QList() << Client::networkModel()->bufferIndex(msgBuffer), filter, chanOrNick, receiver, method, false); + +void ContextMenuActionProvider::addActions(QMenu *menu, const QModelIndex &index, QObject *receiver, const char *method, bool isCustomBufferView) +{ + if (!index.isValid()) + return; + addActions(menu, QList() << index, 0, QString(), receiver, method, isCustomBufferView); } -void ContextMenuActionProvider::addActions(QMenu *menu, const QList &indexList, QObject *receiver, const char *method, bool isCustomBufferView) { - addActions(menu, indexList, 0, QString(), receiver, method, isCustomBufferView); + +void ContextMenuActionProvider::addActions(QMenu *menu, MessageFilter *filter, BufferId msgBuffer, QObject *receiver, const char *slot) +{ + addActions(menu, filter, msgBuffer, QString(), receiver, slot); } -// add a list of actions sensible for the current item(s) -void ContextMenuActionProvider::addActions(QMenu *menu, - const QList &indexList_, - MessageFilter *filter_, - const QString &contextItem_, - QObject *receiver_, - const char *method_, - bool isCustomBufferView) + +void ContextMenuActionProvider::addActions(QMenu *menu, MessageFilter *filter, BufferId msgBuffer, const QString &chanOrNick, QObject *receiver, const char *method) { - if(!indexList_.count()) - return; + if (!filter) + return; + addActions(menu, QList() << Client::networkModel()->bufferIndex(msgBuffer), filter, chanOrNick, receiver, method, false); +} - setIndexList(indexList_); - setMessageFilter(filter_); - setContextItem(contextItem_); - setSlot(receiver_, method_); - if(!messageFilter()) { - // this means we are in a BufferView (or NickView) rather than a ChatView +void ContextMenuActionProvider::addActions(QMenu *menu, const QList &indexList, QObject *receiver, const char *method, bool isCustomBufferView) +{ + addActions(menu, indexList, 0, QString(), receiver, method, isCustomBufferView); +} - // first index in list determines the menu type (just in case we have both buffers and networks selected, for example) - QModelIndex index = indexList().at(0); - NetworkModel::ItemType itemType = static_cast(index.data(NetworkModel::ItemTypeRole).toInt()); - switch(itemType) { - case NetworkModel::NetworkItemType: - addNetworkItemActions(menu, index); - break; - case NetworkModel::BufferItemType: - addBufferItemActions(menu, index, isCustomBufferView); - break; - case NetworkModel::IrcUserItemType: - addIrcUserActions(menu, index); - break; - default: +// add a list of actions sensible for the current item(s) +void ContextMenuActionProvider::addActions(QMenu *menu, + const QList &indexList_, + MessageFilter *filter_, + const QString &contextItem_, + QObject *receiver_, + const char *method_, + bool isCustomBufferView) +{ + if (!indexList_.count()) return; + setIndexList(indexList_); + setMessageFilter(filter_); + setContextItem(contextItem_); + setSlot(receiver_, method_); + + if (!messageFilter()) { + // this means we are in a BufferView (or NickView) rather than a ChatView + + // first index in list determines the menu type (just in case we have both buffers and networks selected, for example) + QModelIndex index = indexList().at(0); + NetworkModel::ItemType itemType = static_cast(index.data(NetworkModel::ItemTypeRole).toInt()); + + switch (itemType) { + case NetworkModel::NetworkItemType: + addNetworkItemActions(menu, index); + break; + case NetworkModel::BufferItemType: + addBufferItemActions(menu, index, isCustomBufferView); + break; + case NetworkModel::IrcUserItemType: + addIrcUserActions(menu, index); + break; + default: + return; + } } - } else { - // ChatView actions - if(contextItem().isEmpty()) { - // a) query buffer: handle like ircuser - // b) general chatview: handle like channel iff it displays a single buffer - // NOTE stuff breaks probably with merged buffers, need to rework a lot around here then - if(messageFilter()->containedBuffers().count() == 1) { - // we can handle this like a single bufferItem - QModelIndex index = Client::networkModel()->bufferIndex(messageFilter()->containedBuffers().values().at(0)); - setIndexList(index); - addBufferItemActions(menu, index); - return; - } else { - // TODO: actions for merged buffers... _indexList contains the index of the message we clicked on - - } - } else { - // context item = chan or nick, _indexList = buf where the msg clicked on originated - if(isChannelName(contextItem())) { - QModelIndex msgIdx = indexList().at(0); - if(!msgIdx.isValid()) - return; - NetworkId networkId = msgIdx.data(NetworkModel::NetworkIdRole).value(); - BufferId bufId = Client::networkModel()->bufferId(networkId, contextItem()); - if(bufId.isValid()) { - QModelIndex targetIdx = Client::networkModel()->bufferIndex(bufId); - setIndexList(targetIdx); - addAction(BufferJoin, menu, targetIdx, InactiveState); - addAction(BufferSwitchTo, menu, targetIdx, ActiveState); - } else - addAction(JoinChannel, menu); - } else { - // TODO: actions for a nick - } + else { + // ChatView actions + if (contextItem().isEmpty()) { + // a) query buffer: handle like ircuser + // b) general chatview: handle like channel iff it displays a single buffer + // NOTE stuff breaks probably with merged buffers, need to rework a lot around here then + if (messageFilter()->containedBuffers().count() == 1) { + // we can handle this like a single bufferItem + QModelIndex index = Client::networkModel()->bufferIndex(messageFilter()->containedBuffers().values().at(0)); + setIndexList(index); + addBufferItemActions(menu, index); + return; + } + else { + // TODO: actions for merged buffers... _indexList contains the index of the message we clicked on + } + } + else { + // context item = chan or nick, _indexList = buf where the msg clicked on originated + if (isChannelName(contextItem())) { + QModelIndex msgIdx = indexList().at(0); + if (!msgIdx.isValid()) + return; + NetworkId networkId = msgIdx.data(NetworkModel::NetworkIdRole).value(); + BufferId bufId = Client::networkModel()->bufferId(networkId, contextItem()); + if (bufId.isValid()) { + QModelIndex targetIdx = Client::networkModel()->bufferIndex(bufId); + setIndexList(targetIdx); + addAction(BufferJoin, menu, targetIdx, InactiveState); + addAction(BufferSwitchTo, menu, targetIdx, ActiveState); + } + else + addAction(JoinChannel, menu); + } + else { + // TODO: actions for a nick + } + } } - } } -void ContextMenuActionProvider::addNetworkItemActions(QMenu *menu, const QModelIndex &index) { - NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value(); - if(!networkId.isValid()) - return; - const Network *network = Client::network(networkId); - Q_CHECK_PTR(network); - if(!network) - return; - - addAction(NetworkConnect, menu, network->connectionState() == Network::Disconnected); - addAction(NetworkDisconnect, menu, network->connectionState() != Network::Disconnected); - menu->addSeparator(); - addAction(ShowChannelList, menu, index, ActiveState); - addAction(JoinChannel, menu, index, ActiveState); +void ContextMenuActionProvider::addNetworkItemActions(QMenu *menu, const QModelIndex &index) +{ + NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value(); + if (!networkId.isValid()) + return; + const Network *network = Client::network(networkId); + Q_CHECK_PTR(network); + if (!network) + return; + + addAction(NetworkConnect, menu, network->connectionState() == Network::Disconnected); + addAction(NetworkDisconnect, menu, network->connectionState() != Network::Disconnected); + menu->addSeparator(); + addAction(ShowChannelList, menu, index, ActiveState); + addAction(JoinChannel, menu, index, ActiveState); } -void ContextMenuActionProvider::addBufferItemActions(QMenu *menu, const QModelIndex &index, bool isCustomBufferView) { - BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value(); - menu->addSeparator(); - switch(bufferInfo.type()) { +void ContextMenuActionProvider::addBufferItemActions(QMenu *menu, const QModelIndex &index, bool isCustomBufferView) +{ + BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value(); + + menu->addSeparator(); + switch (bufferInfo.type()) { case BufferInfo::ChannelBuffer: - addAction(BufferJoin, menu, index, InactiveState); - addAction(BufferPart, menu, index, ActiveState); - menu->addSeparator(); - addHideEventsMenu(menu, bufferInfo.bufferId()); - menu->addSeparator(); - addAction(HideBufferTemporarily, menu, isCustomBufferView); - addAction(HideBufferPermanently, menu, isCustomBufferView); - addAction(BufferRemove, menu, index, InactiveState); - break; + addAction(BufferJoin, menu, index, InactiveState); + addAction(BufferPart, menu, index, ActiveState); + menu->addSeparator(); + addHideEventsMenu(menu, bufferInfo.bufferId()); + menu->addSeparator(); + addAction(HideBufferTemporarily, menu, isCustomBufferView); + addAction(HideBufferPermanently, menu, isCustomBufferView); + addAction(BufferRemove, menu, index, InactiveState); + break; case BufferInfo::QueryBuffer: { - //IrcUser *ircUser = qobject_cast(index.data(NetworkModel::IrcUserRole).value()); - //if(ircUser) { + //IrcUser *ircUser = qobject_cast(index.data(NetworkModel::IrcUserRole).value()); + //if(ircUser) { addIrcUserActions(menu, index); menu->addSeparator(); - //} - addHideEventsMenu(menu, bufferInfo.bufferId()); - menu->addSeparator(); - addAction(HideBufferTemporarily, menu, isCustomBufferView); - addAction(HideBufferPermanently, menu, isCustomBufferView); - addAction(BufferRemove, menu, index); - break; + //} + addHideEventsMenu(menu, bufferInfo.bufferId()); + menu->addSeparator(); + addAction(HideBufferTemporarily, menu, isCustomBufferView); + addAction(HideBufferPermanently, menu, isCustomBufferView); + addAction(BufferRemove, menu, index); + break; } default: - addAction(HideBufferTemporarily, menu, isCustomBufferView); - addAction(HideBufferPermanently, menu, isCustomBufferView); - } + addAction(HideBufferTemporarily, menu, isCustomBufferView); + addAction(HideBufferPermanently, menu, isCustomBufferView); + } } -void ContextMenuActionProvider::addIrcUserActions(QMenu *menu, const QModelIndex &index) { - // this can be called: a) as a nicklist context menu (index has IrcUserItemType) - // b) as a query buffer context menu (index has BufferItemType and is a QueryBufferItem) - // c) right-click in a query chatview (same as b), index will be the corresponding QueryBufferItem) - // d) right-click on some nickname (_contextItem will be non-null, _filter -> chatview, index -> message buffer) - - if(contextItem().isNull()) { - // cases a, b, c - bool haveQuery = indexList().count() == 1 && findQueryBuffer(index).isValid(); - NetworkModel::ItemType itemType = static_cast(index.data(NetworkModel::ItemTypeRole).toInt()); - addAction(_nickModeMenuAction, menu, itemType == NetworkModel::IrcUserItemType); - addAction(_nickCtcpMenuAction, menu); - - IrcUser *ircUser = qobject_cast(index.data(NetworkModel::IrcUserRole).value()); - if(ircUser) { - Network *network = ircUser->network(); - // only show entries for usermode +h if server supports it - if(network && network->prefixModes().contains('h')) { - action(NickHalfop)->setVisible(true); - action(NickDehalfop)->setVisible(true); - } - else { - action(NickHalfop)->setVisible(false); - action(NickDehalfop)->setVisible(false); - } - // ignoreliststuff - QString bufferName; - BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value(); - if(bufferInfo.type() == BufferInfo::ChannelBuffer) - bufferName = bufferInfo.bufferName(); - QMap ignoreMap = Client::ignoreListManager()->matchingRulesForHostmask(ircUser->hostmask(), ircUser->network()->networkName(), bufferName); - addIgnoreMenu(menu, ircUser->hostmask(), ignoreMap); - // end of ignoreliststuff + +void ContextMenuActionProvider::addIrcUserActions(QMenu *menu, const QModelIndex &index) +{ + // this can be called: a) as a nicklist context menu (index has IrcUserItemType) + // b) as a query buffer context menu (index has BufferItemType and is a QueryBufferItem) + // c) right-click in a query chatview (same as b), index will be the corresponding QueryBufferItem) + // d) right-click on some nickname (_contextItem will be non-null, _filter -> chatview, index -> message buffer) + + if (contextItem().isNull()) { + // cases a, b, c + bool haveQuery = indexList().count() == 1 && findQueryBuffer(index).isValid(); + NetworkModel::ItemType itemType = static_cast(index.data(NetworkModel::ItemTypeRole).toInt()); + addAction(_nickModeMenuAction, menu, itemType == NetworkModel::IrcUserItemType); + addAction(_nickCtcpMenuAction, menu); + + IrcUser *ircUser = qobject_cast(index.data(NetworkModel::IrcUserRole).value()); + if (ircUser) { + Network *network = ircUser->network(); + // only show entries for usermode +h if server supports it + if (network && network->prefixModes().contains('h')) { + action(NickHalfop)->setVisible(true); + action(NickDehalfop)->setVisible(true); + } + else { + action(NickHalfop)->setVisible(false); + action(NickDehalfop)->setVisible(false); + } + // ignoreliststuff + QString bufferName; + BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value(); + if (bufferInfo.type() == BufferInfo::ChannelBuffer) + bufferName = bufferInfo.bufferName(); + QMap ignoreMap = Client::ignoreListManager()->matchingRulesForHostmask(ircUser->hostmask(), ircUser->network()->networkName(), bufferName); + addIgnoreMenu(menu, ircUser->hostmask(), ignoreMap); + // end of ignoreliststuff + } + menu->addSeparator(); + addAction(NickQuery, menu, itemType == NetworkModel::IrcUserItemType && !haveQuery && indexList().count() == 1); + addAction(NickSwitchTo, menu, itemType == NetworkModel::IrcUserItemType && haveQuery); + menu->addSeparator(); + addAction(NickWhois, menu, true); } - menu->addSeparator(); - addAction(NickQuery, menu, itemType == NetworkModel::IrcUserItemType && !haveQuery && indexList().count() == 1); - addAction(NickSwitchTo, menu, itemType == NetworkModel::IrcUserItemType && haveQuery); - menu->addSeparator(); - addAction(NickWhois, menu, true); + else if (!contextItem().isEmpty() && messageFilter()) { + // case d + // TODO + } +} - } else if(!contextItem().isEmpty() && messageFilter()) { - // case d - // TODO - } +Action *ContextMenuActionProvider::addAction(ActionType type, QMenu *menu, const QModelIndex &index, ItemActiveStates requiredActiveState) +{ + return addAction(action(type), menu, checkRequirements(index, requiredActiveState)); } -Action * ContextMenuActionProvider::addAction(ActionType type , QMenu *menu, const QModelIndex &index, ItemActiveStates requiredActiveState) { - return addAction(action(type), menu, checkRequirements(index, requiredActiveState)); -} -Action * ContextMenuActionProvider::addAction(Action *action , QMenu *menu, const QModelIndex &index, ItemActiveStates requiredActiveState) { - return addAction(action, menu, checkRequirements(index, requiredActiveState)); +Action *ContextMenuActionProvider::addAction(Action *action, QMenu *menu, const QModelIndex &index, ItemActiveStates requiredActiveState) +{ + return addAction(action, menu, checkRequirements(index, requiredActiveState)); } -Action * ContextMenuActionProvider::addAction(ActionType type , QMenu *menu, bool condition) { - return addAction(action(type), menu, condition); + +Action *ContextMenuActionProvider::addAction(ActionType type, QMenu *menu, bool condition) +{ + return addAction(action(type), menu, condition); } -Action * ContextMenuActionProvider::addAction(Action *action , QMenu *menu, bool condition) { - if(condition) { - menu->addAction(action); - action->setVisible(true); - } else { - action->setVisible(false); - } - return action; + +Action *ContextMenuActionProvider::addAction(Action *action, QMenu *menu, bool condition) +{ + if (condition) { + menu->addAction(action); + action->setVisible(true); + } + else { + action->setVisible(false); + } + return action; } -void ContextMenuActionProvider::addHideEventsMenu(QMenu *menu, BufferId bufferId) { - if(BufferSettings(bufferId).hasFilter()) - addHideEventsMenu(menu, BufferSettings(bufferId).messageFilter()); - else - addHideEventsMenu(menu); + +void ContextMenuActionProvider::addHideEventsMenu(QMenu *menu, BufferId bufferId) +{ + if (BufferSettings(bufferId).hasFilter()) + addHideEventsMenu(menu, BufferSettings(bufferId).messageFilter()); + else + addHideEventsMenu(menu); } -void ContextMenuActionProvider::addHideEventsMenu(QMenu *menu, MessageFilter *msgFilter) { - if(BufferSettings(msgFilter->idString()).hasFilter()) - addHideEventsMenu(menu, BufferSettings(msgFilter->idString()).messageFilter()); - else - addHideEventsMenu(menu); + +void ContextMenuActionProvider::addHideEventsMenu(QMenu *menu, MessageFilter *msgFilter) +{ + if (BufferSettings(msgFilter->idString()).hasFilter()) + addHideEventsMenu(menu, BufferSettings(msgFilter->idString()).messageFilter()); + else + addHideEventsMenu(menu); } -void ContextMenuActionProvider::addHideEventsMenu(QMenu *menu, int filter) { - action(HideApplyToAll)->setEnabled(filter != -1); - action(HideUseDefaults)->setEnabled(filter != -1); - if(filter == -1) - filter = BufferSettings().messageFilter(); - - action(HideJoin)->setChecked(filter & Message::Join); - action(HidePart)->setChecked(filter & Message::Part); - action(HideQuit)->setChecked(filter & Message::Quit); - action(HideNick)->setChecked(filter & Message::Nick); - action(HideMode)->setChecked(filter & Message::Mode); - action(HideDayChange)->setChecked(filter & Message::DayChange); - action(HideTopic)->setChecked(filter & Message::Topic); - - menu->addAction(_hideEventsMenuAction); + +void ContextMenuActionProvider::addHideEventsMenu(QMenu *menu, int filter) +{ + action(HideApplyToAll)->setEnabled(filter != -1); + action(HideUseDefaults)->setEnabled(filter != -1); + if (filter == -1) + filter = BufferSettings().messageFilter(); + + action(HideJoin)->setChecked(filter & Message::Join); + action(HidePart)->setChecked(filter & Message::Part); + action(HideQuit)->setChecked(filter & Message::Quit); + action(HideNick)->setChecked(filter & Message::Nick); + action(HideMode)->setChecked(filter & Message::Mode); + action(HideDayChange)->setChecked(filter & Message::DayChange); + action(HideTopic)->setChecked(filter & Message::Topic); + + menu->addAction(_hideEventsMenuAction); } -void ContextMenuActionProvider::addIgnoreMenu(QMenu *menu, const QString &hostmask, const QMap &ignoreMap) { - QMenu *ignoreMenu = _nickIgnoreMenuAction->menu(); - ignoreMenu->clear(); - QString nick = nickFromMask(hostmask); - QString ident = userFromMask(hostmask); - QString host = hostFromMask(hostmask); - QString domain = host; - QRegExp domainRx = QRegExp("(\\.[^.]+\\.\\w+\\D)$"); - if(domainRx.indexIn(host) != -1) - domain = domainRx.cap(1); - // we can't rely on who-data - // if we don't have the data, we skip actions where we would need it - bool haveWhoData = !ident.isEmpty() && !host.isEmpty(); - - // add "Add Ignore Rule" description - ignoreMenu->addAction(_ignoreDescriptions.at(0)); - - if(haveWhoData) { - QString text; - text = QString("*!%1@%2").arg(ident, host); - action(NickIgnoreUser)->setText(text); - action(NickIgnoreUser)->setProperty("ignoreRule", text); - - text = QString("*!*@%1").arg(host); - action(NickIgnoreHost)->setText(text); - action(NickIgnoreHost)->setProperty("ignoreRule", text); - - text = domain.at(0) == '.' ? QString("*!%1@*%2").arg(ident, domain) - : QString("*!%1@%2").arg(ident, domain); - - action(NickIgnoreDomain)->setText(text); - action(NickIgnoreDomain)->setProperty("ignoreRule", text); - - if(!ignoreMap.contains(action(NickIgnoreUser)->property("ignoreRule").toString())) - ignoreMenu->addAction(action(NickIgnoreUser)); - if(!ignoreMap.contains(action(NickIgnoreHost)->property("ignoreRule").toString())) - ignoreMenu->addAction(action(NickIgnoreHost)); - // we only add that NickIgnoreDomain if it isn't the same as NickIgnoreUser - // as happens with @foobar.com hostmasks and ips - if(!ignoreMap.contains(action(NickIgnoreDomain)->property("ignoreRule").toString()) - && action(NickIgnoreUser)->property("ignoreRule").toString() != action(NickIgnoreDomain)->property("ignoreRule").toString()) - ignoreMenu->addAction(action(NickIgnoreDomain)); - } - - action(NickIgnoreCustom)->setProperty("ignoreRule", hostmask); - ignoreMenu->addAction(action(NickIgnoreCustom)); - - ignoreMenu->addSeparator(); - - if(haveWhoData) { - QMap::const_iterator ruleIter = ignoreMap.begin(); - int counter = 0; - if(!ignoreMap.isEmpty()) - // add "Existing Rules" description - ignoreMenu->addAction(_ignoreDescriptions.at(1)); - while(ruleIter != ignoreMap.constEnd()) { - if(counter < 5) { - ActionType type = static_cast(NickIgnoreToggleEnabled0 + counter*0x100000); - Action *act = action(type); - act->setText(ruleIter.key()); - act->setProperty("ignoreRule", ruleIter.key()); - act->setChecked(ruleIter.value()); - ignoreMenu->addAction(act); - } - counter++; - ruleIter++; + +void ContextMenuActionProvider::addIgnoreMenu(QMenu *menu, const QString &hostmask, const QMap &ignoreMap) +{ + QMenu *ignoreMenu = _nickIgnoreMenuAction->menu(); + ignoreMenu->clear(); + QString nick = nickFromMask(hostmask); + QString ident = userFromMask(hostmask); + QString host = hostFromMask(hostmask); + QString domain = host; + QRegExp domainRx = QRegExp("(\\.[^.]+\\.\\w+\\D)$"); + if (domainRx.indexIn(host) != -1) + domain = domainRx.cap(1); + // we can't rely on who-data + // if we don't have the data, we skip actions where we would need it + bool haveWhoData = !ident.isEmpty() && !host.isEmpty(); + + // add "Add Ignore Rule" description + ignoreMenu->addAction(_ignoreDescriptions.at(0)); + + if (haveWhoData) { + QString text; + text = QString("*!%1@%2").arg(ident, host); + action(NickIgnoreUser)->setText(text); + action(NickIgnoreUser)->setProperty("ignoreRule", text); + + text = QString("*!*@%1").arg(host); + action(NickIgnoreHost)->setText(text); + action(NickIgnoreHost)->setProperty("ignoreRule", text); + + text = domain.at(0) == '.' ? QString("*!%1@*%2").arg(ident, domain) + : QString("*!%1@%2").arg(ident, domain); + + action(NickIgnoreDomain)->setText(text); + action(NickIgnoreDomain)->setProperty("ignoreRule", text); + + if (!ignoreMap.contains(action(NickIgnoreUser)->property("ignoreRule").toString())) + ignoreMenu->addAction(action(NickIgnoreUser)); + if (!ignoreMap.contains(action(NickIgnoreHost)->property("ignoreRule").toString())) + ignoreMenu->addAction(action(NickIgnoreHost)); + // we only add that NickIgnoreDomain if it isn't the same as NickIgnoreUser + // as happens with @foobar.com hostmasks and ips + if (!ignoreMap.contains(action(NickIgnoreDomain)->property("ignoreRule").toString()) + && action(NickIgnoreUser)->property("ignoreRule").toString() != action(NickIgnoreDomain)->property("ignoreRule").toString()) + ignoreMenu->addAction(action(NickIgnoreDomain)); + } + + action(NickIgnoreCustom)->setProperty("ignoreRule", hostmask); + ignoreMenu->addAction(action(NickIgnoreCustom)); + + ignoreMenu->addSeparator(); + + if (haveWhoData) { + QMap::const_iterator ruleIter = ignoreMap.begin(); + int counter = 0; + if (!ignoreMap.isEmpty()) + // add "Existing Rules" description + ignoreMenu->addAction(_ignoreDescriptions.at(1)); + while (ruleIter != ignoreMap.constEnd()) { + if (counter < 5) { + ActionType type = static_cast(NickIgnoreToggleEnabled0 + counter*0x100000); + Action *act = action(type); + act->setText(ruleIter.key()); + act->setProperty("ignoreRule", ruleIter.key()); + act->setChecked(ruleIter.value()); + ignoreMenu->addAction(act); + } + counter++; + ruleIter++; + } + if (counter) + ignoreMenu->addSeparator(); } - if(counter) - ignoreMenu->addSeparator(); - } - ignoreMenu->addAction(action(ShowIgnoreList)); - addAction(_nickIgnoreMenuAction, menu); + ignoreMenu->addAction(action(ShowIgnoreList)); + addAction(_nickIgnoreMenuAction, menu); } diff --git a/src/uisupport/contextmenuactionprovider.h b/src/uisupport/contextmenuactionprovider.h index 5bd7f6d7..e894cd15 100644 --- a/src/uisupport/contextmenuactionprovider.h +++ b/src/uisupport/contextmenuactionprovider.h @@ -23,55 +23,57 @@ #include "networkmodelcontroller.h" -class ContextMenuActionProvider : public NetworkModelController { - Q_OBJECT +class ContextMenuActionProvider : public NetworkModelController +{ + Q_OBJECT public: - ContextMenuActionProvider(QObject *parent = 0); - virtual ~ContextMenuActionProvider(); + ContextMenuActionProvider(QObject *parent = 0); + virtual ~ContextMenuActionProvider(); - //! Provide a list of actions applying to the given item - /** - * Note that this list ist not persistent, hence it should only be used immediately after - * calling this function (e.g. in a context menu). Optionally one can provide a QObject and a slot - * (that should take a QAction * as parameter) that is invoked for actions that require external - * handling. - * @param index The item index in the NetworkModel - * @param receiver The optional object that is notified for actions that need to be handled externally. - * The action type will be stored in the QAction's data(). - * @param slot The receiving slot name; should be "mySlot" rather than SLOT(mySlot(QAction *)) - * @return A list of actions applying to the given item - */ - void addActions(QMenu *, const QModelIndex &index, QObject *receiver = 0, const char *slot = 0, bool allowBufferHide = false); - void addActions(QMenu *, const QList &indexList, QObject *receiver = 0, const char *slot = 0, bool allowBufferHide = false); - void addActions(QMenu *, BufferId id, QObject *receiver = 0, const char *slot = 0); - void addActions(QMenu *, MessageFilter *filter, BufferId msgBuffer, QObject *receiver = 0, const char *slot = 0); - void addActions(QMenu *, MessageFilter *filter, BufferId msgBuffer, const QString &chanOrNick, QObject *receiver = 0, const char *slot = 0); + //! Provide a list of actions applying to the given item + /** + * Note that this list ist not persistent, hence it should only be used immediately after + * calling this function (e.g. in a context menu). Optionally one can provide a QObject and a slot + * (that should take a QAction * as parameter) that is invoked for actions that require external + * handling. + * @param index The item index in the NetworkModel + * @param receiver The optional object that is notified for actions that need to be handled externally. + * The action type will be stored in the QAction's data(). + * @param slot The receiving slot name; should be "mySlot" rather than SLOT(mySlot(QAction *)) + * @return A list of actions applying to the given item + */ + void addActions(QMenu *, const QModelIndex &index, QObject *receiver = 0, const char *slot = 0, bool allowBufferHide = false); + void addActions(QMenu *, const QList &indexList, QObject *receiver = 0, const char *slot = 0, bool allowBufferHide = false); + void addActions(QMenu *, BufferId id, QObject *receiver = 0, const char *slot = 0); + void addActions(QMenu *, MessageFilter *filter, BufferId msgBuffer, QObject *receiver = 0, const char *slot = 0); + void addActions(QMenu *, MessageFilter *filter, BufferId msgBuffer, const QString &chanOrNick, QObject *receiver = 0, const char *slot = 0); private: - void addActions(QMenu *, const QList &indexList, MessageFilter *filter, const QString &chanOrNick, - QObject *receiver, const char *slot, bool allowBufferHide); + void addActions(QMenu *, const QList &indexList, MessageFilter *filter, const QString &chanOrNick, + QObject *receiver, const char *slot, bool allowBufferHide); - Action * addAction(ActionType, QMenu *, bool condition = true); - Action * addAction(Action * , QMenu *, bool condition = true); - Action * addAction(ActionType, QMenu *, const QModelIndex &index, ItemActiveStates requiredActiveState = QFlags(ActiveState | InactiveState)); - Action * addAction(Action * , QMenu *, const QModelIndex &index, ItemActiveStates requiredActiveState = QFlags(ActiveState | InactiveState)); + Action *addAction(ActionType, QMenu *, bool condition = true); + Action *addAction(Action *, QMenu *, bool condition = true); + Action *addAction(ActionType, QMenu *, const QModelIndex &index, ItemActiveStates requiredActiveState = QFlags(ActiveState | InactiveState)); + Action *addAction(Action *, QMenu *, const QModelIndex &index, ItemActiveStates requiredActiveState = QFlags(ActiveState | InactiveState)); - void addHideEventsMenu(QMenu *, BufferId bufferId); - void addHideEventsMenu(QMenu *, MessageFilter *msgFilter); - void addHideEventsMenu(QMenu *, int filter = -1); - void addIgnoreMenu(QMenu *menu, const QString &hostmask, const QMap &ignoreMap); + void addHideEventsMenu(QMenu *, BufferId bufferId); + void addHideEventsMenu(QMenu *, MessageFilter *msgFilter); + void addHideEventsMenu(QMenu *, int filter = -1); + void addIgnoreMenu(QMenu *menu, const QString &hostmask, const QMap &ignoreMap); - void addNetworkItemActions(QMenu *, const QModelIndex &); - void addBufferItemActions(QMenu *, const QModelIndex &, bool isCustomBufferView = false); - void addIrcUserActions(QMenu *, const QModelIndex &); + void addNetworkItemActions(QMenu *, const QModelIndex &); + void addBufferItemActions(QMenu *, const QModelIndex &, bool isCustomBufferView = false); + void addIrcUserActions(QMenu *, const QModelIndex &); - Action *_hideEventsMenuAction; - Action *_nickCtcpMenuAction; - Action *_nickModeMenuAction; - Action *_nickIgnoreMenuAction; - QList _ignoreDescriptions; + Action *_hideEventsMenuAction; + Action *_nickCtcpMenuAction; + Action *_nickModeMenuAction; + Action *_nickIgnoreMenuAction; + QList _ignoreDescriptions; }; + #endif diff --git a/src/uisupport/flatproxymodel.cpp b/src/uisupport/flatproxymodel.cpp index 19f543ba..0894f89c 100644 --- a/src/uisupport/flatproxymodel.cpp +++ b/src/uisupport/flatproxymodel.cpp @@ -24,646 +24,711 @@ #include FlatProxyModel::FlatProxyModel(QObject *parent) - : QAbstractProxyModel(parent), + : QAbstractProxyModel(parent), _rootSourceItem(0) { } -QModelIndex FlatProxyModel::mapFromSource(const QModelIndex &sourceIndex) const { - if(!sourceIndex.isValid()) - return QModelIndex(); - SourceItem *sourceItem = sourceToInternal(sourceIndex); - Q_ASSERT(sourceItem); - return createIndex(sourceItem->pos(), sourceIndex.column(), sourceItem); -} +QModelIndex FlatProxyModel::mapFromSource(const QModelIndex &sourceIndex) const +{ + if (!sourceIndex.isValid()) + return QModelIndex(); -QModelIndex FlatProxyModel::mapToSource(const QModelIndex &proxyIndex) const { - if(!proxyIndex.isValid()) - return QModelIndex(); + SourceItem *sourceItem = sourceToInternal(sourceIndex); + Q_ASSERT(sourceItem); + return createIndex(sourceItem->pos(), sourceIndex.column(), sourceItem); +} - Q_ASSERT(proxyIndex.model() == this); - Q_ASSERT(_rootSourceItem); - int row = proxyIndex.row(); - QModelIndex sourceParent; - SourceItem *sourceItem = _rootSourceItem->findChild(row); - while(sourceItem) { - if(sourceItem->pos() == row) { - return sourceModel()->index(sourceItem->sourceRow(), proxyIndex.column(), sourceParent); - } else { - sourceParent = sourceModel()->index(sourceItem->sourceRow(), 0, sourceParent); - sourceItem = sourceItem->findChild(row); +QModelIndex FlatProxyModel::mapToSource(const QModelIndex &proxyIndex) const +{ + if (!proxyIndex.isValid()) + return QModelIndex(); + + Q_ASSERT(proxyIndex.model() == this); + Q_ASSERT(_rootSourceItem); + + int row = proxyIndex.row(); + QModelIndex sourceParent; + SourceItem *sourceItem = _rootSourceItem->findChild(row); + while (sourceItem) { + if (sourceItem->pos() == row) { + return sourceModel()->index(sourceItem->sourceRow(), proxyIndex.column(), sourceParent); + } + else { + sourceParent = sourceModel()->index(sourceItem->sourceRow(), 0, sourceParent); + sourceItem = sourceItem->findChild(row); + } } - } - qWarning() << "FlatProxyModel::mapToSource(): couldn't find source index for" << proxyIndex; - Q_ASSERT(false); - return QModelIndex(); // make compilers happy :) + qWarning() << "FlatProxyModel::mapToSource(): couldn't find source index for" << proxyIndex; + Q_ASSERT(false); + return QModelIndex(); // make compilers happy :) } -bool FlatProxyModel::_RangeRect::operator<(const FlatProxyModel::_RangeRect &other) const { - if(left != other.left) - return left < other.left; - if(right != other.right) - return right < other.right; +bool FlatProxyModel::_RangeRect::operator<(const FlatProxyModel::_RangeRect &other) const +{ + if (left != other.left) + return left < other.left; + + if (right != other.right) + return right < other.right; - if(top != other.top) - return top < other.top; + if (top != other.top) + return top < other.top; - // top == other.top - return bottom < other.bottom; + // top == other.top + return bottom < other.bottom; } -QItemSelection FlatProxyModel::mapSelectionFromSource(const QItemSelection &sourceSelection) const { - QList<_RangeRect> newRanges; - QHash itemLookup; - // basics steps of the loop: - // 1. convert each source ItemSelectionRange to a mapped Range (internal one for easier post processing) - // 2. insert it into the list of previously mapped Ranges sorted by top location - for(int i = 0; i < sourceSelection.count(); i++) { - const QItemSelectionRange ¤tRange = sourceSelection[i]; - QModelIndex currentParent = currentRange.topLeft().parent(); - Q_ASSERT(currentParent == currentRange.bottomRight().parent()); - SourceItem *parentItem = 0; - if(!itemLookup.contains(currentParent)) { - parentItem = sourceToInternal(currentParent); - itemLookup[currentParent] = parentItem; - } else { - parentItem = itemLookup[currentParent]; +QItemSelection FlatProxyModel::mapSelectionFromSource(const QItemSelection &sourceSelection) const +{ + QList<_RangeRect> newRanges; + QHash itemLookup; + // basics steps of the loop: + // 1. convert each source ItemSelectionRange to a mapped Range (internal one for easier post processing) + // 2. insert it into the list of previously mapped Ranges sorted by top location + for (int i = 0; i < sourceSelection.count(); i++) { + const QItemSelectionRange ¤tRange = sourceSelection[i]; + QModelIndex currentParent = currentRange.topLeft().parent(); + Q_ASSERT(currentParent == currentRange.bottomRight().parent()); + + SourceItem *parentItem = 0; + if (!itemLookup.contains(currentParent)) { + parentItem = sourceToInternal(currentParent); + itemLookup[currentParent] = parentItem; + } + else { + parentItem = itemLookup[currentParent]; + } + + _RangeRect newRange = { currentRange.topLeft().column(), currentRange.bottomRight().column(), + currentRange.topLeft().row(), currentRange.bottomRight().row(), + parentItem->child(currentRange.topLeft().row()), parentItem->child(currentRange.bottomRight().row()) }; + + if (newRanges.isEmpty()) { + newRanges << newRange; + continue; + } + + _RangeRect &first = newRanges[0]; + if (newRange < first) { + newRanges.prepend(newRange); + continue; + } + + bool inserted = false; + for (int j = 0; j < newRanges.count() - 1; j++) { + _RangeRect &a = newRanges[j]; + _RangeRect &b = newRanges[j + 1]; + + if (a < newRange && newRange < b) { + newRanges[j + 1] = newRange; + inserted = true; + break; + } + } + if (inserted) + continue; + + _RangeRect &last = newRanges[newRanges.count() - 1]; + if (last < newRange) { + newRanges.append(newRange); + continue; + } + + Q_ASSERT(false); } - _RangeRect newRange = { currentRange.topLeft().column(), currentRange.bottomRight().column(), - currentRange.topLeft().row(), currentRange.bottomRight().row(), - parentItem->child(currentRange.topLeft().row()), parentItem->child(currentRange.bottomRight().row()) }; - - if(newRanges.isEmpty()) { - newRanges << newRange; - continue; + // we've got a sorted list of ranges now. so we can easily check if there is a possibility to merge + for (int i = newRanges.count() - 1; i > 0; i--) { + _RangeRect &a = newRanges[i - 1]; + _RangeRect &b = newRanges[i]; + if (a.left != b.left || a.right != b.right) + continue; + + if (a.bottom < b.top - 1) { + continue; + } + + // all merge checks passed! + if (b.bottom > a.bottom) { + a.bottom = b.bottom; + a.bottomItem = b.bottomItem; + } // otherwise b is totally enclosed in a -> nothing to do but drop b. + newRanges.removeAt(i); } - _RangeRect &first = newRanges[0]; - if(newRange < first) { - newRanges.prepend(newRange); - continue; + QItemSelection proxySelection; + for (int i = 0; i < newRanges.count(); i++) { + _RangeRect &r = newRanges[i]; + proxySelection << QItemSelectionRange(createIndex(r.top, r.left, r.topItem), createIndex(r.bottom, r.right, r.bottomItem)); } + return proxySelection; +} - bool inserted = false; - for(int j = 0; j < newRanges.count() - 1; j++) { - _RangeRect &a = newRanges[j]; - _RangeRect &b = newRanges[j + 1]; - - if(a < newRange && newRange < b) { - newRanges[j + 1] = newRange; - inserted = true; - break; - } - } - if(inserted) - continue; - _RangeRect &last = newRanges[newRanges.count() - 1]; - if(last < newRange) { - newRanges.append(newRange); - continue; - } - - Q_ASSERT(false); - } - - // we've got a sorted list of ranges now. so we can easily check if there is a possibility to merge - for(int i = newRanges.count() - 1; i > 0; i--) { - _RangeRect &a = newRanges[i - 1]; - _RangeRect &b = newRanges[i]; - if(a.left != b.left || a.right != b.right) - continue; - - if(a.bottom < b.top - 1) { - continue; - } - - // all merge checks passed! - if(b.bottom > a.bottom) { - a.bottom = b.bottom; - a.bottomItem = b.bottomItem; - } // otherwise b is totally enclosed in a -> nothing to do but drop b. - newRanges.removeAt(i); - } - - QItemSelection proxySelection; - for(int i = 0; i < newRanges.count(); i++) { - _RangeRect &r = newRanges[i]; - proxySelection << QItemSelectionRange(createIndex(r.top, r.left, r.topItem), createIndex(r.bottom, r.right, r.bottomItem)); - } - return proxySelection; -} - -QItemSelection FlatProxyModel::mapSelectionToSource(const QItemSelection &proxySelection) const { - QItemSelection sourceSelection; - - for(int i = 0; i < proxySelection.count(); i++) { - const QItemSelectionRange &range = proxySelection[i]; - - SourceItem *topLeftItem = 0; - SourceItem *bottomRightItem = 0; - SourceItem *currentItem = static_cast(range.topLeft().internalPointer()); - int row = range.topLeft().row(); - int left = range.topLeft().column(); - int right = range.bottomRight().column(); - while(currentItem && row <= range.bottomRight().row()) { - Q_ASSERT(currentItem->pos() == row); - if(!topLeftItem) - topLeftItem = currentItem; - - if(currentItem->parent() == topLeftItem->parent()) { - bottomRightItem = currentItem; - } else { - Q_ASSERT(topLeftItem && bottomRightItem); +QItemSelection FlatProxyModel::mapSelectionToSource(const QItemSelection &proxySelection) const +{ + QItemSelection sourceSelection; + + for (int i = 0; i < proxySelection.count(); i++) { + const QItemSelectionRange &range = proxySelection[i]; + + SourceItem *topLeftItem = 0; + SourceItem *bottomRightItem = 0; + SourceItem *currentItem = static_cast(range.topLeft().internalPointer()); + int row = range.topLeft().row(); + int left = range.topLeft().column(); + int right = range.bottomRight().column(); + while (currentItem && row <= range.bottomRight().row()) { + Q_ASSERT(currentItem->pos() == row); + if (!topLeftItem) + topLeftItem = currentItem; + + if (currentItem->parent() == topLeftItem->parent()) { + bottomRightItem = currentItem; + } + else { + Q_ASSERT(topLeftItem && bottomRightItem); + sourceSelection << QItemSelectionRange(mapToSource(createIndex(topLeftItem->pos(), left, topLeftItem)), mapToSource(createIndex(bottomRightItem->pos(), right, bottomRightItem))); + topLeftItem = 0; + bottomRightItem = 0; + } + + // update loop vars + currentItem = currentItem->next(); + row++; + } + + Q_ASSERT(topLeftItem && bottomRightItem); // there should be one range left. sourceSelection << QItemSelectionRange(mapToSource(createIndex(topLeftItem->pos(), left, topLeftItem)), mapToSource(createIndex(bottomRightItem->pos(), right, bottomRightItem))); - topLeftItem = 0; - bottomRightItem = 0; - } - - // update loop vars - currentItem = currentItem->next(); - row++; } - Q_ASSERT(topLeftItem && bottomRightItem); // there should be one range left. - sourceSelection << QItemSelectionRange(mapToSource(createIndex(topLeftItem->pos(), left, topLeftItem)), mapToSource(createIndex(bottomRightItem->pos(), right, bottomRightItem))); - } - - return sourceSelection; + return sourceSelection; } -void FlatProxyModel::setSourceModel(QAbstractItemModel *sourceModel) { - if(QAbstractProxyModel::sourceModel()) { - disconnect(QAbstractProxyModel::sourceModel(), 0, this, 0); - } - QAbstractProxyModel::setSourceModel(sourceModel); +void FlatProxyModel::setSourceModel(QAbstractItemModel *sourceModel) +{ + if (QAbstractProxyModel::sourceModel()) { + disconnect(QAbstractProxyModel::sourceModel(), 0, this, 0); + } + + QAbstractProxyModel::setSourceModel(sourceModel); - emit layoutAboutToBeChanged(); - removeSubTree(QModelIndex(), false /* don't emit removeRows() */); - insertSubTree(QModelIndex(), false /* don't emit insertRows() */); - emit layoutChanged(); + emit layoutAboutToBeChanged(); + removeSubTree(QModelIndex(), false /* don't emit removeRows() */); + insertSubTree(QModelIndex(), false /* don't emit insertRows() */); + emit layoutChanged(); - if(sourceModel) { - connect(sourceModel, SIGNAL(columnsAboutToBeInserted(const QModelIndex &, int, int)), + if (sourceModel) { + connect(sourceModel, SIGNAL(columnsAboutToBeInserted(const QModelIndex &, int, int)), this, SLOT(on_columnsAboutToBeInserted(const QModelIndex &, int, int))); - connect(sourceModel, SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)), + connect(sourceModel, SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)), this, SLOT(on_columnsAboutToBeRemoved(const QModelIndex &, int, int))); - connect(sourceModel, SIGNAL(columnsInserted(const QModelIndex &, int, int)), + connect(sourceModel, SIGNAL(columnsInserted(const QModelIndex &, int, int)), this, SLOT(on_columnsInserted(const QModelIndex &, int, int))); - connect(sourceModel, SIGNAL(columnsRemoved(const QModelIndex &, int, int)), + connect(sourceModel, SIGNAL(columnsRemoved(const QModelIndex &, int, int)), this, SLOT(on_columnsRemoved(const QModelIndex &, int, int))); - - connect(sourceModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), + + connect(sourceModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(on_dataChanged(const QModelIndex &, const QModelIndex &))); - // on_headerDataChanged(Qt::Orientation orientation, int first, int last) + // on_headerDataChanged(Qt::Orientation orientation, int first, int last) - connect(sourceModel, SIGNAL(layoutAboutToBeChanged()), + connect(sourceModel, SIGNAL(layoutAboutToBeChanged()), this, SLOT(on_layoutAboutToBeChanged())); - connect(sourceModel, SIGNAL(layoutChanged()), + connect(sourceModel, SIGNAL(layoutChanged()), this, SLOT(on_layoutChanged())); - connect(sourceModel, SIGNAL(modelAboutToBeReset()), + connect(sourceModel, SIGNAL(modelAboutToBeReset()), this, SLOT(on_modelAboutToBeReset())); - // void on_modelReset() + // void on_modelReset() - connect(sourceModel, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)), + connect(sourceModel, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)), this, SLOT(on_rowsAboutToBeInserted(const QModelIndex &, int, int))); - connect(sourceModel, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)), + connect(sourceModel, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)), this, SLOT(on_rowsAboutToBeRemoved(const QModelIndex &, int, int))); - connect(sourceModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), + connect(sourceModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(on_rowsInserted(const QModelIndex &, int, int))); - connect(sourceModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), + connect(sourceModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SLOT(on_rowsRemoved(const QModelIndex &, int, int))); - } - + } } -void FlatProxyModel::insertSubTree(const QModelIndex &source_idx, bool emitInsert) { - SourceItem *newSubTree = new SourceItem(source_idx.row(), sourceToInternal(sourceModel()->parent(source_idx))); - if(newSubTree->parent()) { - newSubTree->setPos(newSubTree->parent()->pos() + source_idx.row() + 1); - } - SourceItem *lastItem = insertSubTreeHelper(newSubTree, newSubTree, source_idx); +void FlatProxyModel::insertSubTree(const QModelIndex &source_idx, bool emitInsert) +{ + SourceItem *newSubTree = new SourceItem(source_idx.row(), sourceToInternal(sourceModel()->parent(source_idx))); - Q_ASSERT(lastItem); - Q_ASSERT(lastItem->next() == 0); + if (newSubTree->parent()) { + newSubTree->setPos(newSubTree->parent()->pos() + source_idx.row() + 1); + } + SourceItem *lastItem = insertSubTreeHelper(newSubTree, newSubTree, source_idx); + + Q_ASSERT(lastItem); + Q_ASSERT(lastItem->next() == 0); + + if (emitInsert) + beginInsertRows(QModelIndex(), newSubTree->pos(), lastItem->pos()); + + if (newSubTree->parent()) { + if (newSubTree->parent()->childCount() > source_idx.row()) { + SourceItem *next = newSubTree->parent()->child(source_idx.row()); + lastItem->setNext(next); + int nextPos = lastItem->pos() + 1; + while (next) { + next->setPos(nextPos); + next = next->next(); + nextPos++; + } + } + if (source_idx.row() > 0) { + SourceItem *previous = newSubTree->parent()->child(source_idx.row() - 1); + while (previous->childCount() > 0) { + previous = previous->child(previous->childCount() - 1); + } + previous->setNext(newSubTree); + } + else { + newSubTree->parent()->setNext(newSubTree); + } + } + else { + _rootSourceItem = newSubTree; + } - if(emitInsert) - beginInsertRows(QModelIndex(), newSubTree->pos(), lastItem->pos()); + if (emitInsert) + endInsertRows(); +} - if(newSubTree->parent()) { - if(newSubTree->parent()->childCount() > source_idx.row()) { - SourceItem *next = newSubTree->parent()->child(source_idx.row()); - lastItem->setNext(next); - int nextPos = lastItem->pos() + 1; - while(next) { - next->setPos(nextPos); - next = next->next(); - nextPos++; - } - } - if(source_idx.row() > 0) { - SourceItem *previous = newSubTree->parent()->child(source_idx.row() - 1); - while(previous->childCount() > 0) { - previous = previous->child(previous->childCount() - 1); - } - previous->setNext(newSubTree); - } else { - newSubTree->parent()->setNext(newSubTree); - } - } else { - _rootSourceItem = newSubTree; - } - - if(emitInsert) - endInsertRows(); + +FlatProxyModel::SourceItem *FlatProxyModel::insertSubTreeHelper(SourceItem *parentItem, SourceItem *lastItem_, const QModelIndex &source_idx) +{ + SourceItem *lastItem = lastItem_; + SourceItem *newItem = 0; + for (int row = 0; row < sourceModel()->rowCount(source_idx); row++) { + newItem = new SourceItem(row, parentItem); + newItem->setPos(lastItem->pos() + 1); + lastItem->setNext(newItem); + lastItem = insertSubTreeHelper(newItem, newItem, sourceModel()->index(row, 0, source_idx)); + } + return lastItem; } -FlatProxyModel::SourceItem *FlatProxyModel::insertSubTreeHelper(SourceItem *parentItem, SourceItem *lastItem_, const QModelIndex &source_idx) { - SourceItem *lastItem = lastItem_; - SourceItem *newItem = 0; - for(int row = 0; row < sourceModel()->rowCount(source_idx); row++) { - newItem = new SourceItem(row, parentItem); - newItem->setPos(lastItem->pos() + 1); - lastItem->setNext(newItem); - lastItem = insertSubTreeHelper(newItem, newItem, sourceModel()->index(row, 0, source_idx)); - } - return lastItem; -} - -void FlatProxyModel::removeSubTree(const QModelIndex &source_idx, bool emitRemove) { - SourceItem *sourceItem = sourceToInternal(source_idx); - if(!sourceItem) - return; - - SourceItem *prevItem = sourceItem->parent(); - if(sourceItem->sourceRow() > 0) { - prevItem = prevItem->child(sourceItem->sourceRow() - 1); - while(prevItem->childCount() > 0) { - prevItem = prevItem->child(prevItem->childCount() - 1); - } - } - - SourceItem *lastItem = sourceItem; - while(lastItem->childCount() > 0) { - lastItem = lastItem->child(lastItem->childCount() - 1); - } - - if(emitRemove) - beginRemoveRows(QModelIndex(), sourceItem->pos(), lastItem->pos()); - - int nextPos = 0; - if(prevItem) { - prevItem->setNext(lastItem->next()); - nextPos = prevItem->pos() + 1; - } - - SourceItem *nextItem = lastItem->next(); - while(nextItem) { - nextItem->setPos(nextPos); - nextPos++; - nextItem = nextItem->next(); - } - - sourceItem->parent()->removeChild(sourceItem); - delete sourceItem; - - if(emitRemove) - endRemoveRows(); + +void FlatProxyModel::removeSubTree(const QModelIndex &source_idx, bool emitRemove) +{ + SourceItem *sourceItem = sourceToInternal(source_idx); + if (!sourceItem) + return; + + SourceItem *prevItem = sourceItem->parent(); + if (sourceItem->sourceRow() > 0) { + prevItem = prevItem->child(sourceItem->sourceRow() - 1); + while (prevItem->childCount() > 0) { + prevItem = prevItem->child(prevItem->childCount() - 1); + } + } + + SourceItem *lastItem = sourceItem; + while (lastItem->childCount() > 0) { + lastItem = lastItem->child(lastItem->childCount() - 1); + } + + if (emitRemove) + beginRemoveRows(QModelIndex(), sourceItem->pos(), lastItem->pos()); + + int nextPos = 0; + if (prevItem) { + prevItem->setNext(lastItem->next()); + nextPos = prevItem->pos() + 1; + } + + SourceItem *nextItem = lastItem->next(); + while (nextItem) { + nextItem->setPos(nextPos); + nextPos++; + nextItem = nextItem->next(); + } + + sourceItem->parent()->removeChild(sourceItem); + delete sourceItem; + + if (emitRemove) + endRemoveRows(); } -QModelIndex FlatProxyModel::index(int row, int column, const QModelIndex &parent) const { - if(parent.isValid()) { - qWarning() << "FlatProxyModel::index() called with valid parent:" << parent; - return QModelIndex(); - } - if(!_rootSourceItem) { - qWarning() << "FlatProxyModel::index() while model has no root Item"; - return QModelIndex(); - } +QModelIndex FlatProxyModel::index(int row, int column, const QModelIndex &parent) const +{ + if (parent.isValid()) { + qWarning() << "FlatProxyModel::index() called with valid parent:" << parent; + return QModelIndex(); + } + + if (!_rootSourceItem) { + qWarning() << "FlatProxyModel::index() while model has no root Item"; + return QModelIndex(); + } - SourceItem *item = _rootSourceItem; - while(item->pos() != row) { - item = item->findChild(row); - if(!item) { - qWarning() << "FlatProxyModel::index() no such row:" << row; - return QModelIndex(); + SourceItem *item = _rootSourceItem; + while (item->pos() != row) { + item = item->findChild(row); + if (!item) { + qWarning() << "FlatProxyModel::index() no such row:" << row; + return QModelIndex(); + } } - } - Q_ASSERT(item->pos() == row); - return createIndex(row, column, item); + Q_ASSERT(item->pos() == row); + return createIndex(row, column, item); } -QModelIndex FlatProxyModel::parent(const QModelIndex &index) const { - Q_UNUSED(index) - // this is a flat model - return QModelIndex(); + +QModelIndex FlatProxyModel::parent(const QModelIndex &index) const +{ + Q_UNUSED(index) + // this is a flat model + return QModelIndex(); } -int FlatProxyModel::rowCount(const QModelIndex &index) const { - if(!_rootSourceItem) - return 0; - if(index.isValid()) - return 0; +int FlatProxyModel::rowCount(const QModelIndex &index) const +{ + if (!_rootSourceItem) + return 0; + + if (index.isValid()) + return 0; - SourceItem *item = _rootSourceItem; - while(item->childCount() > 0) { - item = item->child(item->childCount() - 1); - } - return item->pos() + 1; + SourceItem *item = _rootSourceItem; + while (item->childCount() > 0) { + item = item->child(item->childCount() - 1); + } + return item->pos() + 1; } -int FlatProxyModel::columnCount(const QModelIndex &index) const { - Q_UNUSED(index) - if(!sourceModel()) { - return 0; - } else { - return sourceModel()->columnCount(QModelIndex()); - } + +int FlatProxyModel::columnCount(const QModelIndex &index) const +{ + Q_UNUSED(index) + if (!sourceModel()) { + return 0; + } + else { + return sourceModel()->columnCount(QModelIndex()); + } } -FlatProxyModel::SourceItem *FlatProxyModel::sourceToInternal(const QModelIndex &sourceIndex) const { - QList childPath; - for(QModelIndex idx = sourceIndex; idx.isValid(); idx = sourceModel()->parent(idx)) { - childPath.prepend(idx.row()); - } +FlatProxyModel::SourceItem *FlatProxyModel::sourceToInternal(const QModelIndex &sourceIndex) const +{ + QList childPath; + for (QModelIndex idx = sourceIndex; idx.isValid(); idx = sourceModel()->parent(idx)) { + childPath.prepend(idx.row()); + } - Q_ASSERT(!sourceIndex.isValid() || !childPath.isEmpty()); + Q_ASSERT(!sourceIndex.isValid() || !childPath.isEmpty()); - SourceItem *item = _rootSourceItem; - for(int i = 0; i < childPath.count(); i++) { - item = item->child(childPath[i]); - } - return item; + SourceItem *item = _rootSourceItem; + for (int i = 0; i < childPath.count(); i++) { + item = item->child(childPath[i]); + } + return item; } -void FlatProxyModel::on_columnsAboutToBeInserted(const QModelIndex &parent, int start, int end) { - Q_UNUSED(parent); - beginInsertColumns(QModelIndex(), start, end); + +void FlatProxyModel::on_columnsAboutToBeInserted(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent); + beginInsertColumns(QModelIndex(), start, end); } -void FlatProxyModel::on_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { - Q_UNUSED(parent); - beginRemoveColumns(QModelIndex(), start, end); + +void FlatProxyModel::on_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent); + beginRemoveColumns(QModelIndex(), start, end); } -void FlatProxyModel::on_columnsInserted(const QModelIndex &parent, int start, int end) { - Q_UNUSED(parent); - Q_UNUSED(start); - Q_UNUSED(end); - endInsertColumns(); + +void FlatProxyModel::on_columnsInserted(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent); + Q_UNUSED(start); + Q_UNUSED(end); + endInsertColumns(); } -void FlatProxyModel::on_columnsRemoved(const QModelIndex &parent, int start, int end) { - Q_UNUSED(parent); - Q_UNUSED(start); - Q_UNUSED(end); - endRemoveRows(); +void FlatProxyModel::on_columnsRemoved(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent); + Q_UNUSED(start); + Q_UNUSED(end); + endRemoveRows(); } -void FlatProxyModel::on_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { - Q_ASSERT(sourceModel()); - Q_ASSERT(sourceModel()->parent(topLeft) == sourceModel()->parent(bottomRight)); - SourceItem *topLeftItem = sourceToInternal(topLeft); - Q_ASSERT(topLeftItem); - Q_ASSERT(topLeftItem->parent()->childCount() > bottomRight.row()); +void FlatProxyModel::on_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) +{ + Q_ASSERT(sourceModel()); + Q_ASSERT(sourceModel()->parent(topLeft) == sourceModel()->parent(bottomRight)); + + SourceItem *topLeftItem = sourceToInternal(topLeft); + Q_ASSERT(topLeftItem); + Q_ASSERT(topLeftItem->parent()->childCount() > bottomRight.row()); - QModelIndex proxyTopLeft = createIndex(topLeftItem->pos(), topLeft.column(), topLeftItem); - QModelIndex proxyBottomRight = createIndex(topLeftItem->pos() + bottomRight.row() - topLeft.row(), bottomRight.column(), topLeftItem->parent()->child(bottomRight.row())); - emit dataChanged(proxyTopLeft, proxyBottomRight); + QModelIndex proxyTopLeft = createIndex(topLeftItem->pos(), topLeft.column(), topLeftItem); + QModelIndex proxyBottomRight = createIndex(topLeftItem->pos() + bottomRight.row() - topLeft.row(), bottomRight.column(), topLeftItem->parent()->child(bottomRight.row())); + emit dataChanged(proxyTopLeft, proxyBottomRight); } -void FlatProxyModel::on_layoutAboutToBeChanged() { - emit layoutAboutToBeChanged(); - removeSubTree(QModelIndex(), false /* don't emit removeRows() */); -} -void FlatProxyModel::on_layoutChanged() { - insertSubTree(QModelIndex(), false /* don't emit insertRows() */); - emit layoutChanged(); +void FlatProxyModel::on_layoutAboutToBeChanged() +{ + emit layoutAboutToBeChanged(); + removeSubTree(QModelIndex(), false /* don't emit removeRows() */); } -void FlatProxyModel::on_rowsAboutToBeInserted(const QModelIndex &parent, int start, int end) { - Q_ASSERT(sourceModel()); - Q_ASSERT(_rootSourceItem); - SourceItem *sourceItem = sourceToInternal(parent); - Q_ASSERT(sourceItem); +void FlatProxyModel::on_layoutChanged() +{ + insertSubTree(QModelIndex(), false /* don't emit insertRows() */); + emit layoutChanged(); +} - beginInsertRows(QModelIndex(), sourceItem->pos() + start + 1, sourceItem->pos() + end + 1); - SourceItem *prevItem = sourceItem; - if(start > 0) { - prevItem = sourceItem->child(start - 1); - while(prevItem->childCount() > 0) { - prevItem = prevItem->child(prevItem->childCount() - 1); - } - } - Q_ASSERT(prevItem); +void FlatProxyModel::on_rowsAboutToBeInserted(const QModelIndex &parent, int start, int end) +{ + Q_ASSERT(sourceModel()); + Q_ASSERT(_rootSourceItem); - SourceItem *nextItem = prevItem->next(); + SourceItem *sourceItem = sourceToInternal(parent); + Q_ASSERT(sourceItem); - SourceItem *newItem = 0; - int newPos = prevItem->pos() + 1; - for(int row = start; row <= end; row++) { - newItem = new SourceItem(row, sourceItem); - newItem->setPos(newPos); - newPos++; - prevItem->setNext(newItem); - prevItem = newItem; - } - prevItem->setNext(nextItem); + beginInsertRows(QModelIndex(), sourceItem->pos() + start + 1, sourceItem->pos() + end + 1); - while(nextItem) { - nextItem->setPos(newPos); - newPos++; - nextItem = nextItem->next(); - } + SourceItem *prevItem = sourceItem; + if (start > 0) { + prevItem = sourceItem->child(start - 1); + while (prevItem->childCount() > 0) { + prevItem = prevItem->child(prevItem->childCount() - 1); + } + } + Q_ASSERT(prevItem); + + SourceItem *nextItem = prevItem->next(); + + SourceItem *newItem = 0; + int newPos = prevItem->pos() + 1; + for (int row = start; row <= end; row++) { + newItem = new SourceItem(row, sourceItem); + newItem->setPos(newPos); + newPos++; + prevItem->setNext(newItem); + prevItem = newItem; + } + prevItem->setNext(nextItem); + while (nextItem) { + nextItem->setPos(newPos); + newPos++; + nextItem = nextItem->next(); + } } -void FlatProxyModel::on_rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { - Q_ASSERT(sourceModel()); - Q_ASSERT(_rootSourceItem); - SourceItem *sourceItem = sourceToInternal(parent); - beginRemoveRows(QModelIndex(), sourceItem->pos() + start + 1, sourceItem->pos() + end + 1); +void FlatProxyModel::on_rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) +{ + Q_ASSERT(sourceModel()); + Q_ASSERT(_rootSourceItem); + + SourceItem *sourceItem = sourceToInternal(parent); + beginRemoveRows(QModelIndex(), sourceItem->pos() + start + 1, sourceItem->pos() + end + 1); + + // sanity check - if that check fails our indexes would be messed up + for (int row = start; row <= end; row++) { + if (sourceItem->child(row)->childCount() > 0) { + qWarning() << "on_rowsAboutToBeRemoved(): sourceModel() removed rows which have children on their own!" << sourceModel()->index(row, 0, parent); + Q_ASSERT(false); + } + } +} + - // sanity check - if that check fails our indexes would be messed up - for(int row = start; row <= end; row++) { - if(sourceItem->child(row)->childCount() > 0) { - qWarning() << "on_rowsAboutToBeRemoved(): sourceModel() removed rows which have children on their own!" << sourceModel()->index(row, 0, parent); - Q_ASSERT(false); +void FlatProxyModel::on_rowsInserted(const QModelIndex &parent, int start, int end) +{ + Q_ASSERT(sourceModel()); + Q_ASSERT(_rootSourceItem); + + SourceItem *sourceItem = sourceToInternal(parent); + Q_ASSERT(sourceItem); + Q_UNUSED(sourceItem); + + // sanity check - if that check fails our indexes would be messed up + for (int row = start; row <= end; row++) { + QModelIndex child = sourceModel()->index(row, 0, parent); + if (sourceModel()->rowCount(child) > 0) { + qWarning() << "on_rowsInserted(): sourceModel() inserted rows which already have children on their own!" << child; + Q_ASSERT(false); + } } - } + + endInsertRows(); } -void FlatProxyModel::on_rowsInserted(const QModelIndex &parent, int start, int end) { - Q_ASSERT(sourceModel()); - Q_ASSERT(_rootSourceItem); - SourceItem *sourceItem = sourceToInternal(parent); - Q_ASSERT(sourceItem); - Q_UNUSED(sourceItem); +void FlatProxyModel::on_rowsRemoved(const QModelIndex &parent, int start, int end) +{ + Q_ASSERT(sourceModel()); + Q_ASSERT(_rootSourceItem); + + SourceItem *sourceItem = sourceToInternal(parent); + Q_ASSERT(sourceItem); + + SourceItem *prevItem = sourceItem; + if (start > 0) { + prevItem = sourceItem->child(start - 1); + while (prevItem->childCount() > 0) { + prevItem = prevItem->child(prevItem->childCount() - 1); + } + } + Q_ASSERT(prevItem); + + SourceItem *nextItem = sourceItem->child(end)->next(); + + int newPos = prevItem->pos() + 1; + prevItem->setNext(nextItem); - // sanity check - if that check fails our indexes would be messed up - for(int row = start; row <= end; row++) { - QModelIndex child = sourceModel()->index(row, 0, parent); - if(sourceModel()->rowCount(child) > 0) { - qWarning() << "on_rowsInserted(): sourceModel() inserted rows which already have children on their own!" << child; - Q_ASSERT(false); + while (nextItem) { + nextItem->setPos(newPos); + newPos++; + nextItem = nextItem->next(); } - } - endInsertRows(); + SourceItem *childItem; + for (int row = start; row <= end; row++) { + childItem = sourceItem->_childs.takeAt(start); + delete childItem; + } + + endRemoveRows(); } -void FlatProxyModel::on_rowsRemoved(const QModelIndex &parent, int start, int end) { - Q_ASSERT(sourceModel()); - Q_ASSERT(_rootSourceItem); - SourceItem *sourceItem = sourceToInternal(parent); - Q_ASSERT(sourceItem); +// integrity Tets +void FlatProxyModel::linkTest() const +{ + qDebug() << "Checking FlatProxyModel for linklist integrity"; + if (!_rootSourceItem) + return; + + int pos = -1; + SourceItem *item = _rootSourceItem; + while (true) { + qDebug() << item << ":" << item->pos() << "==" << pos; + Q_ASSERT(item->pos() == pos); + pos++; + if (!item->next()) + break; + item = item->next(); + } + qDebug() << "Last item in linklist:" << item << item->pos(); - SourceItem *prevItem = sourceItem; - if(start > 0) { - prevItem = sourceItem->child(start - 1); - while(prevItem->childCount() > 0) { - prevItem = prevItem->child(prevItem->childCount() - 1); + int lastPos = item->pos(); + item = _rootSourceItem; + while (item->childCount() > 0) { + item = item->child(item->childCount() - 1); } - } - Q_ASSERT(prevItem); + qDebug() << "Last item in tree:" << item << item->pos(); + Q_ASSERT(lastPos == item->pos()); + Q_UNUSED(lastPos); - SourceItem *nextItem = sourceItem->child(end)->next(); + qDebug() << "success!"; +} - int newPos = prevItem->pos() + 1; - prevItem->setNext(nextItem); - while(nextItem) { - nextItem->setPos(newPos); - newPos++; - nextItem = nextItem->next(); - } +void FlatProxyModel::completenessTest() const +{ + qDebug() << "Checking FlatProxyModel for Completeness:"; + int pos = -1; + checkChildCount(QModelIndex(), _rootSourceItem, pos); + qDebug() << "success!"; +} - SourceItem *childItem; - for(int row = start; row <= end; row++) { - childItem = sourceItem->_childs.takeAt(start); - delete childItem; - } - endRemoveRows(); -} +void FlatProxyModel::checkChildCount(const QModelIndex &index, const SourceItem *item, int &pos) const +{ + if (!sourceModel()) + return; -// integrity Tets -void FlatProxyModel::linkTest() const { - qDebug() << "Checking FlatProxyModel for linklist integrity"; - if(!_rootSourceItem) - return; - - int pos = -1; - SourceItem *item = _rootSourceItem; - while(true) { - qDebug() << item << ":" << item->pos() << "==" << pos; - Q_ASSERT(item->pos() == pos); - pos++; - if(!item->next()) - break; - item = item->next(); - } - qDebug() << "Last item in linklist:" << item << item->pos(); - - int lastPos = item->pos(); - item = _rootSourceItem; - while(item->childCount() > 0) { - item = item->child(item->childCount() - 1); - } - qDebug() << "Last item in tree:" << item << item->pos(); - Q_ASSERT(lastPos == item->pos()); - Q_UNUSED(lastPos); - - qDebug() << "success!"; -} - -void FlatProxyModel::completenessTest() const { - qDebug() << "Checking FlatProxyModel for Completeness:"; - int pos = -1; - checkChildCount(QModelIndex(), _rootSourceItem, pos); - qDebug() << "success!"; -} - -void FlatProxyModel::checkChildCount(const QModelIndex &index, const SourceItem *item, int &pos) const { - if(!sourceModel()) - return; - - qDebug() << index << "(Item:" << item << "):" << sourceModel()->rowCount(index) << "==" << item->childCount(); - qDebug() << "ProxyPos:" << item->pos() << "==" << pos; - Q_ASSERT(sourceModel()->rowCount(index) == item->childCount()); - - for(int row = 0; row < sourceModel()->rowCount(index); row++) { - pos++; - checkChildCount(sourceModel()->index(row, 0, index), item->child(row), pos); - } + qDebug() << index << "(Item:" << item << "):" << sourceModel()->rowCount(index) << "==" << item->childCount(); + qDebug() << "ProxyPos:" << item->pos() << "==" << pos; + Q_ASSERT(sourceModel()->rowCount(index) == item->childCount()); + + for (int row = 0; row < sourceModel()->rowCount(index); row++) { + pos++; + checkChildCount(sourceModel()->index(row, 0, index), item->child(row), pos); + } } + // ======================================== // SourceItem // ======================================== FlatProxyModel::SourceItem::SourceItem(int row, SourceItem *parent) - : _parent(parent), + : _parent(parent), _pos(-1), _next(0) { - if(parent) { - parent->_childs.insert(row, this); - } + if (parent) { + parent->_childs.insert(row, this); + } } -FlatProxyModel::SourceItem::~SourceItem() { - for(int i = 0; i < childCount(); i++) { - delete child(i); - } - _childs.clear(); -} -int FlatProxyModel::SourceItem::sourceRow() const { - if(!parent()) - return -1; - else - return parent()->_childs.indexOf(const_cast(this)); +FlatProxyModel::SourceItem::~SourceItem() +{ + for (int i = 0; i < childCount(); i++) { + delete child(i); + } + _childs.clear(); } -FlatProxyModel::SourceItem *FlatProxyModel::SourceItem::findChild(int proxyPos) const { - Q_ASSERT(proxyPos > pos()); - Q_ASSERT(_childs.count() > 0); - Q_ASSERT(proxyPos >= _childs[0]->pos()); - int start = 0; - int end = _childs.count() - 1; - int pivot; - while(end - start > 1) { - pivot = (end + start) / 2; - if(_childs[pivot]->pos() > proxyPos) - end = pivot; +int FlatProxyModel::SourceItem::sourceRow() const +{ + if (!parent()) + return -1; else - start = pivot; - } + return parent()->_childs.indexOf(const_cast(this)); +} - if(_childs[end]->pos() <= proxyPos) - return _childs[end]; - else - return _childs[start]; + +FlatProxyModel::SourceItem *FlatProxyModel::SourceItem::findChild(int proxyPos) const +{ + Q_ASSERT(proxyPos > pos()); + Q_ASSERT(_childs.count() > 0); + Q_ASSERT(proxyPos >= _childs[0]->pos()); + + int start = 0; + int end = _childs.count() - 1; + int pivot; + while (end - start > 1) { + pivot = (end + start) / 2; + if (_childs[pivot]->pos() > proxyPos) + end = pivot; + else + start = pivot; + } + + if (_childs[end]->pos() <= proxyPos) + return _childs[end]; + else + return _childs[start]; } diff --git a/src/uisupport/flatproxymodel.h b/src/uisupport/flatproxymodel.h index e0067606..d5fa8179 100644 --- a/src/uisupport/flatproxymodel.h +++ b/src/uisupport/flatproxymodel.h @@ -23,100 +23,103 @@ #include -class FlatProxyModel : public QAbstractProxyModel { - Q_OBJECT +class FlatProxyModel : public QAbstractProxyModel +{ + Q_OBJECT public: - FlatProxyModel(QObject *parent = 0); + FlatProxyModel(QObject *parent = 0); - virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const; - virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const; + virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const; + virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const; - virtual QItemSelection mapSelectionFromSource(const QItemSelection &sourceSelection) const; - virtual QItemSelection mapSelectionToSource(const QItemSelection &proxySelection) const; + virtual QItemSelection mapSelectionFromSource(const QItemSelection &sourceSelection) const; + virtual QItemSelection mapSelectionToSource(const QItemSelection &proxySelection) const; - virtual void setSourceModel(QAbstractItemModel *sourceModel); + virtual void setSourceModel(QAbstractItemModel *sourceModel); - virtual QModelIndex index(int row, int column, const QModelIndex &parent) const; - virtual QModelIndex parent(const QModelIndex &index) const; + virtual QModelIndex index(int row, int column, const QModelIndex &parent) const; + virtual QModelIndex parent(const QModelIndex &index) const; - virtual int rowCount(const QModelIndex &index) const; - virtual int columnCount(const QModelIndex &index) const; + virtual int rowCount(const QModelIndex &index) const; + virtual int columnCount(const QModelIndex &index) const; public slots: - void linkTest() const; - void completenessTest() const; + void linkTest() const; + void completenessTest() const; private slots: - void on_columnsAboutToBeInserted(const QModelIndex &parent, int start, int end); - void on_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end); - void on_columnsInserted(const QModelIndex &parent, int start, int end); - void on_columnsRemoved(const QModelIndex &parent, int start, int end); - - void on_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + void on_columnsAboutToBeInserted(const QModelIndex &parent, int start, int end); + void on_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end); + void on_columnsInserted(const QModelIndex &parent, int start, int end); + void on_columnsRemoved(const QModelIndex &parent, int start, int end); + + void on_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); // void on_headerDataChanged(Qt::Orientation orientation, int first, int last); - void on_layoutAboutToBeChanged(); - void on_layoutChanged(); + void on_layoutAboutToBeChanged(); + void on_layoutChanged(); - inline void on_modelAboutToBeReset() { reset(); } - // void on_modelReset(); + inline void on_modelAboutToBeReset() { reset(); } + // void on_modelReset(); - void on_rowsAboutToBeInserted(const QModelIndex &parent, int start, int end); - void on_rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); - void on_rowsInserted(const QModelIndex &parent, int start, int end); - void on_rowsRemoved(const QModelIndex &parent, int start, int end); + void on_rowsAboutToBeInserted(const QModelIndex &parent, int start, int end); + void on_rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); + void on_rowsInserted(const QModelIndex &parent, int start, int end); + void on_rowsRemoved(const QModelIndex &parent, int start, int end); private: - QList _childCount; + QList _childCount; - class SourceItem; - SourceItem *_rootSourceItem; + class SourceItem; + SourceItem *_rootSourceItem; - void insertSubTree(const QModelIndex &source_idx, bool emitInsert = true); - SourceItem *insertSubTreeHelper(SourceItem *parentItem, SourceItem *lastItem_, const QModelIndex &source_idx); + void insertSubTree(const QModelIndex &source_idx, bool emitInsert = true); + SourceItem *insertSubTreeHelper(SourceItem *parentItem, SourceItem *lastItem_, const QModelIndex &source_idx); - void removeSubTree(const QModelIndex &source_idx, bool emitRemove = true); + void removeSubTree(const QModelIndex &source_idx, bool emitRemove = true); - SourceItem *sourceToInternal(const QModelIndex &sourceIndex) const; + SourceItem *sourceToInternal(const QModelIndex &sourceIndex) const; - void checkChildCount(const QModelIndex &index, const SourceItem *item, int &pos) const; + void checkChildCount(const QModelIndex &index, const SourceItem *item, int &pos) const; - class _RangeRect { - public: - int left, right, top, bottom; - SourceItem *topItem, *bottomItem; - bool operator<(const _RangeRect &other) const; - }; + class _RangeRect + { +public: + int left, right, top, bottom; + SourceItem *topItem, *bottomItem; + bool operator<(const _RangeRect &other) const; + }; }; -class FlatProxyModel::SourceItem { +class FlatProxyModel::SourceItem +{ public: - SourceItem(int row = 0, SourceItem *parent = 0); - ~SourceItem(); + SourceItem(int row = 0, SourceItem *parent = 0); + ~SourceItem(); - inline SourceItem *parent() const { return _parent; } - inline SourceItem *child(int i) const { return _childs[i]; } - inline int childCount() const { return _childs.count(); } + inline SourceItem *parent() const { return _parent; } + inline SourceItem *child(int i) const { return _childs[i]; } + inline int childCount() const { return _childs.count(); } - inline int pos() const { return _pos; } - inline SourceItem *next() const { return _next; } + inline int pos() const { return _pos; } + inline SourceItem *next() const { return _next; } - int sourceRow() const; - SourceItem *findChild(int proxyPos) const; + int sourceRow() const; + SourceItem *findChild(int proxyPos) const; private: - inline void removeChild(SourceItem *item) { _childs.removeAt(_childs.indexOf(item)); } - inline void setPos(int i) { _pos = i; } - inline void setNext(SourceItem *next) { _next = next; } + inline void removeChild(SourceItem *item) { _childs.removeAt(_childs.indexOf(item)); } + inline void setPos(int i) { _pos = i; } + inline void setNext(SourceItem *next) { _next = next; } - SourceItem *_parent; - QList _childs; - int _pos; - SourceItem *_next; + SourceItem *_parent; + QList _childs; + int _pos; + SourceItem *_next; - friend class FlatProxyModel; + friend class FlatProxyModel; }; diff --git a/src/uisupport/fontselector.cpp b/src/uisupport/fontselector.cpp index 457c1d9b..27627296 100644 --- a/src/uisupport/fontselector.cpp +++ b/src/uisupport/fontselector.cpp @@ -26,40 +26,45 @@ #include "fontselector.h" -FontSelector::FontSelector(QWidget *parent) : QWidget(parent) { - QHBoxLayout *layout = new QHBoxLayout(this); - QPushButton *chooseButton = new QPushButton(tr("Choose..."), this); - connect(chooseButton, SIGNAL(clicked()), SLOT(chooseFont())); +FontSelector::FontSelector(QWidget *parent) : QWidget(parent) +{ + QHBoxLayout *layout = new QHBoxLayout(this); + QPushButton *chooseButton = new QPushButton(tr("Choose..."), this); + connect(chooseButton, SIGNAL(clicked()), SLOT(chooseFont())); - layout->addWidget(_demo = new QLabel("Font")); - layout->addWidget(chooseButton); - layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(_demo = new QLabel("Font")); + layout->addWidget(chooseButton); + layout->setContentsMargins(0, 0, 0, 0); - _demo->setFrameStyle(QFrame::StyledPanel); - _demo->setFrameShadow(QFrame::Sunken); - _demo->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); - _font = font(); + _demo->setFrameStyle(QFrame::StyledPanel); + _demo->setFrameShadow(QFrame::Sunken); + _demo->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); + _font = font(); } -void FontSelector::setSelectedFont(const QFont &font) { - _font = font; - _demo->setText(QString("%1 %2pt").arg(font.family()).arg(font.pointSize())); - _demo->setFont(font); - emit fontChanged(font); -} -void FontSelector::chooseFont() { - bool ok; - QFont font = QFontDialog::getFont(&ok, _demo->font()); - if(ok) { - setSelectedFont(font); - } +void FontSelector::setSelectedFont(const QFont &font) +{ + _font = font; + _demo->setText(QString("%1 %2pt").arg(font.family()).arg(font.pointSize())); + _demo->setFont(font); + emit fontChanged(font); } -void FontSelector::changeEvent(QEvent *e) { - if(e->type() == QEvent::StyleChange) { - _demo->setFont(_font); - } + +void FontSelector::chooseFont() +{ + bool ok; + QFont font = QFontDialog::getFont(&ok, _demo->font()); + if (ok) { + setSelectedFont(font); + } } +void FontSelector::changeEvent(QEvent *e) +{ + if (e->type() == QEvent::StyleChange) { + _demo->setFont(_font); + } +} diff --git a/src/uisupport/fontselector.h b/src/uisupport/fontselector.h index 378bf296..640c437b 100644 --- a/src/uisupport/fontselector.h +++ b/src/uisupport/fontselector.h @@ -24,30 +24,32 @@ #include #include -class FontSelector : public QWidget { - Q_OBJECT - Q_PROPERTY(QFont selectedFont READ selectedFont WRITE setSelectedFont) +class FontSelector : public QWidget +{ + Q_OBJECT + Q_PROPERTY(QFont selectedFont READ selectedFont WRITE setSelectedFont) -public: - FontSelector(QWidget *parent = 0); +public : + FontSelector(QWidget *parent = 0); - inline const QFont &selectedFont() const { return _font; } + inline const QFont &selectedFont() const { return _font; } public slots: - void setSelectedFont(const QFont &font); + void setSelectedFont(const QFont &font); signals: - void fontChanged(const QFont &); + void fontChanged(const QFont &); protected: - void changeEvent(QEvent *e); + void changeEvent(QEvent *e); protected slots: - void chooseFont(); + void chooseFont(); private: - QFont _font; - QLabel *_demo; + QFont _font; + QLabel *_demo; }; + #endif // FONTSELECTOR_H_ diff --git a/src/uisupport/graphicalui.cpp b/src/uisupport/graphicalui.cpp index 6bccbc70..5d85500d 100644 --- a/src/uisupport/graphicalui.cpp +++ b/src/uisupport/graphicalui.cpp @@ -44,197 +44,231 @@ ToolBarActionProvider *GraphicalUi::_toolBarActionProvider = 0; UiStyle *GraphicalUi::_uiStyle = 0; bool GraphicalUi::_onAllDesktops = false; -GraphicalUi::GraphicalUi(QObject *parent) : AbstractUi(parent) { - Q_ASSERT(!_instance); - _instance = this; +GraphicalUi::GraphicalUi(QObject *parent) : AbstractUi(parent) +{ + Q_ASSERT(!_instance); + _instance = this; #ifdef Q_WS_WIN - _dwTickCount = 0; + _dwTickCount = 0; #endif } -void GraphicalUi::init() { + +void GraphicalUi::init() +{ #ifdef Q_WS_WIN - mainWidget()->installEventFilter(this); + mainWidget()->installEventFilter(this); #endif } -ActionCollection *GraphicalUi::actionCollection(const QString &category, const QString &translatedCategory) { - if(_actionCollections.contains(category)) - return _actionCollections.value(category); - ActionCollection *coll = new ActionCollection(_mainWidget); - if(!translatedCategory.isEmpty()) - coll->setProperty("Category", translatedCategory); - else - coll->setProperty("Category", category); +ActionCollection *GraphicalUi::actionCollection(const QString &category, const QString &translatedCategory) +{ + if (_actionCollections.contains(category)) + return _actionCollections.value(category); + ActionCollection *coll = new ActionCollection(_mainWidget); + + if (!translatedCategory.isEmpty()) + coll->setProperty("Category", translatedCategory); + else + coll->setProperty("Category", category); - if(_mainWidget) - coll->addAssociatedWidget(_mainWidget); - _actionCollections.insert(category, coll); - return coll; + if (_mainWidget) + coll->addAssociatedWidget(_mainWidget); + _actionCollections.insert(category, coll); + return coll; } -QHash GraphicalUi::actionCollections() { - return _actionCollections; + +QHash GraphicalUi::actionCollections() +{ + return _actionCollections; } -void GraphicalUi::loadShortcuts() { - foreach(ActionCollection *coll, actionCollections()) + +void GraphicalUi::loadShortcuts() +{ + foreach(ActionCollection *coll, actionCollections()) coll->readSettings(); } -void GraphicalUi::saveShortcuts() { - ShortcutSettings s; - s.clear(); - foreach(ActionCollection *coll, actionCollections()) + +void GraphicalUi::saveShortcuts() +{ + ShortcutSettings s; + s.clear(); + foreach(ActionCollection *coll, actionCollections()) coll->writeSettings(); } -void GraphicalUi::setMainWidget(QWidget *widget) { - _mainWidget = widget; + +void GraphicalUi::setMainWidget(QWidget *widget) +{ + _mainWidget = widget; } -void GraphicalUi::setContextMenuActionProvider(ContextMenuActionProvider *provider) { - _contextMenuActionProvider = provider; + +void GraphicalUi::setContextMenuActionProvider(ContextMenuActionProvider *provider) +{ + _contextMenuActionProvider = provider; } -void GraphicalUi::setToolBarActionProvider(ToolBarActionProvider *provider) { - _toolBarActionProvider = provider; + +void GraphicalUi::setToolBarActionProvider(ToolBarActionProvider *provider) +{ + _toolBarActionProvider = provider; } -void GraphicalUi::setUiStyle(UiStyle *style) { - _uiStyle = style; + +void GraphicalUi::setUiStyle(UiStyle *style) +{ + _uiStyle = style; } -void GraphicalUi::disconnectedFromCore() { - _contextMenuActionProvider->disconnectedFromCore(); - _toolBarActionProvider->disconnectedFromCore(); - AbstractUi::disconnectedFromCore(); + +void GraphicalUi::disconnectedFromCore() +{ + _contextMenuActionProvider->disconnectedFromCore(); + _toolBarActionProvider->disconnectedFromCore(); + AbstractUi::disconnectedFromCore(); } -bool GraphicalUi::eventFilter(QObject *obj, QEvent *event) { + +bool GraphicalUi::eventFilter(QObject *obj, QEvent *event) +{ #ifdef Q_WS_WIN - if(obj == mainWidget() && event->type() == QEvent::ActivationChange) { - _dwTickCount = GetTickCount(); - } + if (obj == mainWidget() && event->type() == QEvent::ActivationChange) { + _dwTickCount = GetTickCount(); + } #endif - return AbstractUi::eventFilter(obj, event); + return AbstractUi::eventFilter(obj, event); } + // Code taken from KStatusNotifierItem for handling minimize/restore -bool GraphicalUi::checkMainWidgetVisibility(bool perform) { +bool GraphicalUi::checkMainWidgetVisibility(bool perform) +{ #ifdef Q_WS_WIN - // the problem is that we lose focus when the systray icon is activated - // and we don't know the former active window - // therefore we watch for activation event and use our stopwatch :) - if(GetTickCount() - _dwTickCount < 300) { - // we were active in the last 300ms -> hide it - if(perform) - minimizeRestore(false); - return false; - } else { - if(perform) - minimizeRestore(true); - return true; - } + // the problem is that we lose focus when the systray icon is activated + // and we don't know the former active window + // therefore we watch for activation event and use our stopwatch :) + if (GetTickCount() - _dwTickCount < 300) { + // we were active in the last 300ms -> hide it + if (perform) + minimizeRestore(false); + return false; + } + else { + if (perform) + minimizeRestore(true); + return true; + } #elif defined(HAVE_KDE) && defined(Q_WS_X11) - KWindowInfo info1 = KWindowSystem::windowInfo(mainWidget()->winId(), NET::XAWMState | NET::WMState | NET::WMDesktop); - // mapped = visible (but possibly obscured) - bool mapped = (info1.mappingState() == NET::Visible) && !info1.isMinimized(); - - // - not mapped -> show, raise, focus - // - mapped - // - obscured -> raise, focus - // - not obscured -> hide - //info1.mappingState() != NET::Visible -> window on another desktop? - if(!mapped) { - if(perform) - minimizeRestore(true); - return true; - - } else { - QListIterator< WId > it (KWindowSystem::stackingOrder()); - it.toBack(); - while(it.hasPrevious()) { - WId id = it.previous(); - if(id == mainWidget()->winId()) - break; - - KWindowInfo info2 = KWindowSystem::windowInfo(id, NET::WMDesktop | NET::WMGeometry | NET::XAWMState | NET::WMState | NET::WMWindowType); - - if(info2.mappingState() != NET::Visible) - continue; // not visible on current desktop -> ignore - - if(!info2.geometry().intersects(mainWidget()->geometry())) - continue; // not obscuring the window -> ignore - - if(!info1.hasState(NET::KeepAbove) && info2.hasState(NET::KeepAbove)) - continue; // obscured by window kept above -> ignore - - NET::WindowType type = info2.windowType(NET::NormalMask | NET::DesktopMask - | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask - | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask); - - if(type == NET::Dock || type == NET::TopMenu) - continue; // obscured by dock or topmenu -> ignore - - if(perform) { - KWindowSystem::raiseWindow(mainWidget()->winId()); - KWindowSystem::activateWindow(mainWidget()->winId()); - } - return true; + KWindowInfo info1 = KWindowSystem::windowInfo(mainWidget()->winId(), NET::XAWMState | NET::WMState | NET::WMDesktop); + // mapped = visible (but possibly obscured) + bool mapped = (info1.mappingState() == NET::Visible) && !info1.isMinimized(); + + // - not mapped -> show, raise, focus + // - mapped + // - obscured -> raise, focus + // - not obscured -> hide + //info1.mappingState() != NET::Visible -> window on another desktop? + if (!mapped) { + if (perform) + minimizeRestore(true); + return true; } - - //not on current desktop? - if(!info1.isOnCurrentDesktop()) { - if(perform) - KWindowSystem::activateWindow(mainWidget()->winId()); - return true; + else { + QListIterator it(KWindowSystem::stackingOrder()); + it.toBack(); + while (it.hasPrevious()) { + WId id = it.previous(); + if (id == mainWidget()->winId()) + break; + + KWindowInfo info2 = KWindowSystem::windowInfo(id, NET::WMDesktop | NET::WMGeometry | NET::XAWMState | NET::WMState | NET::WMWindowType); + + if (info2.mappingState() != NET::Visible) + continue; // not visible on current desktop -> ignore + + if (!info2.geometry().intersects(mainWidget()->geometry())) + continue; // not obscuring the window -> ignore + + if (!info1.hasState(NET::KeepAbove) && info2.hasState(NET::KeepAbove)) + continue; // obscured by window kept above -> ignore + + NET::WindowType type = info2.windowType(NET::NormalMask | NET::DesktopMask + | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask + | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask); + + if (type == NET::Dock || type == NET::TopMenu) + continue; // obscured by dock or topmenu -> ignore + + if (perform) { + KWindowSystem::raiseWindow(mainWidget()->winId()); + KWindowSystem::activateWindow(mainWidget()->winId()); + } + return true; + } + + //not on current desktop? + if (!info1.isOnCurrentDesktop()) { + if (perform) + KWindowSystem::activateWindow(mainWidget()->winId()); + return true; + } + + if (perform) + minimizeRestore(false); // hide + return false; } - - if(perform) - minimizeRestore(false); // hide - return false; - } #else - if(!mainWidget()->isVisible() || mainWidget()->isMinimized() || !mainWidget()->isActiveWindow()) { - if(perform) - minimizeRestore(true); - return true; - } else { - if(perform) - minimizeRestore(false); - return false; - } + if (!mainWidget()->isVisible() || mainWidget()->isMinimized() || !mainWidget()->isActiveWindow()) { + if (perform) + minimizeRestore(true); + return true; + } + else { + if (perform) + minimizeRestore(false); + return false; + } #endif - return true; + return true; } -bool GraphicalUi::isMainWidgetVisible() { - return !instance()->checkMainWidgetVisibility(false); + +bool GraphicalUi::isMainWidgetVisible() +{ + return !instance()->checkMainWidgetVisibility(false); } -void GraphicalUi::minimizeRestore(bool show) { - if(show) - activateMainWidget(); - else - hideMainWidget(); + +void GraphicalUi::minimizeRestore(bool show) +{ + if (show) + activateMainWidget(); + else + hideMainWidget(); } -void GraphicalUi::activateMainWidget() { + +void GraphicalUi::activateMainWidget() +{ #ifdef HAVE_KDE # ifdef Q_WS_X11 KWindowInfo info = KWindowSystem::windowInfo(mainWidget()->winId(), NET::WMDesktop | NET::WMFrameExtents); - if(_onAllDesktops) { - KWindowSystem::setOnAllDesktops(mainWidget()->winId(), true); - } else { - KWindowSystem::setCurrentDesktop(info.desktop()); + if (_onAllDesktops) { + KWindowSystem::setOnAllDesktops(mainWidget()->winId(), true); + } + else { + KWindowSystem::setCurrentDesktop(info.desktop()); } mainWidget()->move(info.frameGeometry().topLeft()); // avoid placement policies @@ -251,35 +285,38 @@ void GraphicalUi::activateMainWidget() { #else /* HAVE_KDE */ #ifdef Q_WS_X11 - // Bypass focus stealing prevention - QX11Info::setAppUserTime(QX11Info::appTime()); + // Bypass focus stealing prevention + QX11Info::setAppUserTime(QX11Info::appTime()); #endif - if(mainWidget()->windowState() & Qt::WindowMinimized) { - // restore - mainWidget()->setWindowState((mainWidget()->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); - } + if (mainWidget()->windowState() & Qt::WindowMinimized) { + // restore + mainWidget()->setWindowState((mainWidget()->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); + } - // this does not actually work on all platforms... and causes more evil than good - // mainWidget()->move(mainWidget()->frameGeometry().topLeft()); // avoid placement policies - mainWidget()->show(); - mainWidget()->raise(); - mainWidget()->activateWindow(); + // this does not actually work on all platforms... and causes more evil than good + // mainWidget()->move(mainWidget()->frameGeometry().topLeft()); // avoid placement policies + mainWidget()->show(); + mainWidget()->raise(); + mainWidget()->activateWindow(); #endif /* HAVE_KDE */ } -void GraphicalUi::hideMainWidget() { +void GraphicalUi::hideMainWidget() +{ #if defined(HAVE_KDE) && defined(Q_WS_X11) - KWindowInfo info = KWindowSystem::windowInfo(mainWidget()->winId(), NET::WMDesktop | NET::WMFrameExtents); - _onAllDesktops = info.onAllDesktops(); + KWindowInfo info = KWindowSystem::windowInfo(mainWidget()->winId(), NET::WMDesktop | NET::WMFrameExtents); + _onAllDesktops = info.onAllDesktops(); #endif - if(instance()->isHidingMainWidgetAllowed()) - mainWidget()->hide(); + if (instance()->isHidingMainWidgetAllowed()) + mainWidget()->hide(); } -void GraphicalUi::toggleMainWidget() { - instance()->checkMainWidgetVisibility(true); + +void GraphicalUi::toggleMainWidget() +{ + instance()->checkMainWidgetVisibility(true); } diff --git a/src/uisupport/graphicalui.h b/src/uisupport/graphicalui.h index 989ee7fc..11248d94 100644 --- a/src/uisupport/graphicalui.h +++ b/src/uisupport/graphicalui.h @@ -32,95 +32,96 @@ class UiStyle; # include #endif -class GraphicalUi : public AbstractUi { - Q_OBJECT +class GraphicalUi : public AbstractUi +{ + Q_OBJECT public: - GraphicalUi(QObject *parent = 0); - virtual void init(); + GraphicalUi(QObject *parent = 0); + virtual void init(); - //! Access global ActionCollections. - /** These ActionCollections are associated with the main window, i.e. they contain global - * actions (and thus, shortcuts). Widgets providing application-wide shortcuts should - * create appropriate Action objects using GraphicalUi::actionCollection(cat)->add\(). - * @param category The category (default: "General") - */ - static ActionCollection *actionCollection(const QString &category = "General", const QString &translatedCategory = QString()); - static QHash actionCollections(); + //! Access global ActionCollections. + /** These ActionCollections are associated with the main window, i.e. they contain global + * actions (and thus, shortcuts). Widgets providing application-wide shortcuts should + * create appropriate Action objects using GraphicalUi::actionCollection(cat)->add\(). + * @param category The category (default: "General") + */ + static ActionCollection *actionCollection(const QString &category = "General", const QString &translatedCategory = QString()); + static QHash actionCollections(); - //! Load custom shortcuts from ShortcutSettings - /** @note This method assumes that all configurable actions are defined when being called - */ - static void loadShortcuts(); + //! Load custom shortcuts from ShortcutSettings + /** @note This method assumes that all configurable actions are defined when being called + */ + static void loadShortcuts(); - //! Save custom shortcuts to ShortcutSettings - static void saveShortcuts(); + //! Save custom shortcuts to ShortcutSettings + static void saveShortcuts(); - inline static ContextMenuActionProvider *contextMenuActionProvider(); - inline static ToolBarActionProvider *toolBarActionProvider(); - inline static UiStyle *uiStyle(); - inline static QWidget *mainWidget(); + inline static ContextMenuActionProvider *contextMenuActionProvider(); + inline static ToolBarActionProvider *toolBarActionProvider(); + inline static UiStyle *uiStyle(); + inline static QWidget *mainWidget(); - //! Force the main widget to the front and focus it (may not work in all window systems) - static void activateMainWidget(); + //! Force the main widget to the front and focus it (may not work in all window systems) + static void activateMainWidget(); - //! Hide main widget (storing the current desktop if possible) - static void hideMainWidget(); + //! Hide main widget (storing the current desktop if possible) + static void hideMainWidget(); - //! Toggle main widget - static void toggleMainWidget(); + //! Toggle main widget + static void toggleMainWidget(); - //! Check if the main widget if (fully, in KDE) visible - static bool isMainWidgetVisible(); + //! Check if the main widget if (fully, in KDE) visible + static bool isMainWidgetVisible(); protected: - //! This is the widget we associate global actions with, typically the main window - void setMainWidget(QWidget *); + //! This is the widget we associate global actions with, typically the main window + void setMainWidget(QWidget *); - //! Check if the mainWidget is visible and optionally toggle its visibility - /** With KDE integration, we check if the mainWidget is (partially) obscured in order to determine if - * it should be activated or hidden. Without KDE, we need to resort to checking the current state - * as Qt knows it, ignoring windows covering it. - * @param performToggle If true, toggle the window's state in addition to checking visibility - * @return True, if the window is currently *not* visible (needs activation) - */ - bool checkMainWidgetVisibility(bool performToggle); + //! Check if the mainWidget is visible and optionally toggle its visibility + /** With KDE integration, we check if the mainWidget is (partially) obscured in order to determine if + * it should be activated or hidden. Without KDE, we need to resort to checking the current state + * as Qt knows it, ignoring windows covering it. + * @param performToggle If true, toggle the window's state in addition to checking visibility + * @return True, if the window is currently *not* visible (needs activation) + */ + bool checkMainWidgetVisibility(bool performToggle); - //! Minimize to or restore main widget - virtual void minimizeRestore(bool show); + //! Minimize to or restore main widget + virtual void minimizeRestore(bool show); - //! Whether it is allowed to hide the mainWidget - /** The default implementation returns false, meaning that we won't hide the mainWidget even - * if requested. This is to prevent hiding in case we don't have a tray icon to restore from. - */ - virtual inline bool isHidingMainWidgetAllowed() const; + //! Whether it is allowed to hide the mainWidget + /** The default implementation returns false, meaning that we won't hide the mainWidget even + * if requested. This is to prevent hiding in case we don't have a tray icon to restore from. + */ + virtual inline bool isHidingMainWidgetAllowed() const; - void setContextMenuActionProvider(ContextMenuActionProvider *); - void setToolBarActionProvider(ToolBarActionProvider *); - void setUiStyle(UiStyle *); + void setContextMenuActionProvider(ContextMenuActionProvider *); + void setToolBarActionProvider(ToolBarActionProvider *); + void setUiStyle(UiStyle *); - virtual bool eventFilter(QObject *obj, QEvent *event); + virtual bool eventFilter(QObject *obj, QEvent *event); protected slots: - virtual void disconnectedFromCore(); + virtual void disconnectedFromCore(); private: - static inline GraphicalUi *instance(); + static inline GraphicalUi *instance(); - static GraphicalUi *_instance; - static QWidget *_mainWidget; - static QHash _actionCollections; - static ContextMenuActionProvider *_contextMenuActionProvider; - static ToolBarActionProvider *_toolBarActionProvider; - static UiStyle *_uiStyle; - static bool _onAllDesktops; + static GraphicalUi *_instance; + static QWidget *_mainWidget; + static QHash _actionCollections; + static ContextMenuActionProvider *_contextMenuActionProvider; + static ToolBarActionProvider *_toolBarActionProvider; + static UiStyle *_uiStyle; + static bool _onAllDesktops; #ifdef Q_WS_WIN - DWORD _dwTickCount; + DWORD _dwTickCount; #endif - }; + // inlines GraphicalUi *GraphicalUi::instance() { return _instance; } diff --git a/src/uisupport/icon.cpp b/src/uisupport/icon.cpp index a8785b20..e758e047 100644 --- a/src/uisupport/icon.cpp +++ b/src/uisupport/icon.cpp @@ -23,23 +23,29 @@ #include "icon.h" #include "iconloader.h" -Icon::Icon() : QIcon() { - +Icon::Icon() : QIcon() +{ } -Icon::Icon(const QString &name) : QIcon() { - addPixmap(IconLoader::global()->loadIcon(name, IconLoader::Desktop)); + +Icon::Icon(const QString &name) : QIcon() +{ + addPixmap(IconLoader::global()->loadIcon(name, IconLoader::Desktop)); } -Icon::Icon(const QIcon& copy) : QIcon(copy) { +Icon::Icon(const QIcon ©) : QIcon(copy) +{ } -Icon& Icon::operator=(const Icon &other) { - if (this != &other) { - QIcon::operator=(other); - } - return *this; + +Icon &Icon::operator=(const Icon &other) +{ + if (this != &other) { + QIcon::operator=(other); + } + return *this; } + #endif diff --git a/src/uisupport/icon.h b/src/uisupport/icon.h index 2c1d62ee..fd317d00 100644 --- a/src/uisupport/icon.h +++ b/src/uisupport/icon.h @@ -30,26 +30,28 @@ * The overloaded ctor uses IconLoader to locate an icon with this basename in the current theme * or in Qt Resources. */ -class Icon : public QIcon { - - public: +class Icon : public QIcon +{ +public: Icon(); explicit Icon(const QString &iconName); - explicit Icon(const QIcon& copy); + explicit Icon(const QIcon ©); - Icon& operator=(const Icon &other); + Icon &operator=(const Icon &other); }; + #else /* HAVE_KDE */ #include -class Icon : public KIcon { - - public: +class Icon : public KIcon +{ +public: inline Icon() : KIcon() {}; inline explicit Icon(const QString &iconName) : KIcon(iconName) {}; - inline explicit Icon(const QIcon& copy) : KIcon(copy) {}; + inline explicit Icon(const QIcon ©) : KIcon(copy) {}; }; + #endif /* HAVE_KDE */ #endif diff --git a/src/uisupport/iconloader.cpp b/src/uisupport/iconloader.cpp index 1c3d6e77..1ec2682f 100644 --- a/src/uisupport/iconloader.cpp +++ b/src/uisupport/iconloader.cpp @@ -32,143 +32,160 @@ IconLoader IconLoader::_iconLoader; int IconLoader::_groupSize[] = { 48, 22, 22, 16, 32, 22 }; // default sizes taken from Oxygen -IconLoader *IconLoader::global() { - // Workaround: the static _iconLoader might be initialized before the resources it needs - // This way, first call to global() will init it by setting the theme - if(_iconLoader.theme().isEmpty()) - _iconLoader.setTheme("oxygen"); - return &_iconLoader; +IconLoader *IconLoader::global() +{ + // Workaround: the static _iconLoader might be initialized before the resources it needs + // This way, first call to global() will init it by setting the theme + if (_iconLoader.theme().isEmpty()) + _iconLoader.setTheme("oxygen"); + return &_iconLoader; } -IconLoader::IconLoader(QObject *parent) : QObject(parent) { - // setTheme("oxygen"); +IconLoader::IconLoader(QObject *parent) : QObject(parent) +{ + // setTheme("oxygen"); } -IconLoader::~IconLoader() { +IconLoader::~IconLoader() +{ } -void IconLoader::setTheme(const QString &theme) { - _theme = theme; - // check which dirs could contain themed icons - _themedIconDirNames.clear(); - _plainIconDirNames.clear(); - - // First, look for a system theme - // This is supposed to only work on Unix, though other platforms might set $XDG_DATA_DIRS if they please. - QStringList iconDirNames = QString(qgetenv("XDG_DATA_DIRS")).split(':', QString::SkipEmptyParts); - if(!iconDirNames.isEmpty()) { - for(int i = 0; i < iconDirNames.count(); i++) - iconDirNames[i].append(QString("/icons/")); - } + +void IconLoader::setTheme(const QString &theme) +{ + _theme = theme; + // check which dirs could contain themed icons + _themedIconDirNames.clear(); + _plainIconDirNames.clear(); + + // First, look for a system theme + // This is supposed to only work on Unix, though other platforms might set $XDG_DATA_DIRS if they please. + QStringList iconDirNames = QString(qgetenv("XDG_DATA_DIRS")).split(':', QString::SkipEmptyParts); + if (!iconDirNames.isEmpty()) { + for (int i = 0; i < iconDirNames.count(); i++) + iconDirNames[i].append(QString("/icons/")); + } #ifdef Q_OS_UNIX - else { - // Provide a fallback - iconDirNames << "/usr/share/icons/"; - } - // Add our prefix too - QString appDir = QCoreApplication::applicationDirPath(); - int binpos = appDir.lastIndexOf("/bin"); - if(binpos >= 0) { - appDir.replace(binpos, 4, "/share"); - appDir.append("/icons/"); - if(!iconDirNames.contains(appDir)) - iconDirNames.append(appDir); - } + else { + // Provide a fallback + iconDirNames << "/usr/share/icons/"; + } + // Add our prefix too + QString appDir = QCoreApplication::applicationDirPath(); + int binpos = appDir.lastIndexOf("/bin"); + if (binpos >= 0) { + appDir.replace(binpos, 4, "/share"); + appDir.append("/icons/"); + if (!iconDirNames.contains(appDir)) + iconDirNames.append(appDir); + } #endif - // Now look for an icons/ subdir in our data paths - foreach(const QString &dir, Quassel::dataDirPaths()) + // Now look for an icons/ subdir in our data paths + foreach(const QString &dir, Quassel::dataDirPaths()) iconDirNames << dir + "icons/"; - // Add our resource path too - iconDirNames << ":/icons/"; - - // Ready do add theme names - foreach(const QString &dir, iconDirNames) { - QString path = dir + theme + '/'; - if(QFile::exists(path)) - _themedIconDirNames << path; - } - foreach(const QString &dir, iconDirNames) { - QString path = dir + "hicolor/"; - if(QFile::exists(path)) - _themedIconDirNames << path; - } - - // We ship some plain (non-themed) icons in $data/pics - foreach(const QString &dir, Quassel::dataDirPaths()) { - QString path = dir + "pics/"; - if(QFile::exists(path)) - _plainIconDirNames << path; - } - // And of course, our resource path - if(QFile::exists(":/pics")) - _plainIconDirNames << ":/pics"; + // Add our resource path too + iconDirNames << ":/icons/"; + // Ready do add theme names + foreach(const QString &dir, iconDirNames) { + QString path = dir + theme + '/'; + if (QFile::exists(path)) + _themedIconDirNames << path; + } + foreach(const QString &dir, iconDirNames) { + QString path = dir + "hicolor/"; + if (QFile::exists(path)) + _themedIconDirNames << path; + } + + // We ship some plain (non-themed) icons in $data/pics + foreach(const QString &dir, Quassel::dataDirPaths()) { + QString path = dir + "pics/"; + if (QFile::exists(path)) + _plainIconDirNames << path; + } + // And of course, our resource path + if (QFile::exists(":/pics")) + _plainIconDirNames << ":/pics"; } + // TODO: optionally implement cache (speed/memory tradeoff?) -QPixmap IconLoader::loadIcon(const QString &name, IconLoader::Group group, int size) { - if(group < 0 || group >= LastGroup) { - qWarning() << "Invalid icon group!"; - return QPixmap(); - } - if(size == 0) - size = _groupSize[group]; - - QString path = findIconPath(name, size); - if(path.isEmpty()) return QPixmap(); - - // load the icon - return QPixmap(path); +QPixmap IconLoader::loadIcon(const QString &name, IconLoader::Group group, int size) +{ + if (group < 0 || group >= LastGroup) { + qWarning() << "Invalid icon group!"; + return QPixmap(); + } + if (size == 0) + size = _groupSize[group]; + + QString path = findIconPath(name, size); + if (path.isEmpty()) return QPixmap(); + + // load the icon + return QPixmap(path); } -QString IconLoader::findIconPath(const QString &name, int size) { - QString fname = QString("%1.png").arg(name); // we only support PNG so far - // First, look for a themed icon... we don't do anything fancy here, only exact match for both name and size - foreach(QString basedir, _themedIconDirNames) { - QDir sizedir(QString("%1/%2x%2").arg(basedir).arg(QString::number(size))); - if(sizedir.exists()) { - // ignore context, i.e. scan all subdirs - QStringList contextdirs = sizedir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); - foreach(QString dir, contextdirs) { - QString path = QString("%1/%2/%3").arg(sizedir.absolutePath(), dir, fname); - if(QFile::exists(path)) return path; - } + +QString IconLoader::findIconPath(const QString &name, int size) +{ + QString fname = QString("%1.png").arg(name); // we only support PNG so far + // First, look for a themed icon... we don't do anything fancy here, only exact match for both name and size + foreach(QString basedir, _themedIconDirNames) { + QDir sizedir(QString("%1/%2x%2").arg(basedir).arg(QString::number(size))); + if (sizedir.exists()) { + // ignore context, i.e. scan all subdirs + QStringList contextdirs = sizedir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); + foreach(QString dir, contextdirs) { + QString path = QString("%1/%2/%3").arg(sizedir.absolutePath(), dir, fname); + if (QFile::exists(path)) return path; + } + } } - } - // Now check the plain dirs - foreach(QString dir, _plainIconDirNames) { - QString path = QString("%1/%2").arg(dir, name); - if(QFile::exists(path)) return path; - } - - qWarning() << "Icon not found:" << name << size; - return QString(); + // Now check the plain dirs + foreach(QString dir, _plainIconDirNames) { + QString path = QString("%1/%2").arg(dir, name); + if (QFile::exists(path)) return path; + } + + qWarning() << "Icon not found:" << name << size; + return QString(); } + // Convenience constructors -QPixmap DesktopIcon(const QString& name, int force_size) { - IconLoader *loader = IconLoader::global(); - return loader->loadIcon(name, IconLoader::Desktop, force_size); +QPixmap DesktopIcon(const QString &name, int force_size) +{ + IconLoader *loader = IconLoader::global(); + return loader->loadIcon(name, IconLoader::Desktop, force_size); } -QPixmap BarIcon(const QString& name, int force_size) { - IconLoader *loader = IconLoader::global(); - return loader->loadIcon(name, IconLoader::Toolbar, force_size); + +QPixmap BarIcon(const QString &name, int force_size) +{ + IconLoader *loader = IconLoader::global(); + return loader->loadIcon(name, IconLoader::Toolbar, force_size); } -QPixmap MainBarIcon(const QString& name, int force_size) { - IconLoader *loader = IconLoader::global(); - return loader->loadIcon(name, IconLoader::MainToolbar, force_size); + +QPixmap MainBarIcon(const QString &name, int force_size) +{ + IconLoader *loader = IconLoader::global(); + return loader->loadIcon(name, IconLoader::MainToolbar, force_size); } -QPixmap SmallIcon(const QString& name, int force_size) { - IconLoader *loader = IconLoader::global(); - return loader->loadIcon(name, IconLoader::Small, force_size); + +QPixmap SmallIcon(const QString &name, int force_size) +{ + IconLoader *loader = IconLoader::global(); + return loader->loadIcon(name, IconLoader::Small, force_size); } + #endif diff --git a/src/uisupport/iconloader.h b/src/uisupport/iconloader.h index 509eb2dc..6ff0a633 100644 --- a/src/uisupport/iconloader.h +++ b/src/uisupport/iconloader.h @@ -49,57 +49,59 @@ * * We don't search for size/context dirs in /pics, i.e. for a given $name, we expect pics/$name.png. */ -class IconLoader : public QObject { - Q_OBJECT +class IconLoader : public QObject +{ + Q_OBJECT public: - enum Group { - NoGroup = -1, ///< No group - Desktop = 0, ///< Desktop icons - Toolbar, ///< Toolbar icons - MainToolbar, ///< Main toolbar icons - Small, ///< Small icons, e.g. for buttons - Panel, ///< Panel icons - Dialog, ///< Icons for use in dialog title etc. - LastGroup - }; - - /// Standard icon sizes - enum StdSizes { - SizeSmall=16, ///< Small icons for menu entries - SizeSmallMedium=22, ///< Slightly larger small icons for toolbars, panels, etc - SizeMedium=32, ///< Medium-sized icons for the desktop - SizeLarge=48, ///< Large icons for the panel - SizeHuge=64, ///< Huge icons for iconviews - SizeEnormous=128 ///< Enormous icons for iconviews - }; - - explicit IconLoader(QObject *parent = 0); - ~IconLoader(); - - static IconLoader *global(); - - /// Load a pixmap for the given name and group - QPixmap loadIcon(const QString& name, IconLoader::Group group, int size = 0); - - inline QString theme() const; - void setTheme(const QString &name); + enum Group { + NoGroup = -1, ///< No group + Desktop = 0, ///< Desktop icons + Toolbar, ///< Toolbar icons + MainToolbar, ///< Main toolbar icons + Small, ///< Small icons, e.g. for buttons + Panel, ///< Panel icons + Dialog, ///< Icons for use in dialog title etc. + LastGroup + }; + + /// Standard icon sizes + enum StdSizes { + SizeSmall = 16, ///< Small icons for menu entries + SizeSmallMedium = 22, ///< Slightly larger small icons for toolbars, panels, etc + SizeMedium = 32, ///< Medium-sized icons for the desktop + SizeLarge = 48, ///< Large icons for the panel + SizeHuge = 64, ///< Huge icons for iconviews + SizeEnormous = 128 ///< Enormous icons for iconviews + }; + + explicit IconLoader(QObject *parent = 0); + ~IconLoader(); + + static IconLoader *global(); + + /// Load a pixmap for the given name and group + QPixmap loadIcon(const QString &name, IconLoader::Group group, int size = 0); + + inline QString theme() const; + void setTheme(const QString &name); private: - QString findIconPath(const QString &name, int size); + QString findIconPath(const QString &name, int size); - static IconLoader _iconLoader; - QString _theme; - QStringList _themedIconDirNames; - QStringList _plainIconDirNames; - static int _groupSize[]; + static IconLoader _iconLoader; + QString _theme; + QStringList _themedIconDirNames; + QStringList _plainIconDirNames; + static int _groupSize[]; }; + // convenience -QPixmap DesktopIcon(const QString& name, int size = 0); -QPixmap BarIcon(const QString& name, int size = 0); -QPixmap MainBarIcon(const QString& name, int size = 0); -QPixmap SmallIcon(const QString& name, int size = 0); +QPixmap DesktopIcon(const QString &name, int size = 0); +QPixmap BarIcon(const QString &name, int size = 0); +QPixmap MainBarIcon(const QString &name, int size = 0); +QPixmap SmallIcon(const QString &name, int size = 0); //QPixmap SmallMediumIcon(const QString &name, int size = 0); // not part of KIconLoader QString IconLoader::theme() const { return _theme; } @@ -107,7 +109,11 @@ QString IconLoader::theme() const { return _theme; } #else /* HAVE_KDE */ #include -class IconLoader : public KIconLoader { Q_OBJECT }; +class IconLoader : public KIconLoader +{ + Q_OBJECT +}; + #endif /* HAVE_KDE */ diff --git a/src/uisupport/kcmdlinewrapper.cpp b/src/uisupport/kcmdlinewrapper.cpp index 62f39805..4b943945 100644 --- a/src/uisupport/kcmdlinewrapper.cpp +++ b/src/uisupport/kcmdlinewrapper.cpp @@ -21,33 +21,43 @@ #include -KCmdLineWrapper::KCmdLineWrapper() { - +KCmdLineWrapper::KCmdLineWrapper() +{ } -void KCmdLineWrapper::addArgument(const QString &longName, const CliParserArg &arg) { - if(arg.shortName != 0) { - _cmdLineOptions.add(QByteArray().append(arg.shortName)); - } - _cmdLineOptions.add(longName.toUtf8(), ki18n(arg.help.toUtf8()), arg.def.toUtf8()); + +void KCmdLineWrapper::addArgument(const QString &longName, const CliParserArg &arg) +{ + if (arg.shortName != 0) { + _cmdLineOptions.add(QByteArray().append(arg.shortName)); + } + _cmdLineOptions.add(longName.toUtf8(), ki18n(arg.help.toUtf8()), arg.def.toUtf8()); } -bool KCmdLineWrapper::init(const QStringList &) { - KCmdLineArgs::addCmdLineOptions(_cmdLineOptions); - return true; + +bool KCmdLineWrapper::init(const QStringList &) +{ + KCmdLineArgs::addCmdLineOptions(_cmdLineOptions); + return true; } -QString KCmdLineWrapper::value(const QString &longName) { - return KCmdLineArgs::parsedArgs()->getOption(longName.toUtf8()); + +QString KCmdLineWrapper::value(const QString &longName) +{ + return KCmdLineArgs::parsedArgs()->getOption(longName.toUtf8()); } -bool KCmdLineWrapper::isSet(const QString &longName) { - // KCmdLineArgs handles --nooption like NOT --option - if(longName.startsWith("no")) - return !KCmdLineArgs::parsedArgs()->isSet(longName.mid(2).toUtf8()); - return KCmdLineArgs::parsedArgs()->isSet(longName.toUtf8()); + +bool KCmdLineWrapper::isSet(const QString &longName) +{ + // KCmdLineArgs handles --nooption like NOT --option + if (longName.startsWith("no")) + return !KCmdLineArgs::parsedArgs()->isSet(longName.mid(2).toUtf8()); + return KCmdLineArgs::parsedArgs()->isSet(longName.toUtf8()); } -void KCmdLineWrapper::usage() { - KCmdLineArgs::usage(); + +void KCmdLineWrapper::usage() +{ + KCmdLineArgs::usage(); } diff --git a/src/uisupport/kcmdlinewrapper.h b/src/uisupport/kcmdlinewrapper.h index 4ac1d21e..16cce140 100644 --- a/src/uisupport/kcmdlinewrapper.h +++ b/src/uisupport/kcmdlinewrapper.h @@ -26,20 +26,22 @@ #include //! Wrapper for KCmdLineOptions -class KCmdLineWrapper : public AbstractCliParser { +class KCmdLineWrapper : public AbstractCliParser +{ public: - KCmdLineWrapper(); + KCmdLineWrapper(); - bool init(const QStringList &arguments = QStringList()); + bool init(const QStringList &arguments = QStringList()); - QString value(const QString &longName); - bool isSet(const QString &longName); - void usage(); + QString value(const QString &longName); + bool isSet(const QString &longName); + void usage(); private: - void addArgument(const QString &longName, const CliParserArg &arg); + void addArgument(const QString &longName, const CliParserArg &arg); - KCmdLineOptions _cmdLineOptions; + KCmdLineOptions _cmdLineOptions; }; + #endif diff --git a/src/uisupport/multilineedit.cpp b/src/uisupport/multilineedit.cpp index 3ee98d93..a4d95b0d 100644 --- a/src/uisupport/multilineedit.cpp +++ b/src/uisupport/multilineedit.cpp @@ -32,7 +32,7 @@ const int leftMargin = 3; MultiLineEdit::MultiLineEdit(QWidget *parent) - : MultiLineEditParent(parent), + : MultiLineEditParent(parent), _idx(0), _mode(SingleLine), _singleLine(true), @@ -44,678 +44,741 @@ MultiLineEdit::MultiLineEdit(QWidget *parent) _lastDocumentHeight(-1) { #if QT_VERSION >= 0x040500 - document()->setDocumentMargin(0); // new in Qt 4.5 and we really don't want it here + document()->setDocumentMargin(0); // new in Qt 4.5 and we really don't want it here #endif - setAcceptRichText(false); + setAcceptRichText(false); #ifdef HAVE_KDE - enableFindReplace(false); + enableFindReplace(false); #endif - setMode(SingleLine); - setWordWrapEnabled(false); - reset(); - - connect(this, SIGNAL(textChanged()), this, SLOT(on_textChanged())); - - _mircColorMap["00"] = "#ffffff"; - _mircColorMap["01"] = "#000000"; - _mircColorMap["02"] = "#000080"; - _mircColorMap["03"] = "#008000"; - _mircColorMap["04"] = "#ff0000"; - _mircColorMap["05"] = "#800000"; - _mircColorMap["06"] = "#800080"; - _mircColorMap["07"] = "#ffa500"; - _mircColorMap["08"] = "#ffff00"; - _mircColorMap["09"] = "#00ff00"; - _mircColorMap["10"] = "#008080"; - _mircColorMap["11"] = "#00ffff"; - _mircColorMap["12"] = "#4169e1"; - _mircColorMap["13"] = "#ff00ff"; - _mircColorMap["14"] = "#808080"; - _mircColorMap["15"] = "#c0c0c0"; + setMode(SingleLine); + setWordWrapEnabled(false); + reset(); + connect(this, SIGNAL(textChanged()), this, SLOT(on_textChanged())); + + _mircColorMap["00"] = "#ffffff"; + _mircColorMap["01"] = "#000000"; + _mircColorMap["02"] = "#000080"; + _mircColorMap["03"] = "#008000"; + _mircColorMap["04"] = "#ff0000"; + _mircColorMap["05"] = "#800000"; + _mircColorMap["06"] = "#800080"; + _mircColorMap["07"] = "#ffa500"; + _mircColorMap["08"] = "#ffff00"; + _mircColorMap["09"] = "#00ff00"; + _mircColorMap["10"] = "#008080"; + _mircColorMap["11"] = "#00ffff"; + _mircColorMap["12"] = "#4169e1"; + _mircColorMap["13"] = "#ff00ff"; + _mircColorMap["14"] = "#808080"; + _mircColorMap["15"] = "#c0c0c0"; } -MultiLineEdit::~MultiLineEdit() { + +MultiLineEdit::~MultiLineEdit() +{ } -void MultiLineEdit::setCustomFont(const QFont &font) { - setFont(font); - updateSizeHint(); + +void MultiLineEdit::setCustomFont(const QFont &font) +{ + setFont(font); + updateSizeHint(); } -void MultiLineEdit::setMode(Mode mode) { - if(mode == _mode) - return; - _mode = mode; +void MultiLineEdit::setMode(Mode mode) +{ + if (mode == _mode) + return; + + _mode = mode; } -void MultiLineEdit::setMinHeight(int lines) { - if(lines == _minHeight) - return; - _minHeight = lines; - updateSizeHint(); +void MultiLineEdit::setMinHeight(int lines) +{ + if (lines == _minHeight) + return; + + _minHeight = lines; + updateSizeHint(); } -void MultiLineEdit::setMaxHeight(int lines) { - if(lines == _maxHeight) - return; - _maxHeight = lines; - updateSizeHint(); +void MultiLineEdit::setMaxHeight(int lines) +{ + if (lines == _maxHeight) + return; + + _maxHeight = lines; + updateSizeHint(); } -void MultiLineEdit::setScrollBarsEnabled(bool enable) { - if(_scrollBarsEnabled == enable) - return; - _scrollBarsEnabled = enable; - updateScrollBars(); +void MultiLineEdit::setScrollBarsEnabled(bool enable) +{ + if (_scrollBarsEnabled == enable) + return; + + _scrollBarsEnabled = enable; + updateScrollBars(); } -void MultiLineEdit::updateScrollBars() { - QFontMetrics fm(font()); - int _maxPixelHeight = fm.lineSpacing() * _maxHeight; - if(_scrollBarsEnabled && document()->size().height() > _maxPixelHeight) - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - else - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - - if(!_scrollBarsEnabled || isSingleLine()) - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - else - setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + +void MultiLineEdit::updateScrollBars() +{ + QFontMetrics fm(font()); + int _maxPixelHeight = fm.lineSpacing() * _maxHeight; + if (_scrollBarsEnabled && document()->size().height() > _maxPixelHeight) + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + else + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + if (!_scrollBarsEnabled || isSingleLine()) + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + else + setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); } -void MultiLineEdit::resizeEvent(QResizeEvent *event) { - QTextEdit::resizeEvent(event); - updateSizeHint(); - updateScrollBars(); + +void MultiLineEdit::resizeEvent(QResizeEvent *event) +{ + QTextEdit::resizeEvent(event); + updateSizeHint(); + updateScrollBars(); } -void MultiLineEdit::updateSizeHint() { - QFontMetrics fm(font()); - int minPixelHeight = fm.lineSpacing() * _minHeight; - int maxPixelHeight = fm.lineSpacing() * _maxHeight; - int scrollBarHeight = horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0; - - // use the style to determine a decent size - int h = qMin(qMax((int)document()->size().height() + scrollBarHeight, minPixelHeight), maxPixelHeight) + 2 * frameWidth(); - QStyleOptionFrameV2 opt; - opt.initFrom(this); - opt.rect = QRect(0, 0, 100, h); - opt.lineWidth = lineWidth(); - opt.midLineWidth = midLineWidth(); - opt.state |= QStyle::State_Sunken; - QSize s = style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(100, h).expandedTo(QApplication::globalStrut()), this); - if(s != _sizeHint) { - _sizeHint = s; - updateGeometry(); - } + +void MultiLineEdit::updateSizeHint() +{ + QFontMetrics fm(font()); + int minPixelHeight = fm.lineSpacing() * _minHeight; + int maxPixelHeight = fm.lineSpacing() * _maxHeight; + int scrollBarHeight = horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0; + + // use the style to determine a decent size + int h = qMin(qMax((int)document()->size().height() + scrollBarHeight, minPixelHeight), maxPixelHeight) + 2 * frameWidth(); + QStyleOptionFrameV2 opt; + opt.initFrom(this); + opt.rect = QRect(0, 0, 100, h); + opt.lineWidth = lineWidth(); + opt.midLineWidth = midLineWidth(); + opt.state |= QStyle::State_Sunken; + QSize s = style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(100, h).expandedTo(QApplication::globalStrut()), this); + if (s != _sizeHint) { + _sizeHint = s; + updateGeometry(); + } } -QSize MultiLineEdit::sizeHint() const { - if(!_sizeHint.isValid()) { - MultiLineEdit *that = const_cast(this); - that->updateSizeHint(); - } - return _sizeHint; + +QSize MultiLineEdit::sizeHint() const +{ + if (!_sizeHint.isValid()) { + MultiLineEdit *that = const_cast(this); + that->updateSizeHint(); + } + return _sizeHint; } -QSize MultiLineEdit::minimumSizeHint() const { - return sizeHint(); + +QSize MultiLineEdit::minimumSizeHint() const +{ + return sizeHint(); } -void MultiLineEdit::setEmacsMode(bool enable) { - _emacsMode = enable; + +void MultiLineEdit::setEmacsMode(bool enable) +{ + _emacsMode = enable; } -void MultiLineEdit::setSpellCheckEnabled(bool enable) { + +void MultiLineEdit::setSpellCheckEnabled(bool enable) +{ #ifdef HAVE_KDE - setCheckSpellingEnabled(enable); + setCheckSpellingEnabled(enable); #else - Q_UNUSED(enable) + Q_UNUSED(enable) #endif } -void MultiLineEdit::setWordWrapEnabled(bool enable) { - setLineWrapMode(enable? WidgetWidth : NoWrap); - updateSizeHint(); + +void MultiLineEdit::setWordWrapEnabled(bool enable) +{ + setLineWrapMode(enable ? WidgetWidth : NoWrap); + updateSizeHint(); } -void MultiLineEdit::setPasteProtectionEnabled(bool enable, QWidget *) { - _pasteProtectionEnabled = enable; + +void MultiLineEdit::setPasteProtectionEnabled(bool enable, QWidget *) +{ + _pasteProtectionEnabled = enable; } -void MultiLineEdit::historyMoveBack() { - addToHistory(convertRichtextToMircCodes(), true); - if(_idx > 0) { - _idx--; - showHistoryEntry(); - } +void MultiLineEdit::historyMoveBack() +{ + addToHistory(convertRichtextToMircCodes(), true); + + if (_idx > 0) { + _idx--; + showHistoryEntry(); + } } -void MultiLineEdit::historyMoveForward() { - addToHistory(convertRichtextToMircCodes(), true); - if(_idx < _history.count()) { - _idx++; - if(_idx < _history.count() || _tempHistory.contains(_idx)) // tempHistory might have an entry for idx == history.count() + 1 - showHistoryEntry(); - else - reset(); // equals clear() in this case - } else { - addToHistory(convertRichtextToMircCodes()); - reset(); - } +void MultiLineEdit::historyMoveForward() +{ + addToHistory(convertRichtextToMircCodes(), true); + + if (_idx < _history.count()) { + _idx++; + if (_idx < _history.count() || _tempHistory.contains(_idx)) // tempHistory might have an entry for idx == history.count() + 1 + showHistoryEntry(); + else + reset(); // equals clear() in this case + } + else { + addToHistory(convertRichtextToMircCodes()); + reset(); + } } -bool MultiLineEdit::addToHistory(const QString &text, bool temporary) { - if(text.isEmpty()) - return false; - Q_ASSERT(0 <= _idx && _idx <= _history.count()); +bool MultiLineEdit::addToHistory(const QString &text, bool temporary) +{ + if (text.isEmpty()) + return false; - if(temporary) { - // if an entry of the history is changed, we remember it and show it again at this - // position until a line was actually sent - // sent lines get appended to the history - if(_history.isEmpty() || text != _history[_idx - (int)(_idx == _history.count())]) { - _tempHistory[_idx] = text; - return true; + Q_ASSERT(0 <= _idx && _idx <= _history.count()); + + if (temporary) { + // if an entry of the history is changed, we remember it and show it again at this + // position until a line was actually sent + // sent lines get appended to the history + if (_history.isEmpty() || text != _history[_idx - (int)(_idx == _history.count())]) { + _tempHistory[_idx] = text; + return true; + } } - } else { - if(_history.isEmpty() || text != _history.last()) { - _history << text; - _tempHistory.clear(); - return true; + else { + if (_history.isEmpty() || text != _history.last()) { + _history << text; + _tempHistory.clear(); + return true; + } } - } - return false; + return false; } -bool MultiLineEdit::event(QEvent *e) { - // We need to make sure that global shortcuts aren't eaten - if(e->type() == QEvent::ShortcutOverride) { - QKeyEvent* event = static_cast(e); - QKeySequence key = QKeySequence(event->key() | event->modifiers()); - foreach(QAction *action, GraphicalUi::actionCollection()->actions()) { - if(action->shortcuts().contains(key)) { - e->ignore(); - return false; - } + +bool MultiLineEdit::event(QEvent *e) +{ + // We need to make sure that global shortcuts aren't eaten + if (e->type() == QEvent::ShortcutOverride) { + QKeyEvent *event = static_cast(e); + QKeySequence key = QKeySequence(event->key() | event->modifiers()); + foreach(QAction *action, GraphicalUi::actionCollection()->actions()) { + if (action->shortcuts().contains(key)) { + e->ignore(); + return false; + } + } } - } - return MultiLineEditParent::event(e); + return MultiLineEditParent::event(e); } -void MultiLineEdit::keyPressEvent(QKeyEvent *event) { - // Workaround the fact that Qt < 4.5 doesn't know InsertLineSeparator yet + +void MultiLineEdit::keyPressEvent(QKeyEvent *event) +{ + // Workaround the fact that Qt < 4.5 doesn't know InsertLineSeparator yet #if QT_VERSION >= 0x040500 - if(event == QKeySequence::InsertLineSeparator) { + if (event == QKeySequence::InsertLineSeparator) { #else # ifdef Q_WS_MAC - if((event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) && event->modifiers() & Qt::META) { + if ((event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) && event->modifiers() & Qt::META) { # else - if((event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) && event->modifiers() & Qt::SHIFT) { + if ((event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) && event->modifiers() & Qt::SHIFT) { # endif #endif - if(_mode == SingleLine) { - event->accept(); - on_returnPressed(); - return; - } - MultiLineEditParent::keyPressEvent(event); - return; - } - - switch(event->key()) { - case Qt::Key_Up: - if(event->modifiers() & Qt::ShiftModifier) - break; - { - event->accept(); - if(!(event->modifiers() & Qt::ControlModifier)) { - int pos = textCursor().position(); - moveCursor(QTextCursor::Up); - if(pos == textCursor().position()) // already on top line -> history - historyMoveBack(); - } else - historyMoveBack(); - return; - } - - case Qt::Key_Down: - if(event->modifiers() & Qt::ShiftModifier) - break; - { - event->accept(); - if(!(event->modifiers() & Qt::ControlModifier)) { - int pos = textCursor().position(); - moveCursor(QTextCursor::Down); - if(pos == textCursor().position()) // already on bottom line -> history - historyMoveForward(); - } else - historyMoveForward(); - return; - } - - case Qt::Key_Return: - case Qt::Key_Enter: - case Qt::Key_Select: - event->accept(); - on_returnPressed(); - return; - - // We don't want to have the tab key react even if no completer is installed - case Qt::Key_Tab: - event->accept(); - return; - - default: - ; - } - - if(_emacsMode) { - if(event->modifiers() & Qt::ControlModifier) { - switch(event->key()) { - // move - case Qt::Key_A: - moveCursor(QTextCursor::StartOfLine); - return; - case Qt::Key_E: - moveCursor(QTextCursor::EndOfLine); - return; - case Qt::Key_F: - moveCursor(QTextCursor::Right); - return; - case Qt::Key_B: - moveCursor(QTextCursor::Left); + if (_mode == SingleLine) { + event->accept(); + on_returnPressed(); + return; + } + MultiLineEditParent::keyPressEvent(event); return; + } - // modify - case Qt::Key_Y: - paste(); - return; - case Qt::Key_K: - moveCursor(QTextCursor::EndOfLine, QTextCursor::KeepAnchor); - cut(); - return; + switch (event->key()) { + case Qt::Key_Up: + if (event->modifiers() & Qt::ShiftModifier) + break; + { + event->accept(); + if (!(event->modifiers() & Qt::ControlModifier)) { + int pos = textCursor().position(); + moveCursor(QTextCursor::Up); + if (pos == textCursor().position()) // already on top line -> history + historyMoveBack(); + } + else + historyMoveBack(); + return; + } - default: - break; - } - } - else if(event->modifiers() & Qt::MetaModifier || - event->modifiers() & Qt::AltModifier) - { - switch(event->key()) { - case Qt::Key_Right: - moveCursor(QTextCursor::WordRight); - return; - case Qt::Key_Left: - moveCursor(QTextCursor::WordLeft); - return; - case Qt::Key_F: - moveCursor(QTextCursor::WordRight); - return; - case Qt::Key_B: - moveCursor(QTextCursor::WordLeft); - return; - case Qt::Key_Less: - moveCursor(QTextCursor::Start); - return; - case Qt::Key_Greater: - moveCursor(QTextCursor::End); - return; + case Qt::Key_Down: + if (event->modifiers() & Qt::ShiftModifier) + break; + { + event->accept(); + if (!(event->modifiers() & Qt::ControlModifier)) { + int pos = textCursor().position(); + moveCursor(QTextCursor::Down); + if (pos == textCursor().position()) // already on bottom line -> history + historyMoveForward(); + } + else + historyMoveForward(); + return; + } - // modify - case Qt::Key_D: - moveCursor(QTextCursor::WordRight, QTextCursor::KeepAnchor); - cut(); + case Qt::Key_Return: + case Qt::Key_Enter: + case Qt::Key_Select: + event->accept(); + on_returnPressed(); return; - case Qt::Key_U: // uppercase word - moveCursor(QTextCursor::WordRight, QTextCursor::KeepAnchor); - textCursor().insertText(textCursor().selectedText().toUpper()); + // We don't want to have the tab key react even if no completer is installed + case Qt::Key_Tab: + event->accept(); return; - case Qt::Key_L: // lowercase word - moveCursor(QTextCursor::WordRight, QTextCursor::KeepAnchor); - textCursor().insertText(textCursor().selectedText().toLower()); - return; + default: + ; + } - case Qt::Key_C: { // capitalize word - moveCursor(QTextCursor::WordRight, QTextCursor::KeepAnchor); - QString const text = textCursor().selectedText(); - textCursor().insertText(text.left(1).toUpper() + text.mid(1).toLower()); - return; - } - - case Qt::Key_T: { // transpose words - moveCursor(QTextCursor::StartOfWord); - moveCursor(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); - QString const word1 = textCursor().selectedText(); - textCursor().clearSelection(); - moveCursor(QTextCursor::WordRight); - moveCursor(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); - QString const word2 = textCursor().selectedText(); - if(!word2.isEmpty() && !word1.isEmpty()) { - textCursor().insertText(word1); - moveCursor(QTextCursor::WordLeft); - moveCursor(QTextCursor::WordLeft); - moveCursor(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); - textCursor().insertText(word2); - moveCursor(QTextCursor::WordRight); - moveCursor(QTextCursor::EndOfWord); + if (_emacsMode) { + if (event->modifiers() & Qt::ControlModifier) { + switch (event->key()) { + // move + case Qt::Key_A: + moveCursor(QTextCursor::StartOfLine); + return; + case Qt::Key_E: + moveCursor(QTextCursor::EndOfLine); + return; + case Qt::Key_F: + moveCursor(QTextCursor::Right); + return; + case Qt::Key_B: + moveCursor(QTextCursor::Left); + return; + + // modify + case Qt::Key_Y: + paste(); + return; + case Qt::Key_K: + moveCursor(QTextCursor::EndOfLine, QTextCursor::KeepAnchor); + cut(); + return; + + default: + break; + } + } + else if (event->modifiers() & Qt::MetaModifier || + event->modifiers() & Qt::AltModifier) + { + switch (event->key()) { + case Qt::Key_Right: + moveCursor(QTextCursor::WordRight); + return; + case Qt::Key_Left: + moveCursor(QTextCursor::WordLeft); + return; + case Qt::Key_F: + moveCursor(QTextCursor::WordRight); + return; + case Qt::Key_B: + moveCursor(QTextCursor::WordLeft); + return; + case Qt::Key_Less: + moveCursor(QTextCursor::Start); + return; + case Qt::Key_Greater: + moveCursor(QTextCursor::End); + return; + + // modify + case Qt::Key_D: + moveCursor(QTextCursor::WordRight, QTextCursor::KeepAnchor); + cut(); + return; + + case Qt::Key_U: // uppercase word + moveCursor(QTextCursor::WordRight, QTextCursor::KeepAnchor); + textCursor().insertText(textCursor().selectedText().toUpper()); + return; + + case Qt::Key_L: // lowercase word + moveCursor(QTextCursor::WordRight, QTextCursor::KeepAnchor); + textCursor().insertText(textCursor().selectedText().toLower()); + return; + + case Qt::Key_C: + { // capitalize word + moveCursor(QTextCursor::WordRight, QTextCursor::KeepAnchor); + QString const text = textCursor().selectedText(); + textCursor().insertText(text.left(1).toUpper() + text.mid(1).toLower()); + return; + } + + case Qt::Key_T: + { // transpose words + moveCursor(QTextCursor::StartOfWord); + moveCursor(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); + QString const word1 = textCursor().selectedText(); + textCursor().clearSelection(); + moveCursor(QTextCursor::WordRight); + moveCursor(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); + QString const word2 = textCursor().selectedText(); + if (!word2.isEmpty() && !word1.isEmpty()) { + textCursor().insertText(word1); + moveCursor(QTextCursor::WordLeft); + moveCursor(QTextCursor::WordLeft); + moveCursor(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); + textCursor().insertText(word2); + moveCursor(QTextCursor::WordRight); + moveCursor(QTextCursor::EndOfWord); + } + return; + } + + default: + break; + } } - return; - } - - default: - break; - } } - } #ifdef HAVE_KDE - KTextEdit::keyPressEvent(event); + KTextEdit::keyPressEvent(event); #else - QTextEdit::keyPressEvent(event); + QTextEdit::keyPressEvent(event); #endif } -QString MultiLineEdit::convertRichtextToMircCodes() { - bool underline, bold, italic, color; - QString mircText, mircFgColor, mircBgColor; - QTextCursor cursor = textCursor(); - QTextCursor peekcursor = textCursor(); - cursor.movePosition(QTextCursor::Start); - underline = bold = italic = color = false; - - while (cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor)) { +QString MultiLineEdit::convertRichtextToMircCodes() +{ + bool underline, bold, italic, color; + QString mircText, mircFgColor, mircBgColor; + QTextCursor cursor = textCursor(); + QTextCursor peekcursor = textCursor(); + cursor.movePosition(QTextCursor::Start); + + underline = bold = italic = color = false; + + while (cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor)) { + if (cursor.selectedText() == QString(QChar(QChar::LineSeparator)) + || cursor.selectedText() == QString(QChar(QChar::ParagraphSeparator))) { + if (color) { + color = false; + mircText.append('\x03'); + } + if (underline) { + underline = false; + mircText.append('\x1f'); + } + if (italic) { + italic = false; + mircText.append('\x1d'); + } + if (bold) { + bold = false; + mircText.append('\x02'); + } + mircText.append('\n'); + } + else { + if (!bold && cursor.charFormat().font().bold()) { + bold = true; + mircText.append('\x02'); + } + if (!italic && cursor.charFormat().fontItalic()) { + italic = true; + mircText.append('\x1d'); + } + if (!underline && cursor.charFormat().fontUnderline()) { + underline = true; + mircText.append('\x1f'); + } + if (!color && (cursor.charFormat().foreground().isOpaque() || cursor.charFormat().background().isOpaque())) { + color = true; + mircText.append('\x03'); + mircFgColor = _mircColorMap.key(cursor.charFormat().foreground().color().name()); + mircBgColor = _mircColorMap.key(cursor.charFormat().background().color().name()); + + if (mircFgColor.isEmpty()) { + mircFgColor = "01"; //use black if the current foreground color can't be converted + } + + mircText.append(mircFgColor); + if (cursor.charFormat().background().isOpaque()) + mircText.append("," + mircBgColor); + } + + mircText.append(cursor.selectedText()); + + peekcursor.setPosition(cursor.position()); + peekcursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); + + if (mircCodesChanged(cursor, peekcursor)) { + if (color) { + color = false; + mircText.append('\x03'); + } + if (underline) { + underline = false; + mircText.append('\x1f'); + } + if (italic) { + italic = false; + mircText.append('\x1d'); + } + if (bold) { + bold = false; + mircText.append('\x02'); + } + } + } - if (cursor.selectedText() == QString(QChar(QChar::LineSeparator)) - || cursor.selectedText() == QString(QChar(QChar::ParagraphSeparator))) { - if (color) { + cursor.clearSelection(); + } + if (color) { color = false; mircText.append('\x03'); - } - if (underline) { + } + if (underline) { underline = false; mircText.append('\x1f'); - } - if (italic) { + } + if (italic) { italic = false; mircText.append('\x1d'); - } - if (bold) { + } + if (bold) { bold = false; mircText.append('\x02'); - } - mircText.append('\n'); } - else { - if (!bold && cursor.charFormat().font().bold()) { - bold = true; - mircText.append('\x02'); - } - if (!italic && cursor.charFormat().fontItalic()) { - italic = true; - mircText.append('\x1d'); - } - if (!underline && cursor.charFormat().fontUnderline()) { - underline = true; - mircText.append('\x1f'); - } - if (!color && (cursor.charFormat().foreground().isOpaque() || cursor.charFormat().background().isOpaque())) { - color = true; - mircText.append('\x03'); - mircFgColor = _mircColorMap.key(cursor.charFormat().foreground().color().name()); - mircBgColor = _mircColorMap.key(cursor.charFormat().background().color().name()); - - if (mircFgColor.isEmpty()) { - mircFgColor = "01"; //use black if the current foreground color can't be converted - } - - mircText.append(mircFgColor); - if (cursor.charFormat().background().isOpaque()) - mircText.append("," + mircBgColor); - } - mircText.append(cursor.selectedText()); - - peekcursor.setPosition(cursor.position()); - peekcursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); + return mircText; +} - if (mircCodesChanged(cursor, peekcursor)) { - if (color) { - color = false; - mircText.append('\x03'); - } - if (underline) { - underline = false; - mircText.append('\x1f'); - } - if (italic) { - italic = false; - mircText.append('\x1d'); - } - if (bold) { - bold = false; - mircText.append('\x02'); - } - } - } - cursor.clearSelection(); - } - if (color) { - color = false; - mircText.append('\x03'); - } - if (underline) { - underline = false; - mircText.append('\x1f'); - } - if (italic) { - italic = false; - mircText.append('\x1d'); - } - if (bold) { - bold = false; - mircText.append('\x02'); - } - - return mircText; +bool MultiLineEdit::mircCodesChanged(QTextCursor &cursor, QTextCursor &peekcursor) +{ + bool changed = false; + if (cursor.charFormat().font().bold() != peekcursor.charFormat().font().bold()) + changed = true; + if (cursor.charFormat().fontItalic() != peekcursor.charFormat().fontItalic()) + changed = true; + if (cursor.charFormat().fontUnderline() != peekcursor.charFormat().fontUnderline()) + changed = true; + if (cursor.charFormat().foreground().color() != peekcursor.charFormat().foreground().color()) + changed = true; + if (cursor.charFormat().background().color() != peekcursor.charFormat().background().color()) + changed = true; + return changed; } -bool MultiLineEdit::mircCodesChanged(QTextCursor &cursor, QTextCursor &peekcursor) { - bool changed = false; - if (cursor.charFormat().font().bold() != peekcursor.charFormat().font().bold()) - changed = true; - if (cursor.charFormat().fontItalic() != peekcursor.charFormat().fontItalic()) - changed = true; - if (cursor.charFormat().fontUnderline() != peekcursor.charFormat().fontUnderline()) - changed = true; - if (cursor.charFormat().foreground().color() != peekcursor.charFormat().foreground().color()) - changed = true; - if (cursor.charFormat().background().color() != peekcursor.charFormat().background().color()) - changed = true; - return changed; -} -QString MultiLineEdit::convertMircCodesToHtml(const QString &text) { - QStringList words; - QRegExp mircCode = QRegExp("(|||)", Qt::CaseSensitive); +QString MultiLineEdit::convertMircCodesToHtml(const QString &text) +{ + QStringList words; + QRegExp mircCode = QRegExp("(|||)", Qt::CaseSensitive); - int posLeft = 0; - int posRight = 0; + int posLeft = 0; + int posRight = 0; - for(;;) { - posRight = mircCode.indexIn(text, posLeft); + for (;;) { + posRight = mircCode.indexIn(text, posLeft); - if(posRight < 0) { - words << text.mid(posLeft); - break; // no more mirc color codes - } + if (posRight < 0) { + words << text.mid(posLeft); + break; // no more mirc color codes + } + + if (posLeft < posRight) { + words << text.mid(posLeft, posRight - posLeft); + posLeft = posRight; + } - if (posLeft < posRight) { - words << text.mid(posLeft, posRight - posLeft); - posLeft = posRight; + posRight = text.indexOf(mircCode.cap(), posRight + 1); + words << text.mid(posLeft, posRight + 1 - posLeft); + posLeft = posRight + 1; } - posRight = text.indexOf(mircCode.cap(), posRight + 1); - words << text.mid(posLeft, posRight + 1 - posLeft); - posLeft = posRight + 1; - } - - for (int i = 0; i < words.count(); i++) { - QString style; - if (words[i].contains('\x02')) { - style.append(" font-weight:600;"); - words[i].replace('\x02',""); - } - if (words[i].contains('\x1d')) { - style.append(" font-style:italic;"); - words[i].replace('\x1d',""); - } - if (words[i].contains('\x1f')) { - style.append(" text-decoration: underline;"); - words[i].replace('\x1f',""); - } - if (words[i].contains('\x03')) { - int pos = words[i].indexOf('\x03'); - int len = 3; - QString fg = words[i].mid(pos + 1,2); - QString bg; - if (words[i][pos+3] == ',') - bg = words[i].mid(pos+4,2); - - style.append(" color:"); - style.append(_mircColorMap[fg]); - style.append(";"); - - if (!bg.isEmpty()) { - style.append(" background-color:"); - style.append(_mircColorMap[bg]); - style.append(";"); - len = 6; + for (int i = 0; i < words.count(); i++) { + QString style; + if (words[i].contains('\x02')) { + style.append(" font-weight:600;"); + words[i].replace('\x02', ""); } - words[i].replace(pos, len, ""); - words[i].replace('\x03',""); - } - words[i].replace("&","&"); - words[i].replace("<", "<"); - words[i].replace(">", ">"); - words[i].replace("\"", """); - if (style.isEmpty()) { - words[i] = "" + words[i] + ""; - } - else { - words[i] = "" + words[i] + ""; - } - } - return words.join("").replace("\n","
"); + if (words[i].contains('\x1d')) { + style.append(" font-style:italic;"); + words[i].replace('\x1d', ""); + } + if (words[i].contains('\x1f')) { + style.append(" text-decoration: underline;"); + words[i].replace('\x1f', ""); + } + if (words[i].contains('\x03')) { + int pos = words[i].indexOf('\x03'); + int len = 3; + QString fg = words[i].mid(pos + 1, 2); + QString bg; + if (words[i][pos+3] == ',') + bg = words[i].mid(pos+4, 2); + + style.append(" color:"); + style.append(_mircColorMap[fg]); + style.append(";"); + + if (!bg.isEmpty()) { + style.append(" background-color:"); + style.append(_mircColorMap[bg]); + style.append(";"); + len = 6; + } + words[i].replace(pos, len, ""); + words[i].replace('\x03', ""); + } + words[i].replace("&", "&"); + words[i].replace("<", "<"); + words[i].replace(">", ">"); + words[i].replace("\"", """); + if (style.isEmpty()) { + words[i] = "" + words[i] + ""; + } + else { + words[i] = "" + words[i] + ""; + } + } + return words.join("").replace("\n", "
"); } -void MultiLineEdit::on_returnPressed() { - on_returnPressed(convertRichtextToMircCodes()); + +void MultiLineEdit::on_returnPressed() +{ + on_returnPressed(convertRichtextToMircCodes()); } -void MultiLineEdit::on_returnPressed(const QString & text) { - if(!text.isEmpty()) { - foreach(const QString &line, text.split('\n', QString::SkipEmptyParts)) { - if(line.isEmpty()) - continue; - addToHistory(line); - emit textEntered(line); + +void MultiLineEdit::on_returnPressed(const QString &text) +{ + if (!text.isEmpty()) { + foreach(const QString &line, text.split('\n', QString::SkipEmptyParts)) { + if (line.isEmpty()) + continue; + addToHistory(line); + emit textEntered(line); + } + reset(); + _tempHistory.clear(); + } + else { + emit noTextEntered(); } - reset(); - _tempHistory.clear(); - } else { - emit noTextEntered(); - } } -void MultiLineEdit::on_textChanged() { - QString newText = text(); - newText.replace("\r\n", "\n"); - newText.replace('\r', '\n'); - if(_mode == SingleLine) { - if(!pasteProtectionEnabled()) - newText.replace('\n', ' '); - else if(newText.contains('\n')) { - QStringList lines = newText.split('\n', QString::SkipEmptyParts); - clear(); - - if(lines.count() >= 4) { - QString msg = tr("Do you really want to paste %n line(s)?", "", lines.count()); - msg += "

"; - for(int i = 0; i < 4; i++) { - msg += Qt::escape(lines[i].left(40)); - if(lines[i].count() > 40) - msg += "..."; - msg += "
"; - } - msg += "...

"; - QMessageBox question(QMessageBox::NoIcon, tr("Paste Protection"), msg, QMessageBox::Yes|QMessageBox::No); - question.setDefaultButton(QMessageBox::No); + +void MultiLineEdit::on_textChanged() +{ + QString newText = text(); + newText.replace("\r\n", "\n"); + newText.replace('\r', '\n'); + if (_mode == SingleLine) { + if (!pasteProtectionEnabled()) + newText.replace('\n', ' '); + else if (newText.contains('\n')) { + QStringList lines = newText.split('\n', QString::SkipEmptyParts); + clear(); + + if (lines.count() >= 4) { + QString msg = tr("Do you really want to paste %n line(s)?", "", lines.count()); + msg += "

"; + for (int i = 0; i < 4; i++) { + msg += Qt::escape(lines[i].left(40)); + if (lines[i].count() > 40) + msg += "..."; + msg += "
"; + } + msg += "...

"; + QMessageBox question(QMessageBox::NoIcon, tr("Paste Protection"), msg, QMessageBox::Yes|QMessageBox::No); + question.setDefaultButton(QMessageBox::No); #ifdef Q_WS_MAC - question.setWindowFlags(question.windowFlags() | Qt::Sheet); + question.setWindowFlags(question.windowFlags() | Qt::Sheet); #endif - if(question.exec() != QMessageBox::Yes) - return; - } - - foreach(QString line, lines) { - clear(); - insert(line); - on_returnPressed(); - } + if (question.exec() != QMessageBox::Yes) + return; + } + + foreach(QString line, lines) { + clear(); + insert(line); + on_returnPressed(); + } + } } - } - _singleLine = (newText.indexOf('\n') < 0); + _singleLine = (newText.indexOf('\n') < 0); - if(document()->size().height() != _lastDocumentHeight) { - _lastDocumentHeight = document()->size().height(); - on_documentHeightChanged(_lastDocumentHeight); - } - updateSizeHint(); - ensureCursorVisible(); + if (document()->size().height() != _lastDocumentHeight) { + _lastDocumentHeight = document()->size().height(); + on_documentHeightChanged(_lastDocumentHeight); + } + updateSizeHint(); + ensureCursorVisible(); } -void MultiLineEdit::on_documentHeightChanged(qreal) { - updateScrollBars(); + +void MultiLineEdit::on_documentHeightChanged(qreal) +{ + updateScrollBars(); } -void MultiLineEdit::reset() { - // every time the MultiLineEdit is cleared we also reset history index - _idx = _history.count(); - clear(); - QTextBlockFormat format = textCursor().blockFormat(); - format.setLeftMargin(leftMargin); // we want a little space between the frame and the contents - textCursor().setBlockFormat(format); - updateScrollBars(); + +void MultiLineEdit::reset() +{ + // every time the MultiLineEdit is cleared we also reset history index + _idx = _history.count(); + clear(); + QTextBlockFormat format = textCursor().blockFormat(); + format.setLeftMargin(leftMargin); // we want a little space between the frame and the contents + textCursor().setBlockFormat(format); + updateScrollBars(); } -void MultiLineEdit::showHistoryEntry() { - // if the user changed the history, display the changed line - setHtml(convertMircCodesToHtml(_tempHistory.contains(_idx) ? _tempHistory[_idx] : _history[_idx])); - QTextCursor cursor = textCursor(); - QTextBlockFormat format = cursor.blockFormat(); - format.setLeftMargin(leftMargin); // we want a little space between the frame and the contents - cursor.setBlockFormat(format); - cursor.movePosition(QTextCursor::End); - setTextCursor(cursor); - updateScrollBars(); + +void MultiLineEdit::showHistoryEntry() +{ + // if the user changed the history, display the changed line + setHtml(convertMircCodesToHtml(_tempHistory.contains(_idx) ? _tempHistory[_idx] : _history[_idx])); + QTextCursor cursor = textCursor(); + QTextBlockFormat format = cursor.blockFormat(); + format.setLeftMargin(leftMargin); // we want a little space between the frame and the contents + cursor.setBlockFormat(format); + cursor.movePosition(QTextCursor::End); + setTextCursor(cursor); + updateScrollBars(); } diff --git a/src/uisupport/multilineedit.h b/src/uisupport/multilineedit.h index 3218e813..2041be29 100644 --- a/src/uisupport/multilineedit.h +++ b/src/uisupport/multilineedit.h @@ -35,103 +35,105 @@ class QKeyEvent; class TabCompleter; -class MultiLineEdit : public MultiLineEditParent { - Q_OBJECT +class MultiLineEdit : public MultiLineEditParent +{ + Q_OBJECT public: - enum Mode { - SingleLine, - MultiLine - }; + enum Mode { + SingleLine, + MultiLine + }; - MultiLineEdit(QWidget *parent = 0); - ~MultiLineEdit(); + MultiLineEdit(QWidget *parent = 0); + ~MultiLineEdit(); - void setCustomFont(const QFont &); // should be used instead setFont(), so we can set our size correctly + void setCustomFont(const QFont &); // should be used instead setFont(), so we can set our size correctly - // Compatibility methods with the rest of the classes which still expect this to be a QLineEdit - inline QString text() const { return toPlainText(); } - inline QString html() const { return toHtml(); } - inline int cursorPosition() const { return textCursor().position(); } - inline void insert(const QString &newText) { insertPlainText(newText); } - inline void backspace() { keyPressEvent(new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier)); } - inline bool hasSelectedText() const { return textCursor().hasSelection(); } + // Compatibility methods with the rest of the classes which still expect this to be a QLineEdit + inline QString text() const { return toPlainText(); } + inline QString html() const { return toHtml(); } + inline int cursorPosition() const { return textCursor().position(); } + inline void insert(const QString &newText) { insertPlainText(newText); } + inline void backspace() { keyPressEvent(new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier)); } + inline bool hasSelectedText() const { return textCursor().hasSelection(); } - inline bool isSingleLine() const { return _singleLine; } - inline bool pasteProtectionEnabled() const { return _pasteProtectionEnabled; } + inline bool isSingleLine() const { return _singleLine; } + inline bool pasteProtectionEnabled() const { return _pasteProtectionEnabled; } - virtual QSize sizeHint() const; - virtual QSize minimumSizeHint() const; + virtual QSize sizeHint() const; + virtual QSize minimumSizeHint() const; - inline QString mircColorFromRGB(QString rgbColor) const { return _mircColorMap.key(rgbColor); } - inline QString rgbColorFromMirc(QString mircColor) const { return _mircColorMap[mircColor]; } - inline QMap mircColorMap() const { return _mircColorMap; } + inline QString mircColorFromRGB(QString rgbColor) const { return _mircColorMap.key(rgbColor); } + inline QString rgbColorFromMirc(QString mircColor) const { return _mircColorMap[mircColor]; } + inline QMap mircColorMap() const { return _mircColorMap; } - inline QStringList history() const { return _history; } - inline QHash tempHistory() const { return _tempHistory; } - inline qint32 idx() const { return _idx; } - inline bool emacsMode() const { return _emacsMode; } + inline QStringList history() const { return _history; } + inline QHash tempHistory() const { return _tempHistory; } + inline qint32 idx() const { return _idx; } + inline bool emacsMode() const { return _emacsMode; } public slots: - void setMode(Mode mode); - void setMinHeight(int numLines); - void setMaxHeight(int numLines); - void setEmacsMode(bool enable = true); - void setScrollBarsEnabled(bool enable = true); - void setSpellCheckEnabled(bool enable = true); - void setPasteProtectionEnabled(bool enable = true, QWidget *msgBoxParent = 0); + void setMode(Mode mode); + void setMinHeight(int numLines); + void setMaxHeight(int numLines); + void setEmacsMode(bool enable = true); + void setScrollBarsEnabled(bool enable = true); + void setSpellCheckEnabled(bool enable = true); + void setPasteProtectionEnabled(bool enable = true, QWidget *msgBoxParent = 0); - // Note: Enabling wrap will make isSingleLine() not work correctly, so only use this if minHeight() > 1! - void setWordWrapEnabled(bool enable = true); + // Note: Enabling wrap will make isSingleLine() not work correctly, so only use this if minHeight() > 1! + void setWordWrapEnabled(bool enable = true); - inline void setHistory(QStringList history) { _history = history; } - inline void setTempHistory(QHash tempHistory) { _tempHistory = tempHistory; } - inline void setIdx(qint32 idx) { _idx = idx; } + inline void setHistory(QStringList history) { _history = history; } + inline void setTempHistory(QHash tempHistory) { _tempHistory = tempHistory; } + inline void setIdx(qint32 idx) { _idx = idx; } signals: - void textEntered(const QString &text); - void noTextEntered(); + void textEntered(const QString &text); + void noTextEntered(); protected: - virtual bool event(QEvent *e); - virtual void keyPressEvent(QKeyEvent * event); - virtual void resizeEvent(QResizeEvent *event); + virtual bool event(QEvent *e); + virtual void keyPressEvent(QKeyEvent *event); + virtual void resizeEvent(QResizeEvent *event); private slots: - void on_returnPressed(); - void on_returnPressed(const QString &text); - void on_textChanged(); - void on_documentHeightChanged(qreal height); + void on_returnPressed(); + void on_returnPressed(const QString &text); + void on_textChanged(); + void on_documentHeightChanged(qreal height); - bool addToHistory(const QString &text, bool temporary = false); - void historyMoveForward(); - void historyMoveBack(); + bool addToHistory(const QString &text, bool temporary = false); + void historyMoveForward(); + void historyMoveBack(); - QString convertRichtextToMircCodes(); - QString convertMircCodesToHtml(const QString &text); - bool mircCodesChanged(QTextCursor &cursor, QTextCursor &peekcursor); + QString convertRichtextToMircCodes(); + QString convertMircCodesToHtml(const QString &text); + bool mircCodesChanged(QTextCursor &cursor, QTextCursor &peekcursor); private: - QStringList _history; - QHash _tempHistory; - qint32 _idx; - Mode _mode; - bool _singleLine; - int _minHeight; - int _maxHeight; - bool _scrollBarsEnabled; - bool _pasteProtectionEnabled; - bool _emacsMode; - - QSize _sizeHint; - qreal _lastDocumentHeight; - - QMap _mircColorMap; - - void reset(); - void showHistoryEntry(); - void updateScrollBars(); - void updateSizeHint(); + QStringList _history; + QHash _tempHistory; + qint32 _idx; + Mode _mode; + bool _singleLine; + int _minHeight; + int _maxHeight; + bool _scrollBarsEnabled; + bool _pasteProtectionEnabled; + bool _emacsMode; + + QSize _sizeHint; + qreal _lastDocumentHeight; + + QMap _mircColorMap; + + void reset(); + void showHistoryEntry(); + void updateScrollBars(); + void updateSizeHint(); }; + #endif diff --git a/src/uisupport/networkmodelcontroller.cpp b/src/uisupport/networkmodelcontroller.cpp index ac2ab660..3ad9fbf9 100644 --- a/src/uisupport/networkmodelcontroller.cpp +++ b/src/uisupport/networkmodelcontroller.cpp @@ -39,505 +39,553 @@ #include "client.h" NetworkModelController::NetworkModelController(QObject *parent) -: QObject(parent), - _actionCollection(new ActionCollection(this)), - _messageFilter(0), - _receiver(0) + : QObject(parent), + _actionCollection(new ActionCollection(this)), + _messageFilter(0), + _receiver(0) { + connect(_actionCollection, SIGNAL(actionTriggered(QAction *)), SLOT(actionTriggered(QAction *))); +} - connect(_actionCollection, SIGNAL(actionTriggered(QAction *)), SLOT(actionTriggered(QAction *))); +NetworkModelController::~NetworkModelController() +{ } -NetworkModelController::~NetworkModelController() { +Action *NetworkModelController::registerAction(ActionType type, const QString &text, bool checkable) +{ + return registerAction(type, QPixmap(), text, checkable); } -Action * NetworkModelController::registerAction(ActionType type, const QString &text, bool checkable) { - return registerAction(type, QPixmap(), text, checkable); -} -Action * NetworkModelController::registerAction(ActionType type, const QPixmap &icon, const QString &text, bool checkable) { - Action *act; - if(icon.isNull()) - act = new Action(text, this); - else - act = new Action(icon, text, this); +Action *NetworkModelController::registerAction(ActionType type, const QPixmap &icon, const QString &text, bool checkable) +{ + Action *act; + if (icon.isNull()) + act = new Action(text, this); + else + act = new Action(icon, text, this); - act->setCheckable(checkable); - act->setData(type); + act->setCheckable(checkable); + act->setData(type); - _actionCollection->addAction(QString::number(type, 16), act); - _actionByType[type] = act; - return act; + _actionCollection->addAction(QString::number(type, 16), act); + _actionByType[type] = act; + return act; } + /******** Helper Functions ***********************************************************************/ -void NetworkModelController::setIndexList(const QModelIndex &index) { - _indexList = QList() << index; +void NetworkModelController::setIndexList(const QModelIndex &index) +{ + _indexList = QList() << index; } -void NetworkModelController::setIndexList(const QList &list) { - _indexList = list; + +void NetworkModelController::setIndexList(const QList &list) +{ + _indexList = list; } -void NetworkModelController::setMessageFilter(MessageFilter *filter) { - _messageFilter = filter; + +void NetworkModelController::setMessageFilter(MessageFilter *filter) +{ + _messageFilter = filter; } -void NetworkModelController::setContextItem(const QString &contextItem) { - _contextItem = contextItem; + +void NetworkModelController::setContextItem(const QString &contextItem) +{ + _contextItem = contextItem; } -void NetworkModelController::setSlot(QObject *receiver, const char *method) { - _receiver = receiver; - _method = method; + +void NetworkModelController::setSlot(QObject *receiver, const char *method) +{ + _receiver = receiver; + _method = method; } -bool NetworkModelController::checkRequirements(const QModelIndex &index, ItemActiveStates requiredActiveState) { - if(!index.isValid()) - return false; - ItemActiveStates isActive = index.data(NetworkModel::ItemActiveRole).toBool() - ? ActiveState - : InactiveState; +bool NetworkModelController::checkRequirements(const QModelIndex &index, ItemActiveStates requiredActiveState) +{ + if (!index.isValid()) + return false; + + ItemActiveStates isActive = index.data(NetworkModel::ItemActiveRole).toBool() + ? ActiveState + : InactiveState; - if(!(isActive & requiredActiveState)) - return false; + if (!(isActive & requiredActiveState)) + return false; - return true; + return true; } -QString NetworkModelController::nickName(const QModelIndex &index) const { - IrcUser *ircUser = qobject_cast(index.data(NetworkModel::IrcUserRole).value()); - if(ircUser) - return ircUser->nick(); - BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value(); - if(!bufferInfo.isValid()) - return QString(); - if(bufferInfo.type() != BufferInfo::QueryBuffer) - return QString(); +QString NetworkModelController::nickName(const QModelIndex &index) const +{ + IrcUser *ircUser = qobject_cast(index.data(NetworkModel::IrcUserRole).value()); + if (ircUser) + return ircUser->nick(); + + BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value(); + if (!bufferInfo.isValid()) + return QString(); + if (bufferInfo.type() != BufferInfo::QueryBuffer) + return QString(); - return bufferInfo.bufferName(); // FIXME this might break with merged queries maybe + return bufferInfo.bufferName(); // FIXME this might break with merged queries maybe } -BufferId NetworkModelController::findQueryBuffer(const QModelIndex &index, const QString &predefinedNick) const { - NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value(); - if(!networkId.isValid()) - return BufferId(); - QString nick = predefinedNick.isEmpty() ? nickName(index) : predefinedNick; - if(nick.isEmpty()) - return BufferId(); +BufferId NetworkModelController::findQueryBuffer(const QModelIndex &index, const QString &predefinedNick) const +{ + NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value(); + if (!networkId.isValid()) + return BufferId(); - return findQueryBuffer(networkId, nick); + QString nick = predefinedNick.isEmpty() ? nickName(index) : predefinedNick; + if (nick.isEmpty()) + return BufferId(); + + return findQueryBuffer(networkId, nick); } -BufferId NetworkModelController::findQueryBuffer(NetworkId networkId, const QString &nick) const { - return Client::networkModel()->bufferId(networkId, nick); + +BufferId NetworkModelController::findQueryBuffer(NetworkId networkId, const QString &nick) const +{ + return Client::networkModel()->bufferId(networkId, nick); } -void NetworkModelController::removeBuffers(const QModelIndexList &indexList) { - QList inactive; - foreach(QModelIndex index, indexList) { - BufferInfo info = index.data(NetworkModel::BufferInfoRole).value(); - if(info.isValid()) { - if(info.type() == BufferInfo::QueryBuffer - || (info.type() == BufferInfo::ChannelBuffer && !index.data(NetworkModel::ItemActiveRole).toBool())) - inactive << info; - } - } - QString msg; - if(inactive.count()) { - msg = tr("Do you want to delete the following buffer(s) permanently?", 0, inactive.count()); - msg += "
    "; - int count = 0; - foreach(BufferInfo info, inactive) { - if(count < 10) { - msg += QString("
  • %1
  • ").arg(info.bufferName()); - count++; - } - else - break; + +void NetworkModelController::removeBuffers(const QModelIndexList &indexList) +{ + QList inactive; + foreach(QModelIndex index, indexList) { + BufferInfo info = index.data(NetworkModel::BufferInfoRole).value(); + if (info.isValid()) { + if (info.type() == BufferInfo::QueryBuffer + || (info.type() == BufferInfo::ChannelBuffer && !index.data(NetworkModel::ItemActiveRole).toBool())) + inactive << info; + } } - msg += "
"; - if(count > 9 && inactive.size() - count != 0) - msg += tr("...and %1 more

").arg(inactive.size() - count); - msg += tr("Note: This will delete all related data, including all backlog data, from the core's database and cannot be undone."); - if(inactive.count() != indexList.count()) - msg += tr("
Active channel buffers cannot be deleted, please part the channel first."); - - if(QMessageBox::question(0, tr("Remove buffers permanently?"), msg, QMessageBox::Yes|QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) { - foreach(BufferInfo info, inactive) - Client::removeBuffer(info.bufferId()); + QString msg; + if (inactive.count()) { + msg = tr("Do you want to delete the following buffer(s) permanently?", 0, inactive.count()); + msg += "
    "; + int count = 0; + foreach(BufferInfo info, inactive) { + if (count < 10) { + msg += QString("
  • %1
  • ").arg(info.bufferName()); + count++; + } + else + break; + } + msg += "
"; + if (count > 9 && inactive.size() - count != 0) + msg += tr("...and %1 more

").arg(inactive.size() - count); + msg += tr("Note: This will delete all related data, including all backlog data, from the core's database and cannot be undone."); + if (inactive.count() != indexList.count()) + msg += tr("
Active channel buffers cannot be deleted, please part the channel first."); + + if (QMessageBox::question(0, tr("Remove buffers permanently?"), msg, QMessageBox::Yes|QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) { + foreach(BufferInfo info, inactive) + Client::removeBuffer(info.bufferId()); + } } - } } -void NetworkModelController::handleExternalAction(ActionType type, QAction *action) { - Q_UNUSED(type); - if(receiver() && method()) { - if(!QMetaObject::invokeMethod(receiver(), method(), Q_ARG(QAction *, action))) - qWarning() << "NetworkModelActionController::handleExternalAction(): Could not invoke slot" << receiver() << method(); - } + +void NetworkModelController::handleExternalAction(ActionType type, QAction *action) +{ + Q_UNUSED(type); + if (receiver() && method()) { + if (!QMetaObject::invokeMethod(receiver(), method(), Q_ARG(QAction *, action))) + qWarning() << "NetworkModelActionController::handleExternalAction(): Could not invoke slot" << receiver() << method(); + } } + /******** Handle Actions *************************************************************************/ -void NetworkModelController::actionTriggered(QAction *action) { - ActionType type = (ActionType)action->data().toInt(); - if(type > 0) { - if(type & NetworkMask) - handleNetworkAction(type, action); - else if(type & BufferMask) - handleBufferAction(type, action); - else if(type & HideMask) - handleHideAction(type, action); - else if(type & GeneralMask) - handleGeneralAction(type, action); - else if(type & NickMask) - handleNickAction(type, action); - else if(type & ExternalMask) - handleExternalAction(type, action); - else - qWarning() << "NetworkModelController::actionTriggered(): Unhandled action!"; - } +void NetworkModelController::actionTriggered(QAction *action) +{ + ActionType type = (ActionType)action->data().toInt(); + if (type > 0) { + if (type & NetworkMask) + handleNetworkAction(type, action); + else if (type & BufferMask) + handleBufferAction(type, action); + else if (type & HideMask) + handleHideAction(type, action); + else if (type & GeneralMask) + handleGeneralAction(type, action); + else if (type & NickMask) + handleNickAction(type, action); + else if (type & ExternalMask) + handleExternalAction(type, action); + else + qWarning() << "NetworkModelController::actionTriggered(): Unhandled action!"; + } } -void NetworkModelController::handleNetworkAction(ActionType type, QAction *) { - if(type == NetworkConnectAll || type == NetworkDisconnectAll) { - foreach(NetworkId id, Client::networkIds()) { - const Network *net = Client::network(id); - if(type == NetworkConnectAll && net->connectionState() == Network::Disconnected) - net->requestConnect(); - if(type == NetworkDisconnectAll && net->connectionState() != Network::Disconnected) - net->requestDisconnect(); + +void NetworkModelController::handleNetworkAction(ActionType type, QAction *) +{ + if (type == NetworkConnectAll || type == NetworkDisconnectAll) { + foreach(NetworkId id, Client::networkIds()) { + const Network *net = Client::network(id); + if (type == NetworkConnectAll && net->connectionState() == Network::Disconnected) + net->requestConnect(); + if (type == NetworkDisconnectAll && net->connectionState() != Network::Disconnected) + net->requestDisconnect(); + } + return; } - return; - } - if(!indexList().count()) - return; + if (!indexList().count()) + return; - const Network *network = Client::network(indexList().at(0).data(NetworkModel::NetworkIdRole).value()); - Q_CHECK_PTR(network); - if(!network) - return; + const Network *network = Client::network(indexList().at(0).data(NetworkModel::NetworkIdRole).value()); + Q_CHECK_PTR(network); + if (!network) + return; - switch(type) { + switch (type) { case NetworkConnect: - network->requestConnect(); - break; + network->requestConnect(); + break; case NetworkDisconnect: - network->requestDisconnect(); - break; + network->requestDisconnect(); + break; default: - break; - } + break; + } } -void NetworkModelController::handleBufferAction(ActionType type, QAction *) { - if(type == BufferRemove) { - removeBuffers(indexList()); - } else { - QList bufferList; // create temp list because model indexes might change - foreach(QModelIndex index, indexList()) { - BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value(); - if(bufferInfo.isValid()) - bufferList << bufferInfo; +void NetworkModelController::handleBufferAction(ActionType type, QAction *) +{ + if (type == BufferRemove) { + removeBuffers(indexList()); } + else { + QList bufferList; // create temp list because model indexes might change + foreach(QModelIndex index, indexList()) { + BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value(); + if (bufferInfo.isValid()) + bufferList << bufferInfo; + } - foreach(BufferInfo bufferInfo, bufferList) { - switch(type) { - case BufferJoin: - Client::userInput(bufferInfo, QString("/JOIN %1").arg(bufferInfo.bufferName())); - break; - case BufferPart: - { - QString reason = Client::identity(Client::network(bufferInfo.networkId())->identity())->partReason(); - Client::userInput(bufferInfo, QString("/PART %1").arg(reason)); - break; + foreach(BufferInfo bufferInfo, bufferList) { + switch (type) { + case BufferJoin: + Client::userInput(bufferInfo, QString("/JOIN %1").arg(bufferInfo.bufferName())); + break; + case BufferPart: + { + QString reason = Client::identity(Client::network(bufferInfo.networkId())->identity())->partReason(); + Client::userInput(bufferInfo, QString("/PART %1").arg(reason)); + break; + } + case BufferSwitchTo: + Client::bufferModel()->switchToBuffer(bufferInfo.bufferId()); + break; + default: + break; + } } - case BufferSwitchTo: - Client::bufferModel()->switchToBuffer(bufferInfo.bufferId()); - break; - default: - break; - } } - } } -void NetworkModelController::handleHideAction(ActionType type, QAction *action) { - Q_UNUSED(action) - - int filter = 0; - if(NetworkModelController::action(HideJoin)->isChecked()) - filter |= Message::Join | Message::NetsplitJoin; - if(NetworkModelController::action(HidePart)->isChecked()) - filter |= Message::Part; - if(NetworkModelController::action(HideQuit)->isChecked()) - filter |= Message::Quit | Message::NetsplitQuit; - if(NetworkModelController::action(HideNick)->isChecked()) - filter |= Message::Nick; - if(NetworkModelController::action(HideMode)->isChecked()) - filter |= Message::Mode; - if(NetworkModelController::action(HideDayChange)->isChecked()) - filter |= Message::DayChange; - if(NetworkModelController::action(HideTopic)->isChecked()) - filter |= Message::Topic; - - switch(type) { - case HideJoin: - case HidePart: - case HideQuit: - case HideNick: - case HideMode: - case HideDayChange: - case HideTopic: - if(_messageFilter) - BufferSettings(_messageFilter->idString()).setMessageFilter(filter); - else { - foreach(QModelIndex index, _indexList) { - BufferId bufferId = index.data(NetworkModel::BufferIdRole).value(); - if(!bufferId.isValid()) - continue; - BufferSettings(bufferId).setMessageFilter(filter); - } - } - return; - case HideApplyToAll: - BufferSettings().setMessageFilter(filter); - case HideUseDefaults: - if(_messageFilter) - BufferSettings(_messageFilter->idString()).removeFilter(); - else { - foreach(QModelIndex index, _indexList) { - BufferId bufferId = index.data(NetworkModel::BufferIdRole).value(); - if(!bufferId.isValid()) - continue; - BufferSettings(bufferId).removeFilter(); - } - } - return; - default: - return; - }; -} -void NetworkModelController::handleGeneralAction(ActionType type, QAction *action) { - Q_UNUSED(action) - - if(!indexList().count()) - return; - NetworkId networkId = indexList().at(0).data(NetworkModel::NetworkIdRole).value(); - - switch(type) { - case JoinChannel: { - QString channelName = contextItem(); - QString channelPassword; - if(channelName.isEmpty()) { - JoinDlg dlg(indexList().first()); - if(dlg.exec() == QDialog::Accepted) { - channelName = dlg.channelName(); - networkId = dlg.networkId(); - channelPassword = dlg.channelPassword(); +void NetworkModelController::handleHideAction(ActionType type, QAction *action) +{ + Q_UNUSED(action) + + int filter = 0; + if (NetworkModelController::action(HideJoin)->isChecked()) + filter |= Message::Join | Message::NetsplitJoin; + if (NetworkModelController::action(HidePart)->isChecked()) + filter |= Message::Part; + if (NetworkModelController::action(HideQuit)->isChecked()) + filter |= Message::Quit | Message::NetsplitQuit; + if (NetworkModelController::action(HideNick)->isChecked()) + filter |= Message::Nick; + if (NetworkModelController::action(HideMode)->isChecked()) + filter |= Message::Mode; + if (NetworkModelController::action(HideDayChange)->isChecked()) + filter |= Message::DayChange; + if (NetworkModelController::action(HideTopic)->isChecked()) + filter |= Message::Topic; + + switch (type) { + case HideJoin: + case HidePart: + case HideQuit: + case HideNick: + case HideMode: + case HideDayChange: + case HideTopic: + if (_messageFilter) + BufferSettings(_messageFilter->idString()).setMessageFilter(filter); + else { + foreach(QModelIndex index, _indexList) { + BufferId bufferId = index.data(NetworkModel::BufferIdRole).value(); + if (!bufferId.isValid()) + continue; + BufferSettings(bufferId).setMessageFilter(filter); + } } - } - if(!channelName.isEmpty()) { - if(!channelPassword.isEmpty()) - Client::instance()->userInput(BufferInfo::fakeStatusBuffer(networkId), QString("/JOIN %1 %2").arg(channelName).arg(channelPassword)); - else - Client::instance()->userInput(BufferInfo::fakeStatusBuffer(networkId), QString("/JOIN %1").arg(channelName)); - } - break; - } - case ShowChannelList: - if(networkId.isValid()) - emit showChannelList(networkId); - break; - case ShowIgnoreList: - if(networkId.isValid()) - emit showIgnoreList(QString()); - break; + return; + case HideApplyToAll: + BufferSettings().setMessageFilter(filter); + case HideUseDefaults: + if (_messageFilter) + BufferSettings(_messageFilter->idString()).removeFilter(); + else { + foreach(QModelIndex index, _indexList) { + BufferId bufferId = index.data(NetworkModel::BufferIdRole).value(); + if (!bufferId.isValid()) + continue; + BufferSettings(bufferId).removeFilter(); + } + } + return; default: - break; - } + return; + }; } -void NetworkModelController::handleNickAction(ActionType type, QAction *action) { - foreach(QModelIndex index, indexList()) { - NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value(); - if(!networkId.isValid()) - continue; - QString nick = nickName(index); - if(nick.isEmpty()) - continue; - BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value(); - if(!bufferInfo.isValid()) - continue; - switch(type) { - case NickWhois: - Client::userInput(bufferInfo, QString("/WHOIS %1 %1").arg(nick)); - break; - case NickCtcpVersion: - Client::userInput(bufferInfo, QString("/CTCP %1 VERSION").arg(nick)); - break; - case NickCtcpPing: - Client::userInput(bufferInfo, QString("/CTCP %1 PING").arg(nick)); - break; - case NickCtcpTime: - Client::userInput(bufferInfo, QString("/CTCP %1 TIME").arg(nick)); - break; - case NickCtcpClientinfo: - Client::userInput(bufferInfo, QString("/CTCP %1 CLIENTINFO").arg(nick)); - break; - case NickOp: - Client::userInput(bufferInfo, QString("/OP %1").arg(nick)); - break; - case NickDeop: - Client::userInput(bufferInfo, QString("/DEOP %1").arg(nick)); - break; - case NickHalfop: - Client::userInput(bufferInfo, QString("/HALFOP %1").arg(nick)); - break; - case NickDehalfop: - Client::userInput(bufferInfo, QString("/DEHALFOP %1").arg(nick)); - break; - case NickVoice: - Client::userInput(bufferInfo, QString("/VOICE %1").arg(nick)); - break; - case NickDevoice: - Client::userInput(bufferInfo, QString("/DEVOICE %1").arg(nick)); - break; - case NickKick: - Client::userInput(bufferInfo, QString("/KICK %1").arg(nick)); - break; - case NickBan: - Client::userInput(bufferInfo, QString("/BAN %1").arg(nick)); - break; - case NickKickBan: - Client::userInput(bufferInfo, QString("/BAN %1").arg(nick)); - Client::userInput(bufferInfo, QString("/KICK %1").arg(nick)); - break; - case NickSwitchTo: - case NickQuery: - Client::bufferModel()->switchToOrStartQuery(networkId, nick); - break; - case NickIgnoreUser: - { - IrcUser *ircUser = qobject_cast(index.data(NetworkModel::IrcUserRole).value()); - if(!ircUser) - break; - Client::ignoreListManager()->requestAddIgnoreListItem(IgnoreListManager::SenderIgnore, - action->property("ignoreRule").toString(), - false, IgnoreListManager::SoftStrictness, - IgnoreListManager::NetworkScope, - ircUser->network()->networkName(), true); - break; - } - case NickIgnoreHost: - { - IrcUser *ircUser = qobject_cast(index.data(NetworkModel::IrcUserRole).value()); - if(!ircUser) - break; - Client::ignoreListManager()->requestAddIgnoreListItem(IgnoreListManager::SenderIgnore, - action->property("ignoreRule").toString(), - false, IgnoreListManager::SoftStrictness, - IgnoreListManager::NetworkScope, - ircUser->network()->networkName(), true); +void NetworkModelController::handleGeneralAction(ActionType type, QAction *action) +{ + Q_UNUSED(action) + + if (!indexList().count()) + return; + NetworkId networkId = indexList().at(0).data(NetworkModel::NetworkIdRole).value(); + + switch (type) { + case JoinChannel: + { + QString channelName = contextItem(); + QString channelPassword; + if (channelName.isEmpty()) { + JoinDlg dlg(indexList().first()); + if (dlg.exec() == QDialog::Accepted) { + channelName = dlg.channelName(); + networkId = dlg.networkId(); + channelPassword = dlg.channelPassword(); + } + } + if (!channelName.isEmpty()) { + if (!channelPassword.isEmpty()) + Client::instance()->userInput(BufferInfo::fakeStatusBuffer(networkId), QString("/JOIN %1 %2").arg(channelName).arg(channelPassword)); + else + Client::instance()->userInput(BufferInfo::fakeStatusBuffer(networkId), QString("/JOIN %1").arg(channelName)); + } break; - } - case NickIgnoreDomain: - { - IrcUser *ircUser = qobject_cast(index.data(NetworkModel::IrcUserRole).value()); - if(!ircUser) - break; - Client::ignoreListManager()->requestAddIgnoreListItem(IgnoreListManager::SenderIgnore, - action->property("ignoreRule").toString(), - false, IgnoreListManager::SoftStrictness, - IgnoreListManager::NetworkScope, - ircUser->network()->networkName(), true); + } + case ShowChannelList: + if (networkId.isValid()) + emit showChannelList(networkId); break; - } - case NickIgnoreCustom: - // forward that to mainwin since we can access the settingspage only from there - emit showIgnoreList(action->property("ignoreRule").toString()); + case ShowIgnoreList: + if (networkId.isValid()) + emit showIgnoreList(QString()); break; - case NickIgnoreToggleEnabled0: - case NickIgnoreToggleEnabled1: - case NickIgnoreToggleEnabled2: - case NickIgnoreToggleEnabled3: - case NickIgnoreToggleEnabled4: - Client::ignoreListManager()->requestToggleIgnoreRule(action->property("ignoreRule").toString()); + default: break; - default: - qWarning() << "Unhandled nick action"; } - } } + +void NetworkModelController::handleNickAction(ActionType type, QAction *action) +{ + foreach(QModelIndex index, indexList()) { + NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value(); + if (!networkId.isValid()) + continue; + QString nick = nickName(index); + if (nick.isEmpty()) + continue; + BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value(); + if (!bufferInfo.isValid()) + continue; + + switch (type) { + case NickWhois: + Client::userInput(bufferInfo, QString("/WHOIS %1 %1").arg(nick)); + break; + case NickCtcpVersion: + Client::userInput(bufferInfo, QString("/CTCP %1 VERSION").arg(nick)); + break; + case NickCtcpPing: + Client::userInput(bufferInfo, QString("/CTCP %1 PING").arg(nick)); + break; + case NickCtcpTime: + Client::userInput(bufferInfo, QString("/CTCP %1 TIME").arg(nick)); + break; + case NickCtcpClientinfo: + Client::userInput(bufferInfo, QString("/CTCP %1 CLIENTINFO").arg(nick)); + break; + case NickOp: + Client::userInput(bufferInfo, QString("/OP %1").arg(nick)); + break; + case NickDeop: + Client::userInput(bufferInfo, QString("/DEOP %1").arg(nick)); + break; + case NickHalfop: + Client::userInput(bufferInfo, QString("/HALFOP %1").arg(nick)); + break; + case NickDehalfop: + Client::userInput(bufferInfo, QString("/DEHALFOP %1").arg(nick)); + break; + case NickVoice: + Client::userInput(bufferInfo, QString("/VOICE %1").arg(nick)); + break; + case NickDevoice: + Client::userInput(bufferInfo, QString("/DEVOICE %1").arg(nick)); + break; + case NickKick: + Client::userInput(bufferInfo, QString("/KICK %1").arg(nick)); + break; + case NickBan: + Client::userInput(bufferInfo, QString("/BAN %1").arg(nick)); + break; + case NickKickBan: + Client::userInput(bufferInfo, QString("/BAN %1").arg(nick)); + Client::userInput(bufferInfo, QString("/KICK %1").arg(nick)); + break; + case NickSwitchTo: + case NickQuery: + Client::bufferModel()->switchToOrStartQuery(networkId, nick); + break; + case NickIgnoreUser: + { + IrcUser *ircUser = qobject_cast(index.data(NetworkModel::IrcUserRole).value()); + if (!ircUser) + break; + Client::ignoreListManager()->requestAddIgnoreListItem(IgnoreListManager::SenderIgnore, + action->property("ignoreRule").toString(), + false, IgnoreListManager::SoftStrictness, + IgnoreListManager::NetworkScope, + ircUser->network()->networkName(), true); + break; + } + case NickIgnoreHost: + { + IrcUser *ircUser = qobject_cast(index.data(NetworkModel::IrcUserRole).value()); + if (!ircUser) + break; + Client::ignoreListManager()->requestAddIgnoreListItem(IgnoreListManager::SenderIgnore, + action->property("ignoreRule").toString(), + false, IgnoreListManager::SoftStrictness, + IgnoreListManager::NetworkScope, + ircUser->network()->networkName(), true); + break; + } + case NickIgnoreDomain: + { + IrcUser *ircUser = qobject_cast(index.data(NetworkModel::IrcUserRole).value()); + if (!ircUser) + break; + Client::ignoreListManager()->requestAddIgnoreListItem(IgnoreListManager::SenderIgnore, + action->property("ignoreRule").toString(), + false, IgnoreListManager::SoftStrictness, + IgnoreListManager::NetworkScope, + ircUser->network()->networkName(), true); + break; + } + case NickIgnoreCustom: + // forward that to mainwin since we can access the settingspage only from there + emit showIgnoreList(action->property("ignoreRule").toString()); + break; + case NickIgnoreToggleEnabled0: + case NickIgnoreToggleEnabled1: + case NickIgnoreToggleEnabled2: + case NickIgnoreToggleEnabled3: + case NickIgnoreToggleEnabled4: + Client::ignoreListManager()->requestToggleIgnoreRule(action->property("ignoreRule").toString()); + break; + default: + qWarning() << "Unhandled nick action"; + } + } +} + + /*************************************************************************************************************** * JoinDlg ***************************************************************************************************************/ -NetworkModelController::JoinDlg::JoinDlg(const QModelIndex &index, QWidget *parent) : QDialog(parent) { - setWindowIcon(SmallIcon("irc-join-channel")); - setWindowTitle(tr("Join Channel")); - - QGridLayout *layout = new QGridLayout(this); - layout->addWidget(new QLabel(tr("Network:")), 0, 0); - layout->addWidget(networks = new QComboBox, 0, 1); - layout->addWidget(new QLabel(tr("Channel:")), 1, 0); - layout->addWidget(channel = new QLineEdit, 1, 1); - layout->addWidget(new QLabel(tr("Password:")), 2, 0); - layout->addWidget(password = new QLineEdit, 2, 1); - layout->addWidget(buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel), 3, 0, 1, 2); - setLayout(layout); - - channel->setFocus(); - buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - networks->setInsertPolicy(QComboBox::InsertAlphabetically); - password->setEchoMode(QLineEdit::Password); - - connect(buttonBox, SIGNAL(accepted()), SLOT(accept())); - connect(buttonBox, SIGNAL(rejected()), SLOT(reject())); - connect(channel, SIGNAL(textChanged(QString)), SLOT(on_channel_textChanged(QString))); - - foreach(NetworkId id, Client::networkIds()) { - const Network *net = Client::network(id); - if(net->isConnected()) { - networks->addItem(net->networkName(), QVariant::fromValue(id)); +NetworkModelController::JoinDlg::JoinDlg(const QModelIndex &index, QWidget *parent) : QDialog(parent) +{ + setWindowIcon(SmallIcon("irc-join-channel")); + setWindowTitle(tr("Join Channel")); + + QGridLayout *layout = new QGridLayout(this); + layout->addWidget(new QLabel(tr("Network:")), 0, 0); + layout->addWidget(networks = new QComboBox, 0, 1); + layout->addWidget(new QLabel(tr("Channel:")), 1, 0); + layout->addWidget(channel = new QLineEdit, 1, 1); + layout->addWidget(new QLabel(tr("Password:")), 2, 0); + layout->addWidget(password = new QLineEdit, 2, 1); + layout->addWidget(buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel), 3, 0, 1, 2); + setLayout(layout); + + channel->setFocus(); + buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + networks->setInsertPolicy(QComboBox::InsertAlphabetically); + password->setEchoMode(QLineEdit::Password); + + connect(buttonBox, SIGNAL(accepted()), SLOT(accept())); + connect(buttonBox, SIGNAL(rejected()), SLOT(reject())); + connect(channel, SIGNAL(textChanged(QString)), SLOT(on_channel_textChanged(QString))); + + foreach(NetworkId id, Client::networkIds()) { + const Network *net = Client::network(id); + if (net->isConnected()) { + networks->addItem(net->networkName(), QVariant::fromValue(id)); + } } - } - if(index.isValid()) { - NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value(); - if(networkId.isValid()) { - networks->setCurrentIndex(networks->findText(Client::network(networkId)->networkName())); - if(index.data(NetworkModel::BufferTypeRole) == BufferInfo::ChannelBuffer - && !index.data(NetworkModel::ItemActiveRole).toBool()) - channel->setText(index.data(Qt::DisplayRole).toString()); + if (index.isValid()) { + NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value(); + if (networkId.isValid()) { + networks->setCurrentIndex(networks->findText(Client::network(networkId)->networkName())); + if (index.data(NetworkModel::BufferTypeRole) == BufferInfo::ChannelBuffer + && !index.data(NetworkModel::ItemActiveRole).toBool()) + channel->setText(index.data(Qt::DisplayRole).toString()); + } } - } } -NetworkId NetworkModelController::JoinDlg::networkId() const { - return networks->itemData(networks->currentIndex()).value(); + +NetworkId NetworkModelController::JoinDlg::networkId() const +{ + return networks->itemData(networks->currentIndex()).value(); } -QString NetworkModelController::JoinDlg::channelName() const { - return channel->text(); + +QString NetworkModelController::JoinDlg::channelName() const +{ + return channel->text(); } -QString NetworkModelController::JoinDlg::channelPassword() const { - return password->text(); + +QString NetworkModelController::JoinDlg::channelPassword() const +{ + return password->text(); } -void NetworkModelController::JoinDlg::on_channel_textChanged(const QString &text) { - buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!text.isEmpty()); + +void NetworkModelController::JoinDlg::on_channel_textChanged(const QString &text) +{ + buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!text.isEmpty()); } diff --git a/src/uisupport/networkmodelcontroller.h b/src/uisupport/networkmodelcontroller.h index ec27c878..455e9d43 100644 --- a/src/uisupport/networkmodelcontroller.h +++ b/src/uisupport/networkmodelcontroller.h @@ -31,169 +31,172 @@ class QComboBox; class QDialogButtonBox; class QLineEdit; -class NetworkModelController : public QObject { - Q_OBJECT +class NetworkModelController : public QObject +{ + Q_OBJECT public: - NetworkModelController(QObject *parent = 0); - virtual ~NetworkModelController(); - - // don't change enums without doublechecking masks etc. in code - enum ActionType { - // Network actions - NetworkMask = 0x0f, - NetworkConnect = 0x01, - NetworkDisconnect = 0x02, - NetworkConnectAll = 0x03, - NetworkDisconnectAll = 0x04, - - // Buffer actions - BufferMask = 0xf0, - BufferJoin = 0x10, - BufferPart = 0x20, - BufferSwitchTo = 0x30, - BufferRemove = 0x40, - - // Hide actions - HideMask = 0x0f00, - HideJoin = 0x0100, - HidePart = 0x0200, - HideQuit = 0x0300, - HideNick = 0x0400, - HideMode = 0x0500, - HideDayChange = 0x0600, - HideTopic = 0x0700, - HideUseDefaults = 0xe00, - HideApplyToAll = 0xf00, - - // General actions - GeneralMask = 0xf000, - JoinChannel = 0x1000, - ShowChannelList = 0x2000, - ShowIgnoreList = 0x3000, - - // Nick actions - NickMask = 0xff0000, - NickWhois = 0x010000, - NickQuery = 0x020000, - NickSwitchTo = 0x030000, - NickCtcpVersion = 0x040000, - NickCtcpPing = 0x050000, - NickCtcpTime = 0x060000, - NickCtcpClientinfo = 0x070000, - NickOp = 0x080000, - NickDeop = 0x090000, - NickVoice = 0x0a0000, - NickDevoice = 0x0b0000, - NickHalfop = 0x0c0000, - NickDehalfop = 0x0d0000, - NickKick = 0x0e0000, - NickBan = 0x0f0000, - NickKickBan = 0x100000, - NickIgnoreUser = 0x200000, - NickIgnoreHost = 0x300000, - NickIgnoreDomain = 0x400000, - NickIgnoreCustom = 0x500000, - // The next 5 types have to stay together - // Don't change without reading ContextMenuActionProvider::addIgnoreMenu! - NickIgnoreToggleEnabled0 = 0x600000, - NickIgnoreToggleEnabled1 = 0x700000, - NickIgnoreToggleEnabled2 = 0x800000, - NickIgnoreToggleEnabled3 = 0x900000, - NickIgnoreToggleEnabled4 = 0xa00000, - - // Actions that are handled externally - // These emit a signal to the action requester, rather than being handled here - ExternalMask = 0xff000000, - HideBufferTemporarily = 0x01000000, - HideBufferPermanently = 0x02000000 - }; - - inline Action *action(ActionType type) const; + NetworkModelController(QObject *parent = 0); + virtual ~NetworkModelController(); + + // don't change enums without doublechecking masks etc. in code + enum ActionType { + // Network actions + NetworkMask = 0x0f, + NetworkConnect = 0x01, + NetworkDisconnect = 0x02, + NetworkConnectAll = 0x03, + NetworkDisconnectAll = 0x04, + + // Buffer actions + BufferMask = 0xf0, + BufferJoin = 0x10, + BufferPart = 0x20, + BufferSwitchTo = 0x30, + BufferRemove = 0x40, + + // Hide actions + HideMask = 0x0f00, + HideJoin = 0x0100, + HidePart = 0x0200, + HideQuit = 0x0300, + HideNick = 0x0400, + HideMode = 0x0500, + HideDayChange = 0x0600, + HideTopic = 0x0700, + HideUseDefaults = 0xe00, + HideApplyToAll = 0xf00, + + // General actions + GeneralMask = 0xf000, + JoinChannel = 0x1000, + ShowChannelList = 0x2000, + ShowIgnoreList = 0x3000, + + // Nick actions + NickMask = 0xff0000, + NickWhois = 0x010000, + NickQuery = 0x020000, + NickSwitchTo = 0x030000, + NickCtcpVersion = 0x040000, + NickCtcpPing = 0x050000, + NickCtcpTime = 0x060000, + NickCtcpClientinfo = 0x070000, + NickOp = 0x080000, + NickDeop = 0x090000, + NickVoice = 0x0a0000, + NickDevoice = 0x0b0000, + NickHalfop = 0x0c0000, + NickDehalfop = 0x0d0000, + NickKick = 0x0e0000, + NickBan = 0x0f0000, + NickKickBan = 0x100000, + NickIgnoreUser = 0x200000, + NickIgnoreHost = 0x300000, + NickIgnoreDomain = 0x400000, + NickIgnoreCustom = 0x500000, + // The next 5 types have to stay together + // Don't change without reading ContextMenuActionProvider::addIgnoreMenu! + NickIgnoreToggleEnabled0 = 0x600000, + NickIgnoreToggleEnabled1 = 0x700000, + NickIgnoreToggleEnabled2 = 0x800000, + NickIgnoreToggleEnabled3 = 0x900000, + NickIgnoreToggleEnabled4 = 0xa00000, + + // Actions that are handled externally + // These emit a signal to the action requester, rather than being handled here + ExternalMask = 0xff000000, + HideBufferTemporarily = 0x01000000, + HideBufferPermanently = 0x02000000 + }; + + inline Action *action(ActionType type) const; public: - enum ItemActiveState { - InactiveState = 0x01, - ActiveState = 0x02 - }; - Q_DECLARE_FLAGS(ItemActiveStates, ItemActiveState) + enum ItemActiveState { + InactiveState = 0x01, + ActiveState = 0x02 + }; + Q_DECLARE_FLAGS(ItemActiveStates, ItemActiveState) public slots: - virtual void connectedToCore() {} - virtual void disconnectedFromCore() {} + virtual void connectedToCore() {} + virtual void disconnectedFromCore() {} protected: - inline ActionCollection *actionCollection() const; - inline QList indexList() const; - inline MessageFilter *messageFilter() const; - inline QString contextItem() const ; ///< Channel name or nick to provide context menu for - inline QObject *receiver() const ; - inline const char *method() const; - - void setIndexList(const QModelIndex &); - void setIndexList(const QList &); - void setMessageFilter(MessageFilter *); - void setContextItem(const QString &); - void setSlot(QObject *receiver, const char *method); - - Action * registerAction(ActionType type, const QString &text, bool checkable = false); - Action * registerAction(ActionType type, const QPixmap &icon, const QString &text, bool checkable = false); - bool checkRequirements(const QModelIndex &index, ItemActiveStates requiredActiveState = QFlags(ActiveState | InactiveState)); - - QString nickName(const QModelIndex &index) const; - BufferId findQueryBuffer(const QModelIndex &index, const QString &predefinedNick = QString()) const; - BufferId findQueryBuffer(NetworkId, const QString &nickName) const; - void removeBuffers(const QModelIndexList &indexList); + inline ActionCollection *actionCollection() const; + inline QList indexList() const; + inline MessageFilter *messageFilter() const; + inline QString contextItem() const; ///< Channel name or nick to provide context menu for + inline QObject *receiver() const; + inline const char *method() const; + + void setIndexList(const QModelIndex &); + void setIndexList(const QList &); + void setMessageFilter(MessageFilter *); + void setContextItem(const QString &); + void setSlot(QObject *receiver, const char *method); + + Action *registerAction(ActionType type, const QString &text, bool checkable = false); + Action *registerAction(ActionType type, const QPixmap &icon, const QString &text, bool checkable = false); + bool checkRequirements(const QModelIndex &index, ItemActiveStates requiredActiveState = QFlags(ActiveState | InactiveState)); + + QString nickName(const QModelIndex &index) const; + BufferId findQueryBuffer(const QModelIndex &index, const QString &predefinedNick = QString()) const; + BufferId findQueryBuffer(NetworkId, const QString &nickName) const; + void removeBuffers(const QModelIndexList &indexList); protected slots: - virtual void actionTriggered(QAction *); + virtual void actionTriggered(QAction *); signals: - void showChannelList(NetworkId); - void showIgnoreList(QString); + void showChannelList(NetworkId); + void showIgnoreList(QString); protected: - virtual void handleNetworkAction(ActionType, QAction *); - virtual void handleBufferAction(ActionType, QAction *); - virtual void handleHideAction(ActionType, QAction *); - virtual void handleNickAction(ActionType, QAction *action); - virtual void handleGeneralAction(ActionType, QAction *); - virtual void handleExternalAction(ActionType, QAction *); + virtual void handleNetworkAction(ActionType, QAction *); + virtual void handleBufferAction(ActionType, QAction *); + virtual void handleHideAction(ActionType, QAction *); + virtual void handleNickAction(ActionType, QAction *action); + virtual void handleGeneralAction(ActionType, QAction *); + virtual void handleExternalAction(ActionType, QAction *); - class JoinDlg; + class JoinDlg; private: - NetworkModel *_model; + NetworkModel *_model; - ActionCollection *_actionCollection; - QHash _actionByType; + ActionCollection *_actionCollection; + QHash _actionByType; - QList _indexList; - MessageFilter *_messageFilter; - QString _contextItem; ///< Channel name or nick to provide context menu for - QObject *_receiver; - const char *_method; + QList _indexList; + MessageFilter *_messageFilter; + QString _contextItem; ///< Channel name or nick to provide context menu for + QObject *_receiver; + const char *_method; }; + //! Input dialog for joining a channel -class NetworkModelController::JoinDlg : public QDialog { - Q_OBJECT +class NetworkModelController::JoinDlg : public QDialog +{ + Q_OBJECT public: - JoinDlg(const QModelIndex &index, QWidget *parent = 0); + JoinDlg(const QModelIndex &index, QWidget *parent = 0); - QString channelName() const; - QString channelPassword() const; - NetworkId networkId() const; + QString channelName() const; + QString channelPassword() const; + NetworkId networkId() const; private slots: - void on_channel_textChanged(const QString &); + void on_channel_textChanged(const QString &); private: - QComboBox *networks; - QLineEdit *channel; - QLineEdit *password; - QDialogButtonBox *buttonBox; + QComboBox *networks; + QLineEdit *channel; + QLineEdit *password; + QDialogButtonBox *buttonBox; }; diff --git a/src/uisupport/nickview.cpp b/src/uisupport/nickview.cpp index 8b157445..55b7ba9c 100644 --- a/src/uisupport/nickview.cpp +++ b/src/uisupport/nickview.cpp @@ -36,102 +36,117 @@ #include "types.h" NickView::NickView(QWidget *parent) - : QTreeView(parent) + : QTreeView(parent) { - setIndentation(10); - header()->hide(); - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setSortingEnabled(true); - sortByColumn(0, Qt::AscendingOrder); + setIndentation(10); + header()->hide(); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setSortingEnabled(true); + sortByColumn(0, Qt::AscendingOrder); - setContextMenuPolicy(Qt::CustomContextMenu); - setSelectionMode(QAbstractItemView::ExtendedSelection); + setContextMenuPolicy(Qt::CustomContextMenu); + setSelectionMode(QAbstractItemView::ExtendedSelection); // // breaks with Qt 4.8 // if(QString("4.8.0") > qVersion()) // FIXME breaks with Qt versions >= 4.10! - setAnimated(true); + setAnimated(true); - connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(showContextMenu(const QPoint&))); + connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(showContextMenu(const QPoint &))); #if defined Q_WS_QWS || defined Q_WS_X11 - connect(this, SIGNAL(doubleClicked(QModelIndex)), SLOT(startQuery(QModelIndex))); + connect(this, SIGNAL(doubleClicked(QModelIndex)), SLOT(startQuery(QModelIndex))); #else - // afaik this is better on Mac and Windows - connect(this, SIGNAL(activated(QModelIndex)), SLOT(startQuery(QModelIndex))); + // afaik this is better on Mac and Windows + connect(this, SIGNAL(activated(QModelIndex)), SLOT(startQuery(QModelIndex))); #endif } -void NickView::init() { - if(!model()) - return; - for(int i = 1; i < model()->columnCount(); i++) - setColumnHidden(i, true); +void NickView::init() +{ + if (!model()) + return; + + for (int i = 1; i < model()->columnCount(); i++) + setColumnHidden(i, true); - connect(selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), SIGNAL(selectionUpdated())); - connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SIGNAL(selectionUpdated())); + connect(selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), SIGNAL(selectionUpdated())); + connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SIGNAL(selectionUpdated())); } -void NickView::setModel(QAbstractItemModel *model_) { - if(model()) - disconnect(model(), 0, this, 0); - QTreeView::setModel(model_); - init(); +void NickView::setModel(QAbstractItemModel *model_) +{ + if (model()) + disconnect(model(), 0, this, 0); + + QTreeView::setModel(model_); + init(); } -void NickView::rowsInserted(const QModelIndex &parent, int start, int end) { - QTreeView::rowsInserted(parent, start, end); - if(model()->data(parent, NetworkModel::ItemTypeRole) == NetworkModel::UserCategoryItemType && !isExpanded(parent)) { - unanimatedExpandAll(); - } + +void NickView::rowsInserted(const QModelIndex &parent, int start, int end) +{ + QTreeView::rowsInserted(parent, start, end); + if (model()->data(parent, NetworkModel::ItemTypeRole) == NetworkModel::UserCategoryItemType && !isExpanded(parent)) { + unanimatedExpandAll(); + } } -void NickView::setRootIndex(const QModelIndex &index) { - QAbstractItemView::setRootIndex(index); - if(index.isValid()) - unanimatedExpandAll(); + +void NickView::setRootIndex(const QModelIndex &index) +{ + QAbstractItemView::setRootIndex(index); + if (index.isValid()) + unanimatedExpandAll(); } -QModelIndexList NickView::selectedIndexes() const { - QModelIndexList indexList = QTreeView::selectedIndexes(); - // make sure the item we clicked on is first - if(indexList.contains(currentIndex())) { - indexList.removeAll(currentIndex()); - indexList.prepend(currentIndex()); - } +QModelIndexList NickView::selectedIndexes() const +{ + QModelIndexList indexList = QTreeView::selectedIndexes(); + + // make sure the item we clicked on is first + if (indexList.contains(currentIndex())) { + indexList.removeAll(currentIndex()); + indexList.prepend(currentIndex()); + } - return indexList; + return indexList; } -void NickView::unanimatedExpandAll() { - // since of Qt Version 4.8.0 the default expandAll will not properly work if - // animations are enabled. Therefore we perform an unanimated expand when a - // model is set or a toplevel node is inserted. - bool wasAnimated = isAnimated(); - setAnimated(false); - expandAll(); - setAnimated(wasAnimated); + +void NickView::unanimatedExpandAll() +{ + // since of Qt Version 4.8.0 the default expandAll will not properly work if + // animations are enabled. Therefore we perform an unanimated expand when a + // model is set or a toplevel node is inserted. + bool wasAnimated = isAnimated(); + setAnimated(false); + expandAll(); + setAnimated(wasAnimated); } -void NickView::showContextMenu(const QPoint &pos ) { - Q_UNUSED(pos); +void NickView::showContextMenu(const QPoint &pos) +{ + Q_UNUSED(pos); - QMenu contextMenu(this); - GraphicalUi::contextMenuActionProvider()->addActions(&contextMenu, selectedIndexes()); - contextMenu.exec(QCursor::pos()); + QMenu contextMenu(this); + GraphicalUi::contextMenuActionProvider()->addActions(&contextMenu, selectedIndexes()); + contextMenu.exec(QCursor::pos()); } -void NickView::startQuery(const QModelIndex &index) { - if(index.data(NetworkModel::ItemTypeRole) != NetworkModel::IrcUserItemType) - return; - IrcUser *ircUser = qobject_cast(index.data(NetworkModel::IrcUserRole).value()); - NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value(); - if(!ircUser || !networkId.isValid()) - return; +void NickView::startQuery(const QModelIndex &index) +{ + if (index.data(NetworkModel::ItemTypeRole) != NetworkModel::IrcUserItemType) + return; + + IrcUser *ircUser = qobject_cast(index.data(NetworkModel::IrcUserRole).value()); + NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value(); + if (!ircUser || !networkId.isValid()) + return; - Client::bufferModel()->switchToOrStartQuery(networkId, ircUser->nick()); + Client::bufferModel()->switchToOrStartQuery(networkId, ircUser->nick()); } diff --git a/src/uisupport/nickview.h b/src/uisupport/nickview.h index a95798cb..7a67d5b7 100644 --- a/src/uisupport/nickview.h +++ b/src/uisupport/nickview.h @@ -25,32 +25,34 @@ #include "bufferinfo.h" -class NickView : public QTreeView { - Q_OBJECT +class NickView : public QTreeView +{ + Q_OBJECT public: - NickView(QWidget *parent = 0); + NickView(QWidget *parent = 0); protected: - virtual void rowsInserted(const QModelIndex &parent, int start, int end); + virtual void rowsInserted(const QModelIndex &parent, int start, int end); - //! This reimplementation ensures that the current index is first in list - virtual QModelIndexList selectedIndexes() const; + //! This reimplementation ensures that the current index is first in list + virtual QModelIndexList selectedIndexes() const; - void unanimatedExpandAll(); + void unanimatedExpandAll(); public slots: - virtual void setModel(QAbstractItemModel *model); - virtual void setRootIndex(const QModelIndex &index); - void init(); - void showContextMenu(const QPoint & pos); - void startQuery(const QModelIndex & modelIndex); + virtual void setModel(QAbstractItemModel *model); + virtual void setRootIndex(const QModelIndex &index); + void init(); + void showContextMenu(const QPoint &pos); + void startQuery(const QModelIndex &modelIndex); signals: - void selectionUpdated(); + void selectionUpdated(); private: - friend class NickListWidget; // needs selectedIndexes() + friend class NickListWidget; // needs selectedIndexes() }; + #endif diff --git a/src/uisupport/nickviewfilter.cpp b/src/uisupport/nickviewfilter.cpp index 72f9caad..edf776b6 100644 --- a/src/uisupport/nickviewfilter.cpp +++ b/src/uisupport/nickviewfilter.cpp @@ -30,32 +30,36 @@ * NickViewFilter ******************************************************************************************/ NickViewFilter::NickViewFilter(const BufferId &bufferId, NetworkModel *parent) - : QSortFilterProxyModel(parent), + : QSortFilterProxyModel(parent), _bufferId(bufferId) { - setSourceModel(parent); - setDynamicSortFilter(true); - setSortCaseSensitivity(Qt::CaseInsensitive); - setSortRole(TreeModel::SortRole); + setSourceModel(parent); + setDynamicSortFilter(true); + setSortCaseSensitivity(Qt::CaseInsensitive); + setSortRole(TreeModel::SortRole); } -bool NickViewFilter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { - // root node, networkindexes, the bufferindex of the buffer this filter is active for and it's children are accepted - if(!source_parent.isValid()) - return true; - QModelIndex source_child = source_parent.child(source_row, 0); - return (sourceModel()->data(source_child, NetworkModel::BufferIdRole).value() == _bufferId); +bool NickViewFilter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const +{ + // root node, networkindexes, the bufferindex of the buffer this filter is active for and it's children are accepted + if (!source_parent.isValid()) + return true; + + QModelIndex source_child = source_parent.child(source_row, 0); + return (sourceModel()->data(source_child, NetworkModel::BufferIdRole).value() == _bufferId); } -QVariant NickViewFilter::data(const QModelIndex &index, int role) const { - switch(role) { - case Qt::FontRole: - case Qt::ForegroundRole: - case Qt::BackgroundRole: - case Qt::DecorationRole: - return GraphicalUi::uiStyle()->nickViewItemData(mapToSource(index), role); - default: - return QSortFilterProxyModel::data(index, role); - } + +QVariant NickViewFilter::data(const QModelIndex &index, int role) const +{ + switch (role) { + case Qt::FontRole: + case Qt::ForegroundRole: + case Qt::BackgroundRole: + case Qt::DecorationRole: + return GraphicalUi::uiStyle()->nickViewItemData(mapToSource(index), role); + default: + return QSortFilterProxyModel::data(index, role); + } } diff --git a/src/uisupport/nickviewfilter.h b/src/uisupport/nickviewfilter.h index 38208139..0c29c869 100644 --- a/src/uisupport/nickviewfilter.h +++ b/src/uisupport/nickviewfilter.h @@ -28,21 +28,23 @@ class NetworkModel; // This is proxymodel is purely for the sorting right now -class NickViewFilter : public QSortFilterProxyModel { - Q_OBJECT +class NickViewFilter : public QSortFilterProxyModel +{ + Q_OBJECT public: - NickViewFilter(const BufferId &bufferId, NetworkModel *parent = 0); + NickViewFilter(const BufferId &bufferId, NetworkModel *parent = 0); - virtual QVariant data(const QModelIndex &index, int role) const; - QVariant icon(const QModelIndex &index) const; + virtual QVariant data(const QModelIndex &index, int role) const; + QVariant icon(const QModelIndex &index) const; protected: - virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; - QVariant styleData(const QModelIndex &index, int role) const; + virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; + QVariant styleData(const QModelIndex &index, int role) const; private: - BufferId _bufferId; + BufferId _bufferId; }; + #endif diff --git a/src/uisupport/qssparser.cpp b/src/uisupport/qssparser.cpp index f6927e42..e40fe15e 100644 --- a/src/uisupport/qssparser.cpp +++ b/src/uisupport/qssparser.cpp @@ -23,665 +23,710 @@ #include "qssparser.h" QssParser::QssParser() -: _maxSenderHash(0) + : _maxSenderHash(0) { - _palette = QApplication::palette(); - - // Init palette color roles - _paletteColorRoles["alternate-base"] = QPalette::AlternateBase; - _paletteColorRoles["background"] = QPalette::Background; - _paletteColorRoles["base"] = QPalette::Base; - _paletteColorRoles["bright-text"] = QPalette::BrightText; - _paletteColorRoles["button"] = QPalette::Button; - _paletteColorRoles["button-text"] = QPalette::ButtonText; - _paletteColorRoles["dark"] = QPalette::Dark; - _paletteColorRoles["foreground"] = QPalette::Foreground; - _paletteColorRoles["highlight"] = QPalette::Highlight; - _paletteColorRoles["highlighted-text"] = QPalette::HighlightedText; - _paletteColorRoles["light"] = QPalette::Light; - _paletteColorRoles["link"] = QPalette::Link; - _paletteColorRoles["link-visited"] = QPalette::LinkVisited; - _paletteColorRoles["mid"] = QPalette::Mid; - _paletteColorRoles["midlight"] = QPalette::Midlight; - _paletteColorRoles["shadow"] = QPalette::Shadow; - _paletteColorRoles["text"] = QPalette::Text; - _paletteColorRoles["tooltip-base"] = QPalette::ToolTipBase; - _paletteColorRoles["tooltip-text"] = QPalette::ToolTipText; - _paletteColorRoles["window"] = QPalette::Window; - _paletteColorRoles["window-text"] = QPalette::WindowText; - - _uiStylePalette = QVector(UiStyle::NumRoles, QBrush()); - - _uiStyleColorRoles["marker-line"] = UiStyle::MarkerLine; + _palette = QApplication::palette(); + + // Init palette color roles + _paletteColorRoles["alternate-base"] = QPalette::AlternateBase; + _paletteColorRoles["background"] = QPalette::Background; + _paletteColorRoles["base"] = QPalette::Base; + _paletteColorRoles["bright-text"] = QPalette::BrightText; + _paletteColorRoles["button"] = QPalette::Button; + _paletteColorRoles["button-text"] = QPalette::ButtonText; + _paletteColorRoles["dark"] = QPalette::Dark; + _paletteColorRoles["foreground"] = QPalette::Foreground; + _paletteColorRoles["highlight"] = QPalette::Highlight; + _paletteColorRoles["highlighted-text"] = QPalette::HighlightedText; + _paletteColorRoles["light"] = QPalette::Light; + _paletteColorRoles["link"] = QPalette::Link; + _paletteColorRoles["link-visited"] = QPalette::LinkVisited; + _paletteColorRoles["mid"] = QPalette::Mid; + _paletteColorRoles["midlight"] = QPalette::Midlight; + _paletteColorRoles["shadow"] = QPalette::Shadow; + _paletteColorRoles["text"] = QPalette::Text; + _paletteColorRoles["tooltip-base"] = QPalette::ToolTipBase; + _paletteColorRoles["tooltip-text"] = QPalette::ToolTipText; + _paletteColorRoles["window"] = QPalette::Window; + _paletteColorRoles["window-text"] = QPalette::WindowText; + + _uiStylePalette = QVector(UiStyle::NumRoles, QBrush()); + + _uiStyleColorRoles["marker-line"] = UiStyle::MarkerLine; } -void QssParser::processStyleSheet(QString &ss) { - if(ss.isEmpty()) - return; - - // Remove C-style comments /* */ or // - QRegExp commentRx("(//.*(\\n|$)|/\\*.*\\*/)"); - commentRx.setMinimal(true); - ss.remove(commentRx); - - // Palette definitions first, so we can apply roles later on - QRegExp paletterx("(Palette[^{]*)\\{([^}]+)\\}"); - int pos = 0; - while((pos = paletterx.indexIn(ss, pos)) >= 0) { - parsePaletteBlock(paletterx.cap(1).trimmed(), paletterx.cap(2).trimmed()); - ss.remove(pos, paletterx.matchedLength()); - } - - // Now we can parse the rest of our custom blocks - QRegExp blockrx("((?:ChatLine|ChatListItem|NickListItem)[^{]*)\\{([^}]+)\\}"); - pos = 0; - while((pos = blockrx.indexIn(ss, pos)) >= 0) { - //qDebug() << blockrx.cap(1) << blockrx.cap(2); - QString declaration = blockrx.cap(1).trimmed(); - QString contents = blockrx.cap(2).trimmed(); - - if(declaration.startsWith("ChatLine")) - parseChatLineBlock(declaration, contents); - else if(declaration.startsWith("ChatListItem") || declaration.startsWith("NickListItem")) - parseListItemBlock(declaration, contents); - //else - // TODO: add moar here - - ss.remove(pos, blockrx.matchedLength()); - } + +void QssParser::processStyleSheet(QString &ss) +{ + if (ss.isEmpty()) + return; + + // Remove C-style comments /* */ or // + QRegExp commentRx("(//.*(\\n|$)|/\\*.*\\*/)"); + commentRx.setMinimal(true); + ss.remove(commentRx); + + // Palette definitions first, so we can apply roles later on + QRegExp paletterx("(Palette[^{]*)\\{([^}]+)\\}"); + int pos = 0; + while ((pos = paletterx.indexIn(ss, pos)) >= 0) { + parsePaletteBlock(paletterx.cap(1).trimmed(), paletterx.cap(2).trimmed()); + ss.remove(pos, paletterx.matchedLength()); + } + + // Now we can parse the rest of our custom blocks + QRegExp blockrx("((?:ChatLine|ChatListItem|NickListItem)[^{]*)\\{([^}]+)\\}"); + pos = 0; + while ((pos = blockrx.indexIn(ss, pos)) >= 0) { + //qDebug() << blockrx.cap(1) << blockrx.cap(2); + QString declaration = blockrx.cap(1).trimmed(); + QString contents = blockrx.cap(2).trimmed(); + + if (declaration.startsWith("ChatLine")) + parseChatLineBlock(declaration, contents); + else if (declaration.startsWith("ChatListItem") || declaration.startsWith("NickListItem")) + parseListItemBlock(declaration, contents); + //else + // TODO: add moar here + + ss.remove(pos, blockrx.matchedLength()); + } } + /******** Parse a whole block: declaration { contents } *******/ -void QssParser::parseChatLineBlock(const QString &decl, const QString &contents) { - quint64 fmtType = parseFormatType(decl); - if(fmtType == UiStyle::Invalid) - return; +void QssParser::parseChatLineBlock(const QString &decl, const QString &contents) +{ + quint64 fmtType = parseFormatType(decl); + if (fmtType == UiStyle::Invalid) + return; - _formats[fmtType].merge(parseFormat(contents)); + _formats[fmtType].merge(parseFormat(contents)); } -void QssParser::parseListItemBlock(const QString &decl, const QString &contents) { - quint32 fmtType = parseItemFormatType(decl); - if(fmtType == UiStyle::Invalid) - return; - _listItemFormats[fmtType].merge(parseFormat(contents)); +void QssParser::parseListItemBlock(const QString &decl, const QString &contents) +{ + quint32 fmtType = parseItemFormatType(decl); + if (fmtType == UiStyle::Invalid) + return; + + _listItemFormats[fmtType].merge(parseFormat(contents)); } + // Palette { ... } specifies the application palette // ColorGroups can be specified like pseudo states, chaining is OR (contrary to normal CSS handling): // Palette:inactive:disabled { ... } applies to both the Inactive and the Disabled state -void QssParser::parsePaletteBlock(const QString &decl, const QString &contents) { - QList colorGroups; - - // Check if we want to apply this palette definition for particular ColorGroups - QRegExp rx("Palette((:(normal|active|inactive|disabled))*)"); - if(!rx.exactMatch(decl)) { - qWarning() << Q_FUNC_INFO << tr("Invalid block declaration: %1").arg(decl); - return; - } - if(!rx.cap(1).isEmpty()) { - QStringList groups = rx.cap(1).split(':', QString::SkipEmptyParts); - foreach(QString g, groups) { - if((g == "normal" || g == "active") && !colorGroups.contains(QPalette::Active)) - colorGroups.append(QPalette::Active); - else if(g == "inactive" && !colorGroups.contains(QPalette::Inactive)) - colorGroups.append(QPalette::Inactive); - else if(g == "disabled" && !colorGroups.contains(QPalette::Disabled)) - colorGroups.append(QPalette::Disabled); - } - } - - // Now let's go through the roles - foreach(QString line, contents.split(';', QString::SkipEmptyParts)) { - int idx = line.indexOf(':'); - if(idx <= 0) { - qWarning() << Q_FUNC_INFO << tr("Invalid palette role assignment: %1").arg(line.trimmed()); - continue; - } - QString rolestr = line.left(idx).trimmed(); - QString brushstr = line.mid(idx + 1).trimmed(); - - if(_paletteColorRoles.contains(rolestr)) { - QBrush brush = parseBrush(brushstr); - if(colorGroups.count()) { - foreach(QPalette::ColorGroup group, colorGroups) - _palette.setBrush(group, _paletteColorRoles.value(rolestr), brush); - } else - _palette.setBrush(_paletteColorRoles.value(rolestr), brush); - } else if(_uiStyleColorRoles.contains(rolestr)) { - _uiStylePalette[_uiStyleColorRoles.value(rolestr)] = parseBrush(brushstr); - } else - qWarning() << Q_FUNC_INFO << tr("Unknown palette role name: %1").arg(rolestr); - } +void QssParser::parsePaletteBlock(const QString &decl, const QString &contents) +{ + QList colorGroups; + + // Check if we want to apply this palette definition for particular ColorGroups + QRegExp rx("Palette((:(normal|active|inactive|disabled))*)"); + if (!rx.exactMatch(decl)) { + qWarning() << Q_FUNC_INFO << tr("Invalid block declaration: %1").arg(decl); + return; + } + if (!rx.cap(1).isEmpty()) { + QStringList groups = rx.cap(1).split(':', QString::SkipEmptyParts); + foreach(QString g, groups) { + if ((g == "normal" || g == "active") && !colorGroups.contains(QPalette::Active)) + colorGroups.append(QPalette::Active); + else if (g == "inactive" && !colorGroups.contains(QPalette::Inactive)) + colorGroups.append(QPalette::Inactive); + else if (g == "disabled" && !colorGroups.contains(QPalette::Disabled)) + colorGroups.append(QPalette::Disabled); + } + } + + // Now let's go through the roles + foreach(QString line, contents.split(';', QString::SkipEmptyParts)) { + int idx = line.indexOf(':'); + if (idx <= 0) { + qWarning() << Q_FUNC_INFO << tr("Invalid palette role assignment: %1").arg(line.trimmed()); + continue; + } + QString rolestr = line.left(idx).trimmed(); + QString brushstr = line.mid(idx + 1).trimmed(); + + if (_paletteColorRoles.contains(rolestr)) { + QBrush brush = parseBrush(brushstr); + if (colorGroups.count()) { + foreach(QPalette::ColorGroup group, colorGroups) + _palette.setBrush(group, _paletteColorRoles.value(rolestr), brush); + } + else + _palette.setBrush(_paletteColorRoles.value(rolestr), brush); + } + else if (_uiStyleColorRoles.contains(rolestr)) { + _uiStylePalette[_uiStyleColorRoles.value(rolestr)] = parseBrush(brushstr); + } + else + qWarning() << Q_FUNC_INFO << tr("Unknown palette role name: %1").arg(rolestr); + } } + /******** Determine format types from a block declaration ********/ -quint64 QssParser::parseFormatType(const QString &decl) { - QRegExp rx("ChatLine(?:::(\\w+))?(?:#([\\w\\-]+))?(?:\\[([=-,\\\"\\w\\s]+)\\])?"); - // $1: subelement; $2: msgtype; $3: conditionals - if(!rx.exactMatch(decl)) { - qWarning() << Q_FUNC_INFO << tr("Invalid block declaration: %1").arg(decl); - return UiStyle::Invalid; - } - QString subElement = rx.cap(1); - QString msgType = rx.cap(2); - QString conditions = rx.cap(3); - - quint64 fmtType = 0; - - // First determine the subelement - if(!subElement.isEmpty()) { - if(subElement == "timestamp") - fmtType |= UiStyle::Timestamp; - else if(subElement == "sender") - fmtType |= UiStyle::Sender; - else if(subElement == "nick") - fmtType |= UiStyle::Nick; - else if(subElement == "contents") - fmtType |= UiStyle::Contents; - else if(subElement == "hostmask") - fmtType |= UiStyle::Hostmask; - else if(subElement == "modeflags") - fmtType |= UiStyle::ModeFlags; - else if(subElement == "url") - fmtType |= UiStyle::Url; - else { - qWarning() << Q_FUNC_INFO << tr("Invalid subelement name in %1").arg(decl); - return UiStyle::Invalid; - } - } - - // Now, figure out the message type - if(!msgType.isEmpty()) { - if(msgType == "plain") - fmtType |= UiStyle::PlainMsg; - else if(msgType == "notice") - fmtType |= UiStyle::NoticeMsg; - else if(msgType == "action") - fmtType |= UiStyle::ActionMsg; - else if(msgType == "nick") - fmtType |= UiStyle::NickMsg; - else if(msgType == "mode") - fmtType |= UiStyle::ModeMsg; - else if(msgType == "join") - fmtType |= UiStyle::JoinMsg; - else if(msgType == "part") - fmtType |= UiStyle::PartMsg; - else if(msgType == "quit") - fmtType |= UiStyle::QuitMsg; - else if(msgType == "kick") - fmtType |= UiStyle::KickMsg; - else if(msgType == "kill") - fmtType |= UiStyle::KillMsg; - else if(msgType == "server") - fmtType |= UiStyle::ServerMsg; - else if(msgType == "info") - fmtType |= UiStyle::InfoMsg; - else if(msgType == "error") - fmtType |= UiStyle::ErrorMsg; - else if(msgType == "daychange") - fmtType |= UiStyle::DayChangeMsg; - else if(msgType == "topic") - fmtType |= UiStyle::TopicMsg; - else if(msgType == "netsplit-join") - fmtType |= UiStyle::NetsplitJoinMsg; - else if(msgType == "netsplit-quit") - fmtType |= UiStyle::NetsplitQuitMsg; - else if(msgType == "invite") - fmtType |= UiStyle::InviteMsg; - else { - qWarning() << Q_FUNC_INFO << tr("Invalid message type in %1").arg(decl); +quint64 QssParser::parseFormatType(const QString &decl) +{ + QRegExp rx("ChatLine(?:::(\\w+))?(?:#([\\w\\-]+))?(?:\\[([=-,\\\"\\w\\s]+)\\])?"); + // $1: subelement; $2: msgtype; $3: conditionals + if (!rx.exactMatch(decl)) { + qWarning() << Q_FUNC_INFO << tr("Invalid block declaration: %1").arg(decl); + return UiStyle::Invalid; + } + QString subElement = rx.cap(1); + QString msgType = rx.cap(2); + QString conditions = rx.cap(3); + + quint64 fmtType = 0; + + // First determine the subelement + if (!subElement.isEmpty()) { + if (subElement == "timestamp") + fmtType |= UiStyle::Timestamp; + else if (subElement == "sender") + fmtType |= UiStyle::Sender; + else if (subElement == "nick") + fmtType |= UiStyle::Nick; + else if (subElement == "contents") + fmtType |= UiStyle::Contents; + else if (subElement == "hostmask") + fmtType |= UiStyle::Hostmask; + else if (subElement == "modeflags") + fmtType |= UiStyle::ModeFlags; + else if (subElement == "url") + fmtType |= UiStyle::Url; + else { + qWarning() << Q_FUNC_INFO << tr("Invalid subelement name in %1").arg(decl); + return UiStyle::Invalid; + } } - } - // Next up: conditional (formats, labels, nickhash) - QRegExp condRx("\\s*([\\w\\-]+)\\s*=\\s*\"(\\w+)\"\\s*"); - if(!conditions.isEmpty()) { - foreach(const QString &cond, conditions.split(',', QString::SkipEmptyParts)) { - if(!condRx.exactMatch(cond)) { - qWarning() << Q_FUNC_INFO << tr("Invalid condition %1").arg(cond); - return UiStyle::Invalid; - } - QString condName = condRx.cap(1); - QString condValue = condRx.cap(2); - if(condName == "label") { - quint64 labeltype = 0; - if(condValue == "highlight") - labeltype = UiStyle::Highlight; - else if(condValue == "selected") - labeltype = UiStyle::Selected; + // Now, figure out the message type + if (!msgType.isEmpty()) { + if (msgType == "plain") + fmtType |= UiStyle::PlainMsg; + else if (msgType == "notice") + fmtType |= UiStyle::NoticeMsg; + else if (msgType == "action") + fmtType |= UiStyle::ActionMsg; + else if (msgType == "nick") + fmtType |= UiStyle::NickMsg; + else if (msgType == "mode") + fmtType |= UiStyle::ModeMsg; + else if (msgType == "join") + fmtType |= UiStyle::JoinMsg; + else if (msgType == "part") + fmtType |= UiStyle::PartMsg; + else if (msgType == "quit") + fmtType |= UiStyle::QuitMsg; + else if (msgType == "kick") + fmtType |= UiStyle::KickMsg; + else if (msgType == "kill") + fmtType |= UiStyle::KillMsg; + else if (msgType == "server") + fmtType |= UiStyle::ServerMsg; + else if (msgType == "info") + fmtType |= UiStyle::InfoMsg; + else if (msgType == "error") + fmtType |= UiStyle::ErrorMsg; + else if (msgType == "daychange") + fmtType |= UiStyle::DayChangeMsg; + else if (msgType == "topic") + fmtType |= UiStyle::TopicMsg; + else if (msgType == "netsplit-join") + fmtType |= UiStyle::NetsplitJoinMsg; + else if (msgType == "netsplit-quit") + fmtType |= UiStyle::NetsplitQuitMsg; + else if (msgType == "invite") + fmtType |= UiStyle::InviteMsg; else { - qWarning() << Q_FUNC_INFO << tr("Invalid message label: %1").arg(condValue); - return UiStyle::Invalid; + qWarning() << Q_FUNC_INFO << tr("Invalid message type in %1").arg(decl); } - fmtType |= (labeltype << 32); - } else if(condName == "sender") { - if(condValue == "self") - fmtType |= (quint64)UiStyle::OwnMsg << 32; // sender="self" is actually treated as a label - else { - bool ok = true; - quint64 val = condValue.toUInt(&ok, 16); - if(!ok) { - qWarning() << Q_FUNC_INFO << tr("Invalid senderhash specification: %1").arg(condValue); - return UiStyle::Invalid; + } + + // Next up: conditional (formats, labels, nickhash) + QRegExp condRx("\\s*([\\w\\-]+)\\s*=\\s*\"(\\w+)\"\\s*"); + if (!conditions.isEmpty()) { + foreach(const QString &cond, conditions.split(',', QString::SkipEmptyParts)) { + if (!condRx.exactMatch(cond)) { + qWarning() << Q_FUNC_INFO << tr("Invalid condition %1").arg(cond); + return UiStyle::Invalid; } - if(val >= 16) { - qWarning() << Q_FUNC_INFO << tr("Senderhash can be at most \"0x0f\"!"); - return UiStyle::Invalid; + QString condName = condRx.cap(1); + QString condValue = condRx.cap(2); + if (condName == "label") { + quint64 labeltype = 0; + if (condValue == "highlight") + labeltype = UiStyle::Highlight; + else if (condValue == "selected") + labeltype = UiStyle::Selected; + else { + qWarning() << Q_FUNC_INFO << tr("Invalid message label: %1").arg(condValue); + return UiStyle::Invalid; + } + fmtType |= (labeltype << 32); + } + else if (condName == "sender") { + if (condValue == "self") + fmtType |= (quint64) UiStyle::OwnMsg << 32; // sender="self" is actually treated as a label + else { + bool ok = true; + quint64 val = condValue.toUInt(&ok, 16); + if (!ok) { + qWarning() << Q_FUNC_INFO << tr("Invalid senderhash specification: %1").arg(condValue); + return UiStyle::Invalid; + } + if (val >= 16) { + qWarning() << Q_FUNC_INFO << tr("Senderhash can be at most \"0x0f\"!"); + return UiStyle::Invalid; + } + fmtType |= ++val << 48; + } + } + else if (condName == "format") { + if (condValue == "bold") + fmtType |= UiStyle::Bold; + else if (condValue == "italic") + fmtType |= UiStyle::Italic; + else if (condValue == "underline") + fmtType |= UiStyle::Underline; + else if (condValue == "reverse") + fmtType |= UiStyle::Reverse; + else { + qWarning() << Q_FUNC_INFO << tr("Invalid format name: %1").arg(condValue); + return UiStyle::Invalid; + } + } + else if (condName == "fg-color" || condName == "bg-color") { + bool ok; + quint8 col = condValue.toUInt(&ok, 16); + if (!ok || col > 0x0f) { + qWarning() << Q_FUNC_INFO << tr("Illegal IRC color specification (must be between 00 and 0f): %1").arg(condValue); + return UiStyle::Invalid; + } + if (condName == "fg-color") + fmtType |= 0x00400000 | (quint32)(col << 24); + else + fmtType |= 0x00800000 | (quint32)(col << 28); + } + else { + qWarning() << Q_FUNC_INFO << tr("Unhandled condition: %1").arg(condName); + return UiStyle::Invalid; } - fmtType |= ++val << 48; - } - } else if(condName == "format") { - if(condValue == "bold") - fmtType |= UiStyle::Bold; - else if(condValue == "italic") - fmtType |= UiStyle::Italic; - else if(condValue == "underline") - fmtType |= UiStyle::Underline; - else if(condValue == "reverse") - fmtType |= UiStyle::Reverse; - else { - qWarning() << Q_FUNC_INFO << tr("Invalid format name: %1").arg(condValue); - return UiStyle::Invalid; - } - } else if(condName == "fg-color" || condName == "bg-color") { - bool ok; - quint8 col = condValue.toUInt(&ok, 16); - if(!ok || col > 0x0f) { - qWarning() << Q_FUNC_INFO << tr("Illegal IRC color specification (must be between 00 and 0f): %1").arg(condValue); - return UiStyle::Invalid; } - if(condName == "fg-color") - fmtType |= 0x00400000 | (quint32)(col << 24); - else - fmtType |= 0x00800000 | (quint32)(col << 28); - } else { - qWarning() << Q_FUNC_INFO << tr("Unhandled condition: %1").arg(condName); - return UiStyle::Invalid; - } } - } - return fmtType; + return fmtType; } + // FIXME: Code duplication -quint32 QssParser::parseItemFormatType(const QString &decl) { - QRegExp rx("(Chat|Nick)ListItem(?:\\[([=-,\\\"\\w\\s]+)\\])?"); - // $1: item type; $2: properties - if(!rx.exactMatch(decl)) { - qWarning() << Q_FUNC_INFO << tr("Invalid block declaration: %1").arg(decl); - return UiStyle::Invalid; - } - QString mainItemType = rx.cap(1); - QString properties = rx.cap(2); - - quint32 fmtType = 0; - - // Next up: properties - QString type, state; - if(!properties.isEmpty()) { - QHash props; - QRegExp propRx("\\s*([\\w\\-]+)\\s*=\\s*\"([\\w\\-]+)\"\\s*"); - foreach(const QString &prop, properties.split(',', QString::SkipEmptyParts)) { - if(!propRx.exactMatch(prop)) { - qWarning() << Q_FUNC_INFO << tr("Invalid proplist %1").arg(prop); - return UiStyle::Invalid; - } - props[propRx.cap(1)] = propRx.cap(2); - } - type = props.value("type"); - state = props.value("state"); - } - - if(mainItemType == "Chat") { - fmtType |= UiStyle::BufferViewItem; - if(!type.isEmpty()) { - if(type == "network") - fmtType |= UiStyle::NetworkItem; - else if(type == "channel") - fmtType |= UiStyle::ChannelBufferItem; - else if(type == "query") - fmtType |= UiStyle::QueryBufferItem; - else { - qWarning() << Q_FUNC_INFO << tr("Invalid chatlist item type %1").arg(type); - return UiStyle::Invalid; - } - } - if(!state.isEmpty()) { - if(state == "inactive") - fmtType |= UiStyle::InactiveBuffer; - else if(state == "channel-event") - fmtType |= UiStyle::ActiveBuffer; - else if(state == "unread-message") - fmtType |= UiStyle::UnreadBuffer; - else if(state == "highlighted") - fmtType |= UiStyle::HighlightedBuffer; - else if(state == "away") - fmtType |= UiStyle::UserAway; - else { - qWarning() << Q_FUNC_INFO << tr("Invalid chatlist state %1").arg(state); +quint32 QssParser::parseItemFormatType(const QString &decl) +{ + QRegExp rx("(Chat|Nick)ListItem(?:\\[([=-,\\\"\\w\\s]+)\\])?"); + // $1: item type; $2: properties + if (!rx.exactMatch(decl)) { + qWarning() << Q_FUNC_INFO << tr("Invalid block declaration: %1").arg(decl); return UiStyle::Invalid; - } - } - } else { // NickList - fmtType |= UiStyle::NickViewItem; - if(!type.isEmpty()) { - if(type == "user") { - fmtType |= UiStyle::IrcUserItem; - if(state == "away") - fmtType |= UiStyle::UserAway; - } else if(type == "category") - fmtType |= UiStyle::UserCategoryItem; - } - } - return fmtType; + } + QString mainItemType = rx.cap(1); + QString properties = rx.cap(2); + + quint32 fmtType = 0; + + // Next up: properties + QString type, state; + if (!properties.isEmpty()) { + QHash props; + QRegExp propRx("\\s*([\\w\\-]+)\\s*=\\s*\"([\\w\\-]+)\"\\s*"); + foreach(const QString &prop, properties.split(',', QString::SkipEmptyParts)) { + if (!propRx.exactMatch(prop)) { + qWarning() << Q_FUNC_INFO << tr("Invalid proplist %1").arg(prop); + return UiStyle::Invalid; + } + props[propRx.cap(1)] = propRx.cap(2); + } + type = props.value("type"); + state = props.value("state"); + } + + if (mainItemType == "Chat") { + fmtType |= UiStyle::BufferViewItem; + if (!type.isEmpty()) { + if (type == "network") + fmtType |= UiStyle::NetworkItem; + else if (type == "channel") + fmtType |= UiStyle::ChannelBufferItem; + else if (type == "query") + fmtType |= UiStyle::QueryBufferItem; + else { + qWarning() << Q_FUNC_INFO << tr("Invalid chatlist item type %1").arg(type); + return UiStyle::Invalid; + } + } + if (!state.isEmpty()) { + if (state == "inactive") + fmtType |= UiStyle::InactiveBuffer; + else if (state == "channel-event") + fmtType |= UiStyle::ActiveBuffer; + else if (state == "unread-message") + fmtType |= UiStyle::UnreadBuffer; + else if (state == "highlighted") + fmtType |= UiStyle::HighlightedBuffer; + else if (state == "away") + fmtType |= UiStyle::UserAway; + else { + qWarning() << Q_FUNC_INFO << tr("Invalid chatlist state %1").arg(state); + return UiStyle::Invalid; + } + } + } + else { // NickList + fmtType |= UiStyle::NickViewItem; + if (!type.isEmpty()) { + if (type == "user") { + fmtType |= UiStyle::IrcUserItem; + if (state == "away") + fmtType |= UiStyle::UserAway; + } + else if (type == "category") + fmtType |= UiStyle::UserCategoryItem; + } + } + return fmtType; } + /******** Parse a whole format attribute block ********/ -QTextCharFormat QssParser::parseFormat(const QString &qss) { - QTextCharFormat format; - - foreach(QString line, qss.split(';', QString::SkipEmptyParts)) { - int idx = line.indexOf(':'); - if(idx <= 0) { - qWarning() << Q_FUNC_INFO << tr("Invalid property declaration: %1").arg(line.trimmed()); - continue; - } - QString property = line.left(idx).trimmed(); - QString value = line.mid(idx + 1).simplified(); - - if(property == "background" || property == "background-color") - format.setBackground(parseBrush(value)); - else if(property == "foreground" || property == "color") - format.setForeground(parseBrush(value)); - - // font-related properties - else if(property.startsWith("font")) { - if(property == "font") - parseFont(value, &format); - else if(property == "font-style") - parseFontStyle(value, &format); - else if(property == "font-weight") - parseFontWeight(value, &format); - else if(property == "font-size") - parseFontSize(value, &format); - else if(property == "font-family") - parseFontFamily(value, &format); - else { - qWarning() << Q_FUNC_INFO << tr("Invalid font property: %1").arg(line); - continue; - } - } +QTextCharFormat QssParser::parseFormat(const QString &qss) +{ + QTextCharFormat format; - else { - qWarning() << Q_FUNC_INFO << tr("Unknown ChatLine property: %1").arg(property); + foreach(QString line, qss.split(';', QString::SkipEmptyParts)) { + int idx = line.indexOf(':'); + if (idx <= 0) { + qWarning() << Q_FUNC_INFO << tr("Invalid property declaration: %1").arg(line.trimmed()); + continue; + } + QString property = line.left(idx).trimmed(); + QString value = line.mid(idx + 1).simplified(); + + if (property == "background" || property == "background-color") + format.setBackground(parseBrush(value)); + else if (property == "foreground" || property == "color") + format.setForeground(parseBrush(value)); + + // font-related properties + else if (property.startsWith("font")) { + if (property == "font") + parseFont(value, &format); + else if (property == "font-style") + parseFontStyle(value, &format); + else if (property == "font-weight") + parseFontWeight(value, &format); + else if (property == "font-size") + parseFontSize(value, &format); + else if (property == "font-family") + parseFontFamily(value, &format); + else { + qWarning() << Q_FUNC_INFO << tr("Invalid font property: %1").arg(line); + continue; + } + } + + else { + qWarning() << Q_FUNC_INFO << tr("Unknown ChatLine property: %1").arg(property); + } } - } - return format; + return format; } + /******** Brush ********/ -QBrush QssParser::parseBrush(const QString &str, bool *ok) { - if(ok) - *ok = false; - QColor c = parseColor(str); - if(c.isValid()) { - if(ok) - *ok = true; - return QBrush(c); - } - - if(str.startsWith("palette")) { // Palette color role - QRegExp rx("palette\\s*\\(\\s*([a-z-]+)\\s*\\)"); - if(!rx.exactMatch(str)) { - qWarning() << Q_FUNC_INFO << tr("Invalid palette color role specification: %1").arg(str); - return QBrush(); - } - if(_paletteColorRoles.contains(rx.cap(1))) - return QBrush(_palette.brush(_paletteColorRoles.value(rx.cap(1)))); - if(_uiStyleColorRoles.contains(rx.cap(1))) - return QBrush(_uiStylePalette.at(_uiStyleColorRoles.value(rx.cap(1)))); - qWarning() << Q_FUNC_INFO << tr("Unknown palette color role: %1").arg(rx.cap(1)); - return QBrush(); +QBrush QssParser::parseBrush(const QString &str, bool *ok) +{ + if (ok) + *ok = false; + QColor c = parseColor(str); + if (c.isValid()) { + if (ok) + *ok = true; + return QBrush(c); + } - } else if(str.startsWith("qlineargradient")) { - static QString rxFloat("\\s*(-?\\s*[0-9]*\\.?[0-9]+)\\s*"); - QRegExp rx(QString("qlineargradient\\s*\\(\\s*x1:%1,\\s*y1:%1,\\s*x2:%1,\\s*y2:%1,(.+)\\)").arg(rxFloat)); - if(!rx.exactMatch(str)) { - qWarning() << Q_FUNC_INFO << tr("Invalid gradient declaration: %1").arg(str); - return QBrush(); - } - qreal x1 = rx.cap(1).toDouble(); - qreal y1 = rx.cap(2).toDouble(); - qreal x2 = rx.cap(3).toDouble(); - qreal y2 = rx.cap(4).toDouble(); - QGradientStops stops = parseGradientStops(rx.cap(5).trimmed()); - if(!stops.count()) { - qWarning() << Q_FUNC_INFO << tr("Invalid gradient stops list: %1").arg(str); - return QBrush(); - } - QLinearGradient gradient(x1, y1, x2, y2); - gradient.setCoordinateMode(QGradient::ObjectBoundingMode); - gradient.setStops(stops); - if(ok) - *ok = true; - return QBrush(gradient); - - } else if(str.startsWith("qconicalgradient")) { - static QString rxFloat("\\s*(-?\\s*[0-9]*\\.?[0-9]+)\\s*"); - QRegExp rx(QString("qconicalgradient\\s*\\(\\s*cx:%1,\\s*cy:%1,\\s*angle:%1,(.+)\\)").arg(rxFloat)); - if(!rx.exactMatch(str)) { - qWarning() << Q_FUNC_INFO << tr("Invalid gradient declaration: %1").arg(str); - return QBrush(); - } - qreal cx = rx.cap(1).toDouble(); - qreal cy = rx.cap(2).toDouble(); - qreal angle = rx.cap(3).toDouble(); - QGradientStops stops = parseGradientStops(rx.cap(4).trimmed()); - if(!stops.count()) { - qWarning() << Q_FUNC_INFO << tr("Invalid gradient stops list: %1").arg(str); - return QBrush(); - } - QConicalGradient gradient(cx, cy, angle); - gradient.setCoordinateMode(QGradient::ObjectBoundingMode); - gradient.setStops(stops); - if(ok) - *ok = true; - return QBrush(gradient); - - } else if(str.startsWith("qradialgradient")) { - static QString rxFloat("\\s*(-?\\s*[0-9]*\\.?[0-9]+)\\s*"); - QRegExp rx(QString("qradialgradient\\s*\\(\\s*cx:%1,\\s*cy:%1,\\s*radius:%1,\\s*fx:%1,\\s*fy:%1,(.+)\\)").arg(rxFloat)); - if(!rx.exactMatch(str)) { - qWarning() << Q_FUNC_INFO << tr("Invalid gradient declaration: %1").arg(str); - return QBrush(); - } - qreal cx = rx.cap(1).toDouble(); - qreal cy = rx.cap(2).toDouble(); - qreal radius = rx.cap(3).toDouble(); - qreal fx = rx.cap(4).toDouble(); - qreal fy = rx.cap(5).toDouble(); - QGradientStops stops = parseGradientStops(rx.cap(6).trimmed()); - if(!stops.count()) { - qWarning() << Q_FUNC_INFO << tr("Invalid gradient stops list: %1").arg(str); - return QBrush(); - } - QRadialGradient gradient(cx, cy, radius, fx, fy); - gradient.setCoordinateMode(QGradient::ObjectBoundingMode); - gradient.setStops(stops); - if(ok) - *ok = true; - return QBrush(gradient); - } - - return QBrush(); + if (str.startsWith("palette")) { // Palette color role + QRegExp rx("palette\\s*\\(\\s*([a-z-]+)\\s*\\)"); + if (!rx.exactMatch(str)) { + qWarning() << Q_FUNC_INFO << tr("Invalid palette color role specification: %1").arg(str); + return QBrush(); + } + if (_paletteColorRoles.contains(rx.cap(1))) + return QBrush(_palette.brush(_paletteColorRoles.value(rx.cap(1)))); + if (_uiStyleColorRoles.contains(rx.cap(1))) + return QBrush(_uiStylePalette.at(_uiStyleColorRoles.value(rx.cap(1)))); + qWarning() << Q_FUNC_INFO << tr("Unknown palette color role: %1").arg(rx.cap(1)); + return QBrush(); + } + else if (str.startsWith("qlineargradient")) { + static QString rxFloat("\\s*(-?\\s*[0-9]*\\.?[0-9]+)\\s*"); + QRegExp rx(QString("qlineargradient\\s*\\(\\s*x1:%1,\\s*y1:%1,\\s*x2:%1,\\s*y2:%1,(.+)\\)").arg(rxFloat)); + if (!rx.exactMatch(str)) { + qWarning() << Q_FUNC_INFO << tr("Invalid gradient declaration: %1").arg(str); + return QBrush(); + } + qreal x1 = rx.cap(1).toDouble(); + qreal y1 = rx.cap(2).toDouble(); + qreal x2 = rx.cap(3).toDouble(); + qreal y2 = rx.cap(4).toDouble(); + QGradientStops stops = parseGradientStops(rx.cap(5).trimmed()); + if (!stops.count()) { + qWarning() << Q_FUNC_INFO << tr("Invalid gradient stops list: %1").arg(str); + return QBrush(); + } + QLinearGradient gradient(x1, y1, x2, y2); + gradient.setCoordinateMode(QGradient::ObjectBoundingMode); + gradient.setStops(stops); + if (ok) + *ok = true; + return QBrush(gradient); + } + else if (str.startsWith("qconicalgradient")) { + static QString rxFloat("\\s*(-?\\s*[0-9]*\\.?[0-9]+)\\s*"); + QRegExp rx(QString("qconicalgradient\\s*\\(\\s*cx:%1,\\s*cy:%1,\\s*angle:%1,(.+)\\)").arg(rxFloat)); + if (!rx.exactMatch(str)) { + qWarning() << Q_FUNC_INFO << tr("Invalid gradient declaration: %1").arg(str); + return QBrush(); + } + qreal cx = rx.cap(1).toDouble(); + qreal cy = rx.cap(2).toDouble(); + qreal angle = rx.cap(3).toDouble(); + QGradientStops stops = parseGradientStops(rx.cap(4).trimmed()); + if (!stops.count()) { + qWarning() << Q_FUNC_INFO << tr("Invalid gradient stops list: %1").arg(str); + return QBrush(); + } + QConicalGradient gradient(cx, cy, angle); + gradient.setCoordinateMode(QGradient::ObjectBoundingMode); + gradient.setStops(stops); + if (ok) + *ok = true; + return QBrush(gradient); + } + else if (str.startsWith("qradialgradient")) { + static QString rxFloat("\\s*(-?\\s*[0-9]*\\.?[0-9]+)\\s*"); + QRegExp rx(QString("qradialgradient\\s*\\(\\s*cx:%1,\\s*cy:%1,\\s*radius:%1,\\s*fx:%1,\\s*fy:%1,(.+)\\)").arg(rxFloat)); + if (!rx.exactMatch(str)) { + qWarning() << Q_FUNC_INFO << tr("Invalid gradient declaration: %1").arg(str); + return QBrush(); + } + qreal cx = rx.cap(1).toDouble(); + qreal cy = rx.cap(2).toDouble(); + qreal radius = rx.cap(3).toDouble(); + qreal fx = rx.cap(4).toDouble(); + qreal fy = rx.cap(5).toDouble(); + QGradientStops stops = parseGradientStops(rx.cap(6).trimmed()); + if (!stops.count()) { + qWarning() << Q_FUNC_INFO << tr("Invalid gradient stops list: %1").arg(str); + return QBrush(); + } + QRadialGradient gradient(cx, cy, radius, fx, fy); + gradient.setCoordinateMode(QGradient::ObjectBoundingMode); + gradient.setStops(stops); + if (ok) + *ok = true; + return QBrush(gradient); + } + + return QBrush(); } -QColor QssParser::parseColor(const QString &str) { - if(str.startsWith("rgba")) { - ColorTuple tuple = parseColorTuple(str.mid(4)); - if(tuple.count() == 4) - return QColor(tuple.at(0), tuple.at(1), tuple.at(2), tuple.at(3)); - } else if(str.startsWith("rgb")) { - ColorTuple tuple = parseColorTuple(str.mid(3)); - if(tuple.count() == 3) - return QColor(tuple.at(0), tuple.at(1), tuple.at(2)); - } else if(str.startsWith("hsva")) { - ColorTuple tuple = parseColorTuple(str.mid(4)); - if(tuple.count() == 4) { - QColor c; - c.setHsvF(tuple.at(0), tuple.at(1), tuple.at(2), tuple.at(3)); - return c; - } - } else if(str.startsWith("hsv")) { - ColorTuple tuple = parseColorTuple(str.mid(3)); - if(tuple.count() == 3) { - QColor c; - c.setHsvF(tuple.at(0), tuple.at(1), tuple.at(2)); - return c; - } - } else { - QRegExp rx("#?[0-9A-Fa-z]+"); - if(rx.exactMatch(str)) - return QColor(str); - } - return QColor(); + +QColor QssParser::parseColor(const QString &str) +{ + if (str.startsWith("rgba")) { + ColorTuple tuple = parseColorTuple(str.mid(4)); + if (tuple.count() == 4) + return QColor(tuple.at(0), tuple.at(1), tuple.at(2), tuple.at(3)); + } + else if (str.startsWith("rgb")) { + ColorTuple tuple = parseColorTuple(str.mid(3)); + if (tuple.count() == 3) + return QColor(tuple.at(0), tuple.at(1), tuple.at(2)); + } + else if (str.startsWith("hsva")) { + ColorTuple tuple = parseColorTuple(str.mid(4)); + if (tuple.count() == 4) { + QColor c; + c.setHsvF(tuple.at(0), tuple.at(1), tuple.at(2), tuple.at(3)); + return c; + } + } + else if (str.startsWith("hsv")) { + ColorTuple tuple = parseColorTuple(str.mid(3)); + if (tuple.count() == 3) { + QColor c; + c.setHsvF(tuple.at(0), tuple.at(1), tuple.at(2)); + return c; + } + } + else { + QRegExp rx("#?[0-9A-Fa-z]+"); + if (rx.exactMatch(str)) + return QColor(str); + } + return QColor(); } + // get a list of comma-separated int values or percentages (rel to 0-255) -QssParser::ColorTuple QssParser::parseColorTuple(const QString &str) { - ColorTuple result; - QRegExp rx("\\(((\\s*[0-9]{1,3}%?\\s*)(,\\s*[0-9]{1,3}%?\\s*)*)\\)"); - if(!rx.exactMatch(str.trimmed())) { - return ColorTuple(); - } - QStringList values = rx.cap(1).split(','); - foreach(QString v, values) { - qreal val; - bool perc = false; - bool ok; - v = v.trimmed(); - if(v.endsWith('%')) { - perc = true; - v.chop(1); - } - val = (qreal)v.toUInt(&ok); - if(!ok) - return ColorTuple(); - if(perc) - val = 255 * val/100; - result.append(val); - } - return result; +QssParser::ColorTuple QssParser::parseColorTuple(const QString &str) +{ + ColorTuple result; + QRegExp rx("\\(((\\s*[0-9]{1,3}%?\\s*)(,\\s*[0-9]{1,3}%?\\s*)*)\\)"); + if (!rx.exactMatch(str.trimmed())) { + return ColorTuple(); + } + QStringList values = rx.cap(1).split(','); + foreach(QString v, values) { + qreal val; + bool perc = false; + bool ok; + v = v.trimmed(); + if (v.endsWith('%')) { + perc = true; + v.chop(1); + } + val = (qreal)v.toUInt(&ok); + if (!ok) + return ColorTuple(); + if (perc) + val = 255 * val/100; + result.append(val); + } + return result; } -QGradientStops QssParser::parseGradientStops(const QString &str_) { - QString str = str_; - QGradientStops result; - static QString rxFloat("(0?\\.[0-9]+|[01])"); // values between 0 and 1 - QRegExp rx(QString("\\s*,?\\s*stop:\\s*(%1)\\s+([^:]+)(,\\s*stop:|$)").arg(rxFloat)); - int idx; - while((idx = rx.indexIn(str)) == 0) { - qreal x = rx.cap(1).toDouble(); - QColor c = parseColor(rx.cap(3)); - if(!c.isValid()) - return QGradientStops(); - result << QGradientStop(x, c); - str.remove(0, rx.matchedLength() - rx.cap(4).length()); - } - if(!str.trimmed().isEmpty()) - return QGradientStops(); - - return result; + +QGradientStops QssParser::parseGradientStops(const QString &str_) +{ + QString str = str_; + QGradientStops result; + static QString rxFloat("(0?\\.[0-9]+|[01])"); // values between 0 and 1 + QRegExp rx(QString("\\s*,?\\s*stop:\\s*(%1)\\s+([^:]+)(,\\s*stop:|$)").arg(rxFloat)); + int idx; + while ((idx = rx.indexIn(str)) == 0) { + qreal x = rx.cap(1).toDouble(); + QColor c = parseColor(rx.cap(3)); + if (!c.isValid()) + return QGradientStops(); + result << QGradientStop(x, c); + str.remove(0, rx.matchedLength() - rx.cap(4).length()); + } + if (!str.trimmed().isEmpty()) + return QGradientStops(); + + return result; } + /******** Font Properties ********/ -void QssParser::parseFont(const QString& value, QTextCharFormat* format) { - QRegExp rx("((?:(?:normal|italic|oblique|underline|bold|100|200|300|400|500|600|700|800|900) ){0,2}) ?(\\d+)(pt|px)? \"(.*)\""); - if(!rx.exactMatch(value)) { - qWarning() << Q_FUNC_INFO << tr("Invalid font specification: %1").arg(value); - return; - } - format->setFontItalic(false); - format->setFontWeight(QFont::Normal); - QStringList proplist = rx.cap(1).split(' ', QString::SkipEmptyParts); - foreach(QString prop, proplist) { - if(prop == "italic") - format->setFontItalic(true); - else if(prop == "underline") - format->setFontUnderline(true); - //else if(prop == "oblique") - // format->setStyle(QFont::StyleOblique); - else if(prop == "bold") - format->setFontWeight(QFont::Bold); - else { // number - int w = prop.toInt(); - format->setFontWeight(qMin(w / 8, 99)); // taken from Qt's qss parser +void QssParser::parseFont(const QString &value, QTextCharFormat *format) +{ + QRegExp rx("((?:(?:normal|italic|oblique|underline|bold|100|200|300|400|500|600|700|800|900) ){0,2}) ?(\\d+)(pt|px)? \"(.*)\""); + if (!rx.exactMatch(value)) { + qWarning() << Q_FUNC_INFO << tr("Invalid font specification: %1").arg(value); + return; + } + format->setFontItalic(false); + format->setFontWeight(QFont::Normal); + QStringList proplist = rx.cap(1).split(' ', QString::SkipEmptyParts); + foreach(QString prop, proplist) { + if (prop == "italic") + format->setFontItalic(true); + else if (prop == "underline") + format->setFontUnderline(true); + //else if(prop == "oblique") + // format->setStyle(QFont::StyleOblique); + else if (prop == "bold") + format->setFontWeight(QFont::Bold); + else { // number + int w = prop.toInt(); + format->setFontWeight(qMin(w / 8, 99)); // taken from Qt's qss parser + } } - } - if(rx.cap(3) == "px") - format->setProperty(QTextFormat::FontPixelSize, rx.cap(2).toInt()); - else - format->setFontPointSize(rx.cap(2).toInt()); + if (rx.cap(3) == "px") + format->setProperty(QTextFormat::FontPixelSize, rx.cap(2).toInt()); + else + format->setFontPointSize(rx.cap(2).toInt()); - format->setFontFamily(rx.cap(4)); + format->setFontFamily(rx.cap(4)); } -void QssParser::parseFontStyle(const QString& value, QTextCharFormat* format) { - if(value == "normal") - format->setFontItalic(false); - else if(value == "italic") - format->setFontItalic(true); - else if(value == "underline") - format->setFontUnderline(true); - //else if(value == "oblique") - // format->setStyle(QFont::StyleOblique); - else { - qWarning() << Q_FUNC_INFO << tr("Invalid font style specification: %1").arg(value); - } + +void QssParser::parseFontStyle(const QString &value, QTextCharFormat *format) +{ + if (value == "normal") + format->setFontItalic(false); + else if (value == "italic") + format->setFontItalic(true); + else if (value == "underline") + format->setFontUnderline(true); + //else if(value == "oblique") + // format->setStyle(QFont::StyleOblique); + else { + qWarning() << Q_FUNC_INFO << tr("Invalid font style specification: %1").arg(value); + } } -void QssParser::parseFontWeight(const QString& value, QTextCharFormat* format) { - if(value == "normal") - format->setFontWeight(QFont::Normal); - else if(value == "bold") - format->setFontWeight(QFont::Bold); - else { - bool ok; - int w = value.toInt(&ok); - if(!ok) { - qWarning() << Q_FUNC_INFO << tr("Invalid font weight specification: %1").arg(value); - return; - } - format->setFontWeight(qMin(w / 8, 99)); // taken from Qt's qss parser - } + +void QssParser::parseFontWeight(const QString &value, QTextCharFormat *format) +{ + if (value == "normal") + format->setFontWeight(QFont::Normal); + else if (value == "bold") + format->setFontWeight(QFont::Bold); + else { + bool ok; + int w = value.toInt(&ok); + if (!ok) { + qWarning() << Q_FUNC_INFO << tr("Invalid font weight specification: %1").arg(value); + return; + } + format->setFontWeight(qMin(w / 8, 99)); // taken from Qt's qss parser + } } -void QssParser::parseFontSize(const QString& value, QTextCharFormat* format) { - QRegExp rx("(\\d+)(pt|px)"); - if(!rx.exactMatch(value)) { - qWarning() << Q_FUNC_INFO << tr("Invalid font size specification: %1").arg(value); - return; - } - if(rx.cap(2) == "px") - format->setProperty(QTextFormat::FontPixelSize, rx.cap(1).toInt()); - else - format->setFontPointSize(rx.cap(1).toInt()); + +void QssParser::parseFontSize(const QString &value, QTextCharFormat *format) +{ + QRegExp rx("(\\d+)(pt|px)"); + if (!rx.exactMatch(value)) { + qWarning() << Q_FUNC_INFO << tr("Invalid font size specification: %1").arg(value); + return; + } + if (rx.cap(2) == "px") + format->setProperty(QTextFormat::FontPixelSize, rx.cap(1).toInt()); + else + format->setFontPointSize(rx.cap(1).toInt()); } -void QssParser::parseFontFamily(const QString& value, QTextCharFormat* format) { - QString family = value; - if(family.startsWith('"') && family.endsWith('"')) { - family = family.mid(1, family.length() - 2); - } - format->setFontFamily(family); + +void QssParser::parseFontFamily(const QString &value, QTextCharFormat *format) +{ + QString family = value; + if (family.startsWith('"') && family.endsWith('"')) { + family = family.mid(1, family.length() - 2); + } + format->setFontFamily(family); } diff --git a/src/uisupport/qssparser.h b/src/uisupport/qssparser.h index f4501148..b7bb38ed 100644 --- a/src/uisupport/qssparser.h +++ b/src/uisupport/qssparser.h @@ -23,20 +23,21 @@ #include "uistyle.h" -class QssParser { - Q_DECLARE_TR_FUNCTIONS(QssParser) +class QssParser +{ + Q_DECLARE_TR_FUNCTIONS(QssParser) - public: +public: QssParser(); void processStyleSheet(QString &sheet); inline QPalette palette() const { return _palette; } inline QVector uiStylePalette() const { return _uiStylePalette; } - inline const QHash& formats() const { return _formats; } - inline const QHash& listItemFormats() const { return _listItemFormats; } + inline const QHash &formats() const { return _formats; } + inline const QHash &listItemFormats() const { return _listItemFormats; } - protected: +protected: typedef QList ColorTuple; void parseChatLineBlock(const QString &decl, const QString &contents); @@ -64,7 +65,7 @@ class QssParser { QHash _paletteColorRoles; QHash _uiStyleColorRoles; - private: +private: QPalette _palette; QVector _uiStylePalette; QHash _formats; @@ -72,4 +73,5 @@ class QssParser { int _maxSenderHash; }; + #endif diff --git a/src/uisupport/resizingstackedwidget.cpp b/src/uisupport/resizingstackedwidget.cpp index fe6ffd71..417e8cb7 100644 --- a/src/uisupport/resizingstackedwidget.cpp +++ b/src/uisupport/resizingstackedwidget.cpp @@ -22,17 +22,21 @@ ResizingStackedWidget::ResizingStackedWidget(QWidget *parent) : QStackedWidget(parent) { - connect(this, SIGNAL(currentChanged(int)), SLOT(indexChanged(int))); + connect(this, SIGNAL(currentChanged(int)), SLOT(indexChanged(int))); } -QSize ResizingStackedWidget::sizeHint() const { - QWidget *widget = currentWidget(); - if(!widget) - return QSize(); - return widget->sizeHint(); + +QSize ResizingStackedWidget::sizeHint() const +{ + QWidget *widget = currentWidget(); + if (!widget) + return QSize(); + return widget->sizeHint(); } -void ResizingStackedWidget::indexChanged(int index) { - Q_UNUSED(index) - updateGeometry(); + +void ResizingStackedWidget::indexChanged(int index) +{ + Q_UNUSED(index) + updateGeometry(); } diff --git a/src/uisupport/resizingstackedwidget.h b/src/uisupport/resizingstackedwidget.h index 37aa4465..8b22d0f5 100644 --- a/src/uisupport/resizingstackedwidget.h +++ b/src/uisupport/resizingstackedwidget.h @@ -23,16 +23,18 @@ #include -class ResizingStackedWidget : public QStackedWidget { - Q_OBJECT +class ResizingStackedWidget : public QStackedWidget +{ + Q_OBJECT public: - ResizingStackedWidget(QWidget *parent = 0); + ResizingStackedWidget(QWidget *parent = 0); - virtual QSize sizeHint() const; + virtual QSize sizeHint() const; private slots: - void indexChanged(int index); + void indexChanged(int index); }; + #endif // RESIZINGSTACKEDWIDGET_H_ diff --git a/src/uisupport/settingspage.cpp b/src/uisupport/settingspage.cpp index 78660f93..98f41233 100644 --- a/src/uisupport/settingspage.cpp +++ b/src/uisupport/settingspage.cpp @@ -28,7 +28,7 @@ #include "uisettings.h" SettingsPage::SettingsPage(const QString &category, const QString &title, QWidget *parent) - : QWidget(parent), + : QWidget(parent), _category(category), _title(title), _changed(false), @@ -36,181 +36,213 @@ SettingsPage::SettingsPage(const QString &category, const QString &title, QWidge { } -void SettingsPage::setChangedState(bool hasChanged_) { - if(hasChanged_ != _changed) { - bool old = hasChanged(); - _changed = hasChanged_; - if(hasChanged() != old) - emit changed(hasChanged()); - } + +void SettingsPage::setChangedState(bool hasChanged_) +{ + if (hasChanged_ != _changed) { + bool old = hasChanged(); + _changed = hasChanged_; + if (hasChanged() != old) + emit changed(hasChanged()); + } } -void SettingsPage::load(QCheckBox *box, bool checked) { - box->setProperty("StoredValue", checked); - box->setChecked(checked); + +void SettingsPage::load(QCheckBox *box, bool checked) +{ + box->setProperty("StoredValue", checked); + box->setChecked(checked); } -bool SettingsPage::hasChanged(QCheckBox *box) { - return box->property("StoredValue").toBool() != box->isChecked(); + +bool SettingsPage::hasChanged(QCheckBox *box) +{ + return box->property("StoredValue").toBool() != box->isChecked(); } -void SettingsPage::load(QComboBox *box, int index) { - box->setProperty("StoredValue", index); - box->setCurrentIndex(index); +void SettingsPage::load(QComboBox *box, int index) +{ + box->setProperty("StoredValue", index); + box->setCurrentIndex(index); } -bool SettingsPage::hasChanged(QComboBox *box) { - return box->property("StoredValue").toInt() != box->currentIndex(); + +bool SettingsPage::hasChanged(QComboBox *box) +{ + return box->property("StoredValue").toInt() != box->currentIndex(); } -void SettingsPage::load(QSpinBox *box, int value) { - box->setProperty("StoredValue", value); - box->setValue(value); + +void SettingsPage::load(QSpinBox *box, int value) +{ + box->setProperty("StoredValue", value); + box->setValue(value); } -bool SettingsPage::hasChanged(QSpinBox *box) { - return box->property("StoredValue").toInt() != box->value(); + +bool SettingsPage::hasChanged(QSpinBox *box) +{ + return box->property("StoredValue").toInt() != box->value(); } + /*** Auto child widget handling ***/ -void SettingsPage::initAutoWidgets() { - _autoWidgets.clear(); - - // find all descendants that should be considered auto widgets - // we need to climb the QObject tree recursively - findAutoWidgets(this, &_autoWidgets); - - foreach(QObject *widget, _autoWidgets) { - if(widget->inherits("ColorButton")) - connect(widget, SIGNAL(colorChanged(QColor)), SLOT(autoWidgetHasChanged())); - else if(widget->inherits("QAbstractButton") || widget->inherits("QGroupBox")) - connect(widget, SIGNAL(toggled(bool)), SLOT(autoWidgetHasChanged())); - else if(widget->inherits("QLineEdit") || widget->inherits("QTextEdit")) - connect(widget, SIGNAL(textChanged(const QString &)), SLOT(autoWidgetHasChanged())); - else if(widget->inherits("QComboBox")) - connect(widget, SIGNAL(currentIndexChanged(int)), SLOT(autoWidgetHasChanged())); - else if(widget->inherits("QSpinBox")) - connect(widget, SIGNAL(valueChanged(int)), SLOT(autoWidgetHasChanged())); - else if(widget->inherits("FontSelector")) - connect(widget, SIGNAL(fontChanged(QFont)), SLOT(autoWidgetHasChanged())); - else - qWarning() << "SettingsPage::init(): Unknown autoWidget type" << widget->metaObject()->className(); - } -} - -void SettingsPage::findAutoWidgets(QObject *parent, QObjectList *autoList) const { - foreach(QObject *child, parent->children()) { - if(child->property("settingsKey").isValid()) - autoList->append(child); - findAutoWidgets(child, autoList); - } -} - -QByteArray SettingsPage::autoWidgetPropertyName(QObject *widget) const { - QByteArray prop; - if(widget->inherits("ColorButton")) - prop = "color"; - else if(widget->inherits("QAbstractButton") || widget->inherits("QGroupBox")) - prop = "checked"; - else if(widget->inherits("QLineEdit") || widget->inherits("QTextEdit")) - prop = "text"; - else if(widget->inherits("QComboBox")) - prop = "currentIndex"; - else if(widget->inherits("QSpinBox")) - prop = "value"; - else if(widget->inherits("FontSelector")) - prop = "selectedFont"; - else - qWarning() << "SettingsPage::autoWidgetPropertyName(): Unhandled widget type for" << widget; - - return prop; -} - -QString SettingsPage::autoWidgetSettingsKey(QObject *widget) const { - QString key = widget->property("settingsKey").toString(); - if(key.isEmpty()) - return QString(""); - if(key.startsWith('/')) - key.remove(0, 1); - else - key.prepend(settingsKey() + '/'); - return key; -} - -void SettingsPage::autoWidgetHasChanged() { - bool changed_ = false; - foreach(QObject *widget, _autoWidgets) { - QVariant curValue = widget->property(autoWidgetPropertyName(widget)); - if(!curValue.isValid()) - qWarning() << "SettingsPage::autoWidgetHasChanged(): Unknown property"; - - if(curValue != widget->property("storedValue")) { - changed_ = true; - break; +void SettingsPage::initAutoWidgets() +{ + _autoWidgets.clear(); + + // find all descendants that should be considered auto widgets + // we need to climb the QObject tree recursively + findAutoWidgets(this, &_autoWidgets); + + foreach(QObject *widget, _autoWidgets) { + if (widget->inherits("ColorButton")) + connect(widget, SIGNAL(colorChanged(QColor)), SLOT(autoWidgetHasChanged())); + else if (widget->inherits("QAbstractButton") || widget->inherits("QGroupBox")) + connect(widget, SIGNAL(toggled(bool)), SLOT(autoWidgetHasChanged())); + else if (widget->inherits("QLineEdit") || widget->inherits("QTextEdit")) + connect(widget, SIGNAL(textChanged(const QString &)), SLOT(autoWidgetHasChanged())); + else if (widget->inherits("QComboBox")) + connect(widget, SIGNAL(currentIndexChanged(int)), SLOT(autoWidgetHasChanged())); + else if (widget->inherits("QSpinBox")) + connect(widget, SIGNAL(valueChanged(int)), SLOT(autoWidgetHasChanged())); + else if (widget->inherits("FontSelector")) + connect(widget, SIGNAL(fontChanged(QFont)), SLOT(autoWidgetHasChanged())); + else + qWarning() << "SettingsPage::init(): Unknown autoWidget type" << widget->metaObject()->className(); } - } +} - if(changed_ != _autoWidgetsChanged) { - bool old = hasChanged(); - _autoWidgetsChanged = changed_; - if(hasChanged() != old) - emit changed(hasChanged()); - } -} - -void SettingsPage::load() { - UiSettings s(""); - foreach(QObject *widget, _autoWidgets) { - QString key = autoWidgetSettingsKey(widget); - QVariant val; - if(key.isEmpty()) - val = loadAutoWidgetValue(widget->objectName()); + +void SettingsPage::findAutoWidgets(QObject *parent, QObjectList *autoList) const +{ + foreach(QObject *child, parent->children()) { + if (child->property("settingsKey").isValid()) + autoList->append(child); + findAutoWidgets(child, autoList); + } +} + + +QByteArray SettingsPage::autoWidgetPropertyName(QObject *widget) const +{ + QByteArray prop; + if (widget->inherits("ColorButton")) + prop = "color"; + else if (widget->inherits("QAbstractButton") || widget->inherits("QGroupBox")) + prop = "checked"; + else if (widget->inherits("QLineEdit") || widget->inherits("QTextEdit")) + prop = "text"; + else if (widget->inherits("QComboBox")) + prop = "currentIndex"; + else if (widget->inherits("QSpinBox")) + prop = "value"; + else if (widget->inherits("FontSelector")) + prop = "selectedFont"; else - val = s.value(key, QVariant()); - if(!val.isValid()) - val = widget->property("defaultValue"); - widget->setProperty(autoWidgetPropertyName(widget), val); - widget->setProperty("storedValue", val); - } - bool old = hasChanged(); - _autoWidgetsChanged = _changed = false; - if(hasChanged() != old) - emit changed(hasChanged()); -} - -void SettingsPage::save() { - UiSettings s(""); - foreach(QObject *widget, _autoWidgets) { - QString key = autoWidgetSettingsKey(widget); - QVariant val = widget->property(autoWidgetPropertyName(widget)); - widget->setProperty("storedValue", val); - if(key.isEmpty()) - saveAutoWidgetValue(widget->objectName(), val); + qWarning() << "SettingsPage::autoWidgetPropertyName(): Unhandled widget type for" << widget; + + return prop; +} + + +QString SettingsPage::autoWidgetSettingsKey(QObject *widget) const +{ + QString key = widget->property("settingsKey").toString(); + if (key.isEmpty()) + return QString(""); + if (key.startsWith('/')) + key.remove(0, 1); else - s.setValue(key, val); - } - bool old = hasChanged(); - _autoWidgetsChanged = _changed = false; - if(hasChanged() != old) - emit changed(hasChanged()); + key.prepend(settingsKey() + '/'); + return key; +} + + +void SettingsPage::autoWidgetHasChanged() +{ + bool changed_ = false; + foreach(QObject *widget, _autoWidgets) { + QVariant curValue = widget->property(autoWidgetPropertyName(widget)); + if (!curValue.isValid()) + qWarning() << "SettingsPage::autoWidgetHasChanged(): Unknown property"; + + if (curValue != widget->property("storedValue")) { + changed_ = true; + break; + } + } + + if (changed_ != _autoWidgetsChanged) { + bool old = hasChanged(); + _autoWidgetsChanged = changed_; + if (hasChanged() != old) + emit changed(hasChanged()); + } +} + + +void SettingsPage::load() +{ + UiSettings s(""); + foreach(QObject *widget, _autoWidgets) { + QString key = autoWidgetSettingsKey(widget); + QVariant val; + if (key.isEmpty()) + val = loadAutoWidgetValue(widget->objectName()); + else + val = s.value(key, QVariant()); + if (!val.isValid()) + val = widget->property("defaultValue"); + widget->setProperty(autoWidgetPropertyName(widget), val); + widget->setProperty("storedValue", val); + } + bool old = hasChanged(); + _autoWidgetsChanged = _changed = false; + if (hasChanged() != old) + emit changed(hasChanged()); } -void SettingsPage::defaults() { - foreach(QObject *widget, _autoWidgets) { - QVariant val = widget->property("defaultValue"); - widget->setProperty(autoWidgetPropertyName(widget), val); - } - autoWidgetHasChanged(); + +void SettingsPage::save() +{ + UiSettings s(""); + foreach(QObject *widget, _autoWidgets) { + QString key = autoWidgetSettingsKey(widget); + QVariant val = widget->property(autoWidgetPropertyName(widget)); + widget->setProperty("storedValue", val); + if (key.isEmpty()) + saveAutoWidgetValue(widget->objectName(), val); + else + s.setValue(key, val); + } + bool old = hasChanged(); + _autoWidgetsChanged = _changed = false; + if (hasChanged() != old) + emit changed(hasChanged()); } -QVariant SettingsPage::loadAutoWidgetValue(const QString &widgetName) { - qWarning() << "Could not load value for SettingsPage widget" << widgetName; - return QVariant(); + +void SettingsPage::defaults() +{ + foreach(QObject *widget, _autoWidgets) { + QVariant val = widget->property("defaultValue"); + widget->setProperty(autoWidgetPropertyName(widget), val); + } + autoWidgetHasChanged(); } -void SettingsPage::saveAutoWidgetValue(const QString &widgetName, const QVariant &) { - qWarning() << "Could not save value for SettingsPage widget" << widgetName; + +QVariant SettingsPage::loadAutoWidgetValue(const QString &widgetName) +{ + qWarning() << "Could not load value for SettingsPage widget" << widgetName; + return QVariant(); } + +void SettingsPage::saveAutoWidgetValue(const QString &widgetName, const QVariant &) +{ + qWarning() << "Could not save value for SettingsPage widget" << widgetName; +} diff --git a/src/uisupport/settingspage.h b/src/uisupport/settingspage.h index b68b78b1..80df8d36 100644 --- a/src/uisupport/settingspage.h +++ b/src/uisupport/settingspage.h @@ -54,109 +54,109 @@ class QSpinBox; * - QComboBox (currentIndex()) * - QSpinBox (value()) */ -class SettingsPage : public QWidget { - Q_OBJECT +class SettingsPage : public QWidget +{ + Q_OBJECT public: - SettingsPage(const QString &category, const QString &name, QWidget *parent = 0); - virtual ~SettingsPage() {}; - - //! The category of this settings page. - inline virtual QString category() const { return _category; } - - //! The title of this settings page. - inline virtual QString title() const { return _title; } - - //! Whether the settingspage needs a core connection to be selectable - /** This is a hint for the settingspage dialog. Do not rely on the settingspage not being - * visible if disconnected, and care about disabling it yourself. - */ - inline virtual bool needsCoreConnection() const { return false; } - - //! The key this settings page stores its values under - /** This needs to be overriden to enable automatic loading/saving/hasChanged checking of widgets. - * The child widgets' values will be stored in client settings under this key. Every widget that - * should be automatically handled needs to have a \c settingsKey property set, and should also provide - * a \c defaultValue property. - * You can return an empty string (as opposed to a null string) to use the config root as a base, and - * you can override this key for individual widgets by prefixing their SettingsKey with /. - */ - inline virtual QString settingsKey() const { return QString(); } - - //! Derived classes need to define this and return true if they have default settings. - /** If this method returns true, the "Restore Defaults" button in the SettingsDlg is - * enabled. You also need to provide an implementation of defaults() then. - * - * The default implementation returns false. - */ - inline virtual bool hasDefaults() const { return false; } + SettingsPage(const QString &category, const QString &name, QWidget *parent = 0); + virtual ~SettingsPage() {}; + + //! The category of this settings page. + inline virtual QString category() const { return _category; } - //! Check if there are changes in the page, compared to the state saved in permanent storage. - inline bool hasChanged() const { return _changed || _autoWidgetsChanged; } + //! The title of this settings page. + inline virtual QString title() const { return _title; } - //! Called immediately before save() is called. - /** Derived classes should return false if saving is not possible (e.g. the current settings are invalid). - * \return false, if the SettingsPage cannot be saved in its current state. - */ - inline virtual bool aboutToSave() { return true; } + //! Whether the settingspage needs a core connection to be selectable + /** This is a hint for the settingspage dialog. Do not rely on the settingspage not being + * visible if disconnected, and care about disabling it yourself. + */ + inline virtual bool needsCoreConnection() const { return false; } + + //! The key this settings page stores its values under + /** This needs to be overriden to enable automatic loading/saving/hasChanged checking of widgets. + * The child widgets' values will be stored in client settings under this key. Every widget that + * should be automatically handled needs to have a \c settingsKey property set, and should also provide + * a \c defaultValue property. + * You can return an empty string (as opposed to a null string) to use the config root as a base, and + * you can override this key for individual widgets by prefixing their SettingsKey with /. + */ + inline virtual QString settingsKey() const { return QString(); } + + //! Derived classes need to define this and return true if they have default settings. + /** If this method returns true, the "Restore Defaults" button in the SettingsDlg is + * enabled. You also need to provide an implementation of defaults() then. + * + * The default implementation returns false. + */ + inline virtual bool hasDefaults() const { return false; } + + //! Check if there are changes in the page, compared to the state saved in permanent storage. + inline bool hasChanged() const { return _changed || _autoWidgetsChanged; } + + //! Called immediately before save() is called. + /** Derived classes should return false if saving is not possible (e.g. the current settings are invalid). + * \return false, if the SettingsPage cannot be saved in its current state. + */ + inline virtual bool aboutToSave() { return true; } - //! sets checked state depending on \checked and stores the value for later comparision - static void load(QCheckBox *box, bool checked); - static bool hasChanged(QCheckBox *box); - static void load(QComboBox *box, int index); - static bool hasChanged(QComboBox *box); - static void load(QSpinBox *box, int value); - static bool hasChanged(QSpinBox *box); + //! sets checked state depending on \checked and stores the value for later comparision + static void load(QCheckBox *box, bool checked); + static bool hasChanged(QCheckBox *box); + static void load(QComboBox *box, int index); + static bool hasChanged(QComboBox *box); + static void load(QSpinBox *box, int value); + static bool hasChanged(QSpinBox *box); public slots: - //! Save settings to permanent storage. - /** This baseclass implementation saves the autoWidgets, so be sure to call it if you use - * this feature in your settingsPage! - */ - virtual void save(); - - //! Load settings from permanent storage, overriding any changes the user might have made in the dialog. - /** This baseclass implementation loads the autoWidgets, so be sure to call it if you use - * this feature in your settingsPage! - */ - virtual void load(); - - //! Restore defaults, overriding any changes the user might have made in the dialog. - /** This baseclass implementation loads the defaults of the autoWidgets (if available), so be sure - * to call it if you use this feature in your settingsPage! - */ - virtual void defaults(); + //! Save settings to permanent storage. + /** This baseclass implementation saves the autoWidgets, so be sure to call it if you use + * this feature in your settingsPage! + */ + virtual void save(); + + //! Load settings from permanent storage, overriding any changes the user might have made in the dialog. + /** This baseclass implementation loads the autoWidgets, so be sure to call it if you use + * this feature in your settingsPage! + */ + virtual void load(); + + //! Restore defaults, overriding any changes the user might have made in the dialog. + /** This baseclass implementation loads the defaults of the autoWidgets (if available), so be sure + * to call it if you use this feature in your settingsPage! + */ + virtual void defaults(); protected slots: - //! Calling this slot is equivalent to calling setChangedState(true). - inline void changed() { setChangedState(true); } + //! Calling this slot is equivalent to calling setChangedState(true). + inline void changed() { setChangedState(true); } - //! This should be called whenever the widget state changes from unchanged to change or the other way round. - void setChangedState(bool hasChanged = true); + //! This should be called whenever the widget state changes from unchanged to change or the other way round. + void setChangedState(bool hasChanged = true); protected: - void initAutoWidgets(); - virtual QVariant loadAutoWidgetValue(const QString &widgetName); - virtual void saveAutoWidgetValue(const QString &widgetName, const QVariant &value); + void initAutoWidgets(); + virtual QVariant loadAutoWidgetValue(const QString &widgetName); + virtual void saveAutoWidgetValue(const QString &widgetName, const QVariant &value); signals: - //! Emitted whenever the widget state changes. - void changed(bool hasChanged); + //! Emitted whenever the widget state changes. + void changed(bool hasChanged); private slots: - // for auto stuff - void autoWidgetHasChanged(); + // for auto stuff + void autoWidgetHasChanged(); private: - void findAutoWidgets(QObject *parent, QObjectList *widgetList) const; - QByteArray autoWidgetPropertyName(QObject *widget) const; - QString autoWidgetSettingsKey(QObject *widget) const; + void findAutoWidgets(QObject *parent, QObjectList *widgetList) const; + QByteArray autoWidgetPropertyName(QObject *widget) const; + QString autoWidgetSettingsKey(QObject *widget) const; - QString _category, _title; - bool _changed, _autoWidgetsChanged; - QObjectList _autoWidgets; + QString _category, _title; + bool _changed, _autoWidgetsChanged; + QObjectList _autoWidgets; }; - #endif diff --git a/src/uisupport/styledlabel.cpp b/src/uisupport/styledlabel.cpp index 38250ea2..cf382296 100644 --- a/src/uisupport/styledlabel.cpp +++ b/src/uisupport/styledlabel.cpp @@ -27,210 +27,245 @@ #include "uistyle.h" StyledLabel::StyledLabel(QWidget *parent) -: QFrame(parent), - _wrapMode(QTextOption::NoWrap), - _alignment(Qt::AlignVCenter|Qt::AlignLeft), - _toolTipEnabled(true), - _resizeMode(NoResize) + : QFrame(parent), + _wrapMode(QTextOption::NoWrap), + _alignment(Qt::AlignVCenter|Qt::AlignLeft), + _toolTipEnabled(true), + _resizeMode(NoResize) { - setMouseTracking(true); + setMouseTracking(true); - QTextOption opt = _layout.textOption(); - opt.setWrapMode(_wrapMode); - opt.setAlignment(_alignment); - _layout.setTextOption(opt); + QTextOption opt = _layout.textOption(); + opt.setWrapMode(_wrapMode); + opt.setAlignment(_alignment); + _layout.setTextOption(opt); } -void StyledLabel::setCustomFont(const QFont &font) { - setFont(font); - _layout.setFont(font); - setText(_layout.text()); + +void StyledLabel::setCustomFont(const QFont &font) +{ + setFont(font); + _layout.setFont(font); + setText(_layout.text()); } -void StyledLabel::setWrapMode(QTextOption::WrapMode mode) { - if(_wrapMode == mode) - return; - _wrapMode = mode; - QTextOption opt = _layout.textOption(); - opt.setWrapMode(mode); - _layout.setTextOption(opt); +void StyledLabel::setWrapMode(QTextOption::WrapMode mode) +{ + if (_wrapMode == mode) + return; + + _wrapMode = mode; + QTextOption opt = _layout.textOption(); + opt.setWrapMode(mode); + _layout.setTextOption(opt); - layout(); + layout(); } -void StyledLabel::setAlignment(Qt::Alignment alignment) { - if(_alignment == alignment) - return; - _alignment = alignment; - QTextOption opt = _layout.textOption(); - opt.setAlignment(alignment); - _layout.setTextOption(opt); +void StyledLabel::setAlignment(Qt::Alignment alignment) +{ + if (_alignment == alignment) + return; + + _alignment = alignment; + QTextOption opt = _layout.textOption(); + opt.setAlignment(alignment); + _layout.setTextOption(opt); - layout(); + layout(); } -void StyledLabel::setResizeMode(ResizeMode mode) { - if(_resizeMode == mode) - return; - _resizeMode = mode; - if(mode == DynamicResize) - setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); - else - setWrapMode(QTextOption::NoWrap); +void StyledLabel::setResizeMode(ResizeMode mode) +{ + if (_resizeMode == mode) + return; + + _resizeMode = mode; + if (mode == DynamicResize) + setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); + else + setWrapMode(QTextOption::NoWrap); } -void StyledLabel::resizeEvent(QResizeEvent *event) { - QFrame::resizeEvent(event); - layout(); -} +void StyledLabel::resizeEvent(QResizeEvent *event) +{ + QFrame::resizeEvent(event); -QSize StyledLabel::sizeHint() const { - return _sizeHint; + layout(); } -void StyledLabel::updateSizeHint() { - QSize sh; - int padding = frameWidth() * 2; - sh = _layout.boundingRect().size().toSize() + QSize(padding, padding); - if(_sizeHint != sh) { - _sizeHint = sh; - updateGeometry(); - } +QSize StyledLabel::sizeHint() const +{ + return _sizeHint; } -void StyledLabel::setText(const QString &text) { - UiStyle *style = GraphicalUi::uiStyle(); - UiStyle::StyledString sstr = style->styleString(style->mircToInternal(text), UiStyle::PlainMsg); - QList layoutList = style->toTextLayoutList(sstr.formatList, sstr.plainText.length(), 0); +void StyledLabel::updateSizeHint() +{ + QSize sh; + int padding = frameWidth() * 2; + sh = _layout.boundingRect().size().toSize() + QSize(padding, padding); + + if (_sizeHint != sh) { + _sizeHint = sh; + updateGeometry(); + } +} - // Use default font rather than the style's - QTextLayout::FormatRange fmtRange; - fmtRange.format.setFont(font()); - fmtRange.start = 0; - fmtRange.length = sstr.plainText.length(); - layoutList << fmtRange; - // Mark URLs - _clickables = ClickableList::fromString(sstr.plainText); - foreach(Clickable click, _clickables) { - if(click.type() == Clickable::Url) { - QTextLayout::FormatRange range; - range.start = click.start(); - range.length = click.length(); - range.format.setForeground(palette().link()); - layoutList << range; +void StyledLabel::setText(const QString &text) +{ + UiStyle *style = GraphicalUi::uiStyle(); + + UiStyle::StyledString sstr = style->styleString(style->mircToInternal(text), UiStyle::PlainMsg); + QList layoutList = style->toTextLayoutList(sstr.formatList, sstr.plainText.length(), 0); + + // Use default font rather than the style's + QTextLayout::FormatRange fmtRange; + fmtRange.format.setFont(font()); + fmtRange.start = 0; + fmtRange.length = sstr.plainText.length(); + layoutList << fmtRange; + + // Mark URLs + _clickables = ClickableList::fromString(sstr.plainText); + foreach(Clickable click, _clickables) { + if (click.type() == Clickable::Url) { + QTextLayout::FormatRange range; + range.start = click.start(); + range.length = click.length(); + range.format.setForeground(palette().link()); + layoutList << range; + } } - } - _layout.setText(sstr.plainText); - _layout.setAdditionalFormats(layoutList); + _layout.setText(sstr.plainText); + _layout.setAdditionalFormats(layoutList); - layout(); + layout(); - endHoverMode(); + endHoverMode(); } -void StyledLabel::updateToolTip() { - if(frameRect().width() - 2*frameWidth() < _layout.minimumWidth()) - setToolTip(QString("%1").arg(Qt::escape(_layout.text()))); // only rich text gets wordwrapped! - else - setToolTip(QString()); + +void StyledLabel::updateToolTip() +{ + if (frameRect().width() - 2*frameWidth() < _layout.minimumWidth()) + setToolTip(QString("%1").arg(Qt::escape(_layout.text()))); // only rich text gets wordwrapped! + else + setToolTip(QString()); } -void StyledLabel::layout() { - qreal h = 0; - qreal w = contentsRect().width(); - _layout.beginLayout(); - forever { - QTextLine line = _layout.createLine(); - if(!line.isValid()) - break; - line.setLineWidth(w); - line.setPosition(QPointF(0, h)); - h += line.height(); - } - _layout.endLayout(); +void StyledLabel::layout() +{ + qreal h = 0; + qreal w = contentsRect().width(); + + _layout.beginLayout(); + forever { + QTextLine line = _layout.createLine(); + if (!line.isValid()) + break; + line.setLineWidth(w); + line.setPosition(QPointF(0, h)); + h += line.height(); + } + _layout.endLayout(); - updateSizeHint(); - updateToolTip(); - update(); + updateSizeHint(); + updateToolTip(); + update(); } -void StyledLabel::paintEvent(QPaintEvent *e) { - QFrame::paintEvent(e); - QPainter painter(this); - qreal y = contentsRect().y() + (contentsRect().height() - _layout.boundingRect().height()) / 2; - _layout.draw(&painter, QPointF(contentsRect().x(), y), _extraLayoutList); +void StyledLabel::paintEvent(QPaintEvent *e) +{ + QFrame::paintEvent(e); + QPainter painter(this); + + qreal y = contentsRect().y() + (contentsRect().height() - _layout.boundingRect().height()) / 2; + _layout.draw(&painter, QPointF(contentsRect().x(), y), _extraLayoutList); } -int StyledLabel::posToCursor(const QPointF &pos) { - if(pos.y() < 0 || pos.y() > height()) - return -1; - for(int l = _layout.lineCount() - 1; l >= 0; l--) { - QTextLine line = _layout.lineAt(l); - if(pos.y() >= line.y()) { - return line.xToCursor(pos.x(), QTextLine::CursorOnCharacter); +int StyledLabel::posToCursor(const QPointF &pos) +{ + if (pos.y() < 0 || pos.y() > height()) + return -1; + + for (int l = _layout.lineCount() - 1; l >= 0; l--) { + QTextLine line = _layout.lineAt(l); + if (pos.y() >= line.y()) { + return line.xToCursor(pos.x(), QTextLine::CursorOnCharacter); + } } - } - return -1; + return -1; } -void StyledLabel::mouseMoveEvent(QMouseEvent *event) { - if(event->buttons() == Qt::NoButton) { - Clickable click = _clickables.atCursorPos(posToCursor(event->posF())); - if(click.isValid()) - setHoverMode(click.start(), click.length()); - else - endHoverMode(); - } -} -void StyledLabel::enterEvent(QEvent *) { - if(resizeMode() == ResizeOnHover) - setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); +void StyledLabel::mouseMoveEvent(QMouseEvent *event) +{ + if (event->buttons() == Qt::NoButton) { + Clickable click = _clickables.atCursorPos(posToCursor(event->posF())); + if (click.isValid()) + setHoverMode(click.start(), click.length()); + else + endHoverMode(); + } } -void StyledLabel::leaveEvent(QEvent *) { - endHoverMode(); - if(resizeMode() == ResizeOnHover) - setWrapMode(QTextOption::NoWrap); -} -void StyledLabel::mousePressEvent(QMouseEvent *event) { - if(event->button() == Qt::LeftButton) { - Clickable click = _clickables.atCursorPos(posToCursor(event->posF())); - if(click.isValid()) - emit clickableActivated(click); - } +void StyledLabel::enterEvent(QEvent *) +{ + if (resizeMode() == ResizeOnHover) + setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); } -void StyledLabel::setHoverMode(int start, int length) { - if(_extraLayoutList.count() >= 1 && _extraLayoutList.first().start == start && _extraLayoutList.first().length == length) - return; - QTextLayout::FormatRange range; - range.start = start; - range.length = length; - range.format.setFontUnderline(true); - _extraLayoutList.clear(); - _extraLayoutList << range; +void StyledLabel::leaveEvent(QEvent *) +{ + endHoverMode(); + if (resizeMode() == ResizeOnHover) + setWrapMode(QTextOption::NoWrap); +} + - setCursor(Qt::PointingHandCursor); - update(); +void StyledLabel::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + Clickable click = _clickables.atCursorPos(posToCursor(event->posF())); + if (click.isValid()) + emit clickableActivated(click); + } } -void StyledLabel::endHoverMode() { - _extraLayoutList.clear(); - setCursor(Qt::ArrowCursor); - update(); + +void StyledLabel::setHoverMode(int start, int length) +{ + if (_extraLayoutList.count() >= 1 && _extraLayoutList.first().start == start && _extraLayoutList.first().length == length) + return; + + QTextLayout::FormatRange range; + range.start = start; + range.length = length; + range.format.setFontUnderline(true); + _extraLayoutList.clear(); + _extraLayoutList << range; + + setCursor(Qt::PointingHandCursor); + update(); } + +void StyledLabel::endHoverMode() +{ + _extraLayoutList.clear(); + setCursor(Qt::ArrowCursor); + update(); +} diff --git a/src/uisupport/styledlabel.h b/src/uisupport/styledlabel.h index ef9bad25..9f5fe33f 100644 --- a/src/uisupport/styledlabel.h +++ b/src/uisupport/styledlabel.h @@ -26,67 +26,69 @@ #include "clickable.h" #include "uistyle.h" -class StyledLabel : public QFrame { - Q_OBJECT +class StyledLabel : public QFrame +{ + Q_OBJECT public: - enum ResizeMode { - NoResize, - DynamicResize, - ResizeOnHover - }; + enum ResizeMode { + NoResize, + DynamicResize, + ResizeOnHover + }; - StyledLabel(QWidget *parent = 0); + StyledLabel(QWidget *parent = 0); - void setText(const QString &text); - void setCustomFont(const QFont &font); + void setText(const QString &text); + void setCustomFont(const QFont &font); - virtual QSize sizeHint() const; - //virtual QSize minimumSizeHint() const; + virtual QSize sizeHint() const; + //virtual QSize minimumSizeHint() const; - inline QTextOption::WrapMode wrapMode() const { return _wrapMode; } - void setWrapMode(QTextOption::WrapMode mode); + inline QTextOption::WrapMode wrapMode() const { return _wrapMode; } + void setWrapMode(QTextOption::WrapMode mode); - inline Qt::Alignment alignment() const { return _alignment; } - void setAlignment(Qt::Alignment alignment); + inline Qt::Alignment alignment() const { return _alignment; } + void setAlignment(Qt::Alignment alignment); - inline bool toolTipEnabled() const { return _toolTipEnabled; } - void setToolTipEnabled(bool); + inline bool toolTipEnabled() const { return _toolTipEnabled; } + void setToolTipEnabled(bool); - inline ResizeMode resizeMode() const { return _resizeMode; } - void setResizeMode(ResizeMode); + inline ResizeMode resizeMode() const { return _resizeMode; } + void setResizeMode(ResizeMode); signals: - void clickableActivated(const Clickable &click); + void clickableActivated(const Clickable &click); protected: - virtual void paintEvent(QPaintEvent *event); - virtual void resizeEvent(QResizeEvent *event); - virtual void enterEvent(QEvent *); - virtual void leaveEvent(QEvent *); - virtual void mouseMoveEvent(QMouseEvent *event); - virtual void mousePressEvent(QMouseEvent *event); + virtual void paintEvent(QPaintEvent *event); + virtual void resizeEvent(QResizeEvent *event); + virtual void enterEvent(QEvent *); + virtual void leaveEvent(QEvent *); + virtual void mouseMoveEvent(QMouseEvent *event); + virtual void mousePressEvent(QMouseEvent *event); - int posToCursor(const QPointF &pos); + int posToCursor(const QPointF &pos); private: - QSize _sizeHint; - QTextOption::WrapMode _wrapMode; - Qt::Alignment _alignment; - QTextLayout _layout; - ClickableList _clickables; - bool _toolTipEnabled; - ResizeMode _resizeMode; - - QList _layoutList; - QVector _extraLayoutList; - - void layout(); - void updateSizeHint(); - void updateToolTip(); - - void setHoverMode(int start, int length); - void endHoverMode(); + QSize _sizeHint; + QTextOption::WrapMode _wrapMode; + Qt::Alignment _alignment; + QTextLayout _layout; + ClickableList _clickables; + bool _toolTipEnabled; + ResizeMode _resizeMode; + + QList _layoutList; + QVector _extraLayoutList; + + void layout(); + void updateSizeHint(); + void updateToolTip(); + + void setHoverMode(int start, int length); + void endHoverMode(); }; + #endif diff --git a/src/uisupport/tabcompleter.cpp b/src/uisupport/tabcompleter.cpp index 5d2bf027..3fe99019 100644 --- a/src/uisupport/tabcompleter.cpp +++ b/src/uisupport/tabcompleter.cpp @@ -40,177 +40,192 @@ QString TabCompleter::_currentBufferName; TabCompleter::Type TabCompleter::_completionType; TabCompleter::TabCompleter(MultiLineEdit *_lineEdit) - : QObject(_lineEdit), + : QObject(_lineEdit), _lineEdit(_lineEdit), _enabled(false), _nickSuffix(": ") { - // use both an Action and generic eventFilter, to make the shortcut configurable - // yet still be able to reset() when required - _lineEdit->installEventFilter(this); - ActionCollection *coll = GraphicalUi::actionCollection("General"); - coll->addAction("TabCompletionKey", new Action(tr("Tab completion"), coll, - this, SLOT(onTabCompletionKey()), QKeySequence(Qt::Key_Tab))); + // use both an Action and generic eventFilter, to make the shortcut configurable + // yet still be able to reset() when required + _lineEdit->installEventFilter(this); + ActionCollection *coll = GraphicalUi::actionCollection("General"); + coll->addAction("TabCompletionKey", new Action(tr("Tab completion"), coll, + this, SLOT(onTabCompletionKey()), QKeySequence(Qt::Key_Tab))); } -void TabCompleter::onTabCompletionKey() { - complete(); + +void TabCompleter::onTabCompletionKey() +{ + complete(); } -void TabCompleter::buildCompletionList() { - // ensure a safe state in case we return early. - _completionMap.clear(); - _nextCompletion = _completionMap.begin(); - - // this is the first time tab is pressed -> build up the completion list and it's iterator - QModelIndex currentIndex = Client::bufferModel()->currentIndex(); - _currentBufferId = currentIndex.data(NetworkModel::BufferIdRole).value(); - if(!_currentBufferId.isValid()) - return; - - NetworkId networkId = currentIndex.data(NetworkModel::NetworkIdRole).value(); - _currentBufferName = currentIndex.sibling(currentIndex.row(), 0).data().toString(); - - _currentNetwork = Client::network(networkId); - if(!_currentNetwork) - return; - - QString tabAbbrev = _lineEdit->text().left(_lineEdit->cursorPosition()).section(QRegExp("[^#\\w\\d-_\\[\\]{}|`^.\\\\]"),-1,-1); - QRegExp regex(QString("^[-_\\[\\]{}|`^.\\\\]*").append(QRegExp::escape(tabAbbrev)), Qt::CaseInsensitive); - - // channel completion - add all channels of the current network to the map - if(tabAbbrev.startsWith('#')) { - _completionType = ChannelTab; - foreach(IrcChannel *ircChannel, _currentNetwork->ircChannels()) { - if(regex.indexIn(ircChannel->name()) > -1) - _completionMap[ircChannel->name()] = ircChannel->name(); + +void TabCompleter::buildCompletionList() +{ + // ensure a safe state in case we return early. + _completionMap.clear(); + _nextCompletion = _completionMap.begin(); + + // this is the first time tab is pressed -> build up the completion list and it's iterator + QModelIndex currentIndex = Client::bufferModel()->currentIndex(); + _currentBufferId = currentIndex.data(NetworkModel::BufferIdRole).value(); + if (!_currentBufferId.isValid()) + return; + + NetworkId networkId = currentIndex.data(NetworkModel::NetworkIdRole).value(); + _currentBufferName = currentIndex.sibling(currentIndex.row(), 0).data().toString(); + + _currentNetwork = Client::network(networkId); + if (!_currentNetwork) + return; + + QString tabAbbrev = _lineEdit->text().left(_lineEdit->cursorPosition()).section(QRegExp("[^#\\w\\d-_\\[\\]{}|`^.\\\\]"), -1, -1); + QRegExp regex(QString("^[-_\\[\\]{}|`^.\\\\]*").append(QRegExp::escape(tabAbbrev)), Qt::CaseInsensitive); + + // channel completion - add all channels of the current network to the map + if (tabAbbrev.startsWith('#')) { + _completionType = ChannelTab; + foreach(IrcChannel *ircChannel, _currentNetwork->ircChannels()) { + if (regex.indexIn(ircChannel->name()) > -1) + _completionMap[ircChannel->name()] = ircChannel->name(); + } } - } else { - // user completion - _completionType = UserTab; - switch(static_cast(currentIndex.data(NetworkModel::BufferTypeRole).toInt())) { - case BufferInfo::ChannelBuffer: - { // scope is needed for local var declaration - IrcChannel *channel = _currentNetwork->ircChannel(_currentBufferName); - if(!channel) - return; - foreach(IrcUser *ircUser, channel->ircUsers()) { - if(regex.indexIn(ircUser->nick()) > -1) - _completionMap[ircUser->nick().toLower()] = ircUser->nick(); + else { + // user completion + _completionType = UserTab; + switch (static_cast(currentIndex.data(NetworkModel::BufferTypeRole).toInt())) { + case BufferInfo::ChannelBuffer: + { // scope is needed for local var declaration + IrcChannel *channel = _currentNetwork->ircChannel(_currentBufferName); + if (!channel) + return; + foreach(IrcUser *ircUser, channel->ircUsers()) { + if (regex.indexIn(ircUser->nick()) > -1) + _completionMap[ircUser->nick().toLower()] = ircUser->nick(); + } + } + break; + case BufferInfo::QueryBuffer: + if (regex.indexIn(_currentBufferName) > -1) + _completionMap[_currentBufferName.toLower()] = _currentBufferName; + case BufferInfo::StatusBuffer: + if (!_currentNetwork->myNick().isEmpty() && regex.indexIn(_currentNetwork->myNick()) > -1) + _completionMap[_currentNetwork->myNick().toLower()] = _currentNetwork->myNick(); + break; + default: + return; } - } - break; - case BufferInfo::QueryBuffer: - if(regex.indexIn(_currentBufferName) > -1) - _completionMap[_currentBufferName.toLower()] = _currentBufferName; - case BufferInfo::StatusBuffer: - if(!_currentNetwork->myNick().isEmpty() && regex.indexIn(_currentNetwork->myNick()) > -1) - _completionMap[_currentNetwork->myNick().toLower()] = _currentNetwork->myNick(); - break; - default: - return; } - } - _nextCompletion = _completionMap.begin(); - _lastCompletionLength = tabAbbrev.length(); + _nextCompletion = _completionMap.begin(); + _lastCompletionLength = tabAbbrev.length(); } -void TabCompleter::complete() { - TabCompletionSettings s; - _nickSuffix = s.completionSuffix(); - if(!_enabled) { - buildCompletionList(); - _enabled = true; - } +void TabCompleter::complete() +{ + TabCompletionSettings s; + _nickSuffix = s.completionSuffix(); - if (_nextCompletion != _completionMap.end()) { - // clear previous completion - for (int i = 0; i < _lastCompletionLength; i++) { - _lineEdit->backspace(); + if (!_enabled) { + buildCompletionList(); + _enabled = true; } - // insert completion - _lineEdit->insert(*_nextCompletion); + if (_nextCompletion != _completionMap.end()) { + // clear previous completion + for (int i = 0; i < _lastCompletionLength; i++) { + _lineEdit->backspace(); + } + + // insert completion + _lineEdit->insert(*_nextCompletion); - // remember charcount to delete next time and advance to next completion - _lastCompletionLength = _nextCompletion->length(); - _nextCompletion++; + // remember charcount to delete next time and advance to next completion + _lastCompletionLength = _nextCompletion->length(); + _nextCompletion++; - // we're completing the first word of the line - if(_completionType == UserTab && _lineEdit->cursorPosition() == _lastCompletionLength) { - _lineEdit->insert(_nickSuffix); - _lastCompletionLength += _nickSuffix.length(); - } else if (s.addSpaceMidSentence()) { - _lineEdit->insert(" "); - _lastCompletionLength++; - } + // we're completing the first word of the line + if (_completionType == UserTab && _lineEdit->cursorPosition() == _lastCompletionLength) { + _lineEdit->insert(_nickSuffix); + _lastCompletionLength += _nickSuffix.length(); + } + else if (s.addSpaceMidSentence()) { + _lineEdit->insert(" "); + _lastCompletionLength++; + } - // we're at the end of the list -> start over again - } else { - if(!_completionMap.isEmpty()) { - _nextCompletion = _completionMap.begin(); - complete(); + // we're at the end of the list -> start over again + } + else { + if (!_completionMap.isEmpty()) { + _nextCompletion = _completionMap.begin(); + complete(); + } } - } } -void TabCompleter::reset() { - _enabled = false; + +void TabCompleter::reset() +{ + _enabled = false; } -bool TabCompleter::eventFilter(QObject *obj, QEvent *event) { - if(obj != _lineEdit || event->type() != QEvent::KeyPress) - return QObject::eventFilter(obj, event); - QKeyEvent *keyEvent = static_cast(event); +bool TabCompleter::eventFilter(QObject *obj, QEvent *event) +{ + if (obj != _lineEdit || event->type() != QEvent::KeyPress) + return QObject::eventFilter(obj, event); + + QKeyEvent *keyEvent = static_cast(event); - if(keyEvent->key() != GraphicalUi::actionCollection("General")->action("TabCompletionKey")->shortcut()) { - reset(); - } - return false; + if (keyEvent->key() != GraphicalUi::actionCollection("General")->action("TabCompletionKey")->shortcut()) { + reset(); + } + return false; } + // this determines the sort order -bool TabCompleter::CompletionKey::operator<(const CompletionKey &other) const { - switch(_completionType) { +bool TabCompleter::CompletionKey::operator<(const CompletionKey &other) const +{ + switch (_completionType) { case UserTab: - { + { IrcUser *thisUser = _currentNetwork->ircUser(this->contents); - if(thisUser && _currentNetwork->isMe(thisUser)) - return false; + if (thisUser && _currentNetwork->isMe(thisUser)) + return false; IrcUser *thatUser = _currentNetwork->ircUser(other.contents); - if(thatUser && _currentNetwork->isMe(thatUser)) - return true; + if (thatUser && _currentNetwork->isMe(thatUser)) + return true; - if(!thisUser || !thatUser) - return QString::localeAwareCompare(this->contents, other.contents) < 0; + if (!thisUser || !thatUser) + return QString::localeAwareCompare(this->contents, other.contents) < 0; QDateTime thisSpokenTo = thisUser->lastSpokenTo(_currentBufferId); QDateTime thatSpokenTo = thatUser->lastSpokenTo(_currentBufferId); - if(thisSpokenTo.isValid() || thatSpokenTo.isValid()) - return thisSpokenTo > thatSpokenTo; + if (thisSpokenTo.isValid() || thatSpokenTo.isValid()) + return thisSpokenTo > thatSpokenTo; QDateTime thisTime = thisUser->lastChannelActivity(_currentBufferId); QDateTime thatTime = thatUser->lastChannelActivity(_currentBufferId); - if(thisTime.isValid() || thatTime.isValid()) - return thisTime > thatTime; - } - break; + if (thisTime.isValid() || thatTime.isValid()) + return thisTime > thatTime; + } + break; case ChannelTab: - if(QString::compare(_currentBufferName, this->contents, Qt::CaseInsensitive) == 0) - return true; + if (QString::compare(_currentBufferName, this->contents, Qt::CaseInsensitive) == 0) + return true; - if(QString::compare(_currentBufferName, other.contents, Qt::CaseInsensitive) == 0) - return false; - break; + if (QString::compare(_currentBufferName, other.contents, Qt::CaseInsensitive) == 0) + return false; + break; default: - break; - } + break; + } - return QString::localeAwareCompare(this->contents, other.contents) < 0; + return QString::localeAwareCompare(this->contents, other.contents) < 0; } diff --git a/src/uisupport/tabcompleter.h b/src/uisupport/tabcompleter.h index 47aebb09..08773198 100644 --- a/src/uisupport/tabcompleter.h +++ b/src/uisupport/tabcompleter.h @@ -31,50 +31,51 @@ class MultiLineEdit; class IrcUser; class Network; -class TabCompleter : public QObject { - Q_OBJECT +class TabCompleter : public QObject +{ + Q_OBJECT public: - enum Type { - UserTab = 0x01, - ChannelTab = 0x02 - }; + enum Type { + UserTab = 0x01, + ChannelTab = 0x02 + }; - explicit TabCompleter(MultiLineEdit *inputLine_); + explicit TabCompleter(MultiLineEdit *inputLine_); - void reset(); - void complete(); + void reset(); + void complete(); - virtual bool eventFilter(QObject *obj, QEvent *event); + virtual bool eventFilter(QObject *obj, QEvent *event); public slots: - void onTabCompletionKey(); + void onTabCompletionKey(); private: - struct CompletionKey { - inline CompletionKey(const QString &n) { contents = n; } - bool operator<(const CompletionKey &other) const; - QString contents; - }; + struct CompletionKey { + inline CompletionKey(const QString &n) { contents = n; } + bool operator<(const CompletionKey &other) const; + QString contents; + }; - QPointer _lineEdit; - bool _enabled; - QString _nickSuffix; + QPointer _lineEdit; + bool _enabled; + QString _nickSuffix; - static const Network *_currentNetwork; - static BufferId _currentBufferId; - static QString _currentBufferName; - static Type _completionType; + static const Network *_currentNetwork; + static BufferId _currentBufferId; + static QString _currentBufferName; + static Type _completionType; - QMap _completionMap; - // QStringList completionTemplates; + QMap _completionMap; + // QStringList completionTemplates; - QMap::Iterator _nextCompletion; - int _lastCompletionLength; - - void buildCompletionList(); + QMap::Iterator _nextCompletion; + int _lastCompletionLength; + void buildCompletionList(); }; + #endif diff --git a/src/uisupport/toolbaractionprovider.cpp b/src/uisupport/toolbaractionprovider.cpp index a560ea6d..1e5c2be0 100644 --- a/src/uisupport/toolbaractionprovider.cpp +++ b/src/uisupport/toolbaractionprovider.cpp @@ -26,176 +26,203 @@ #include "iconloader.h" ToolBarActionProvider::ToolBarActionProvider(QObject *parent) -: NetworkModelController(parent) + : NetworkModelController(parent) { - registerAction(NetworkConnectAll, DesktopIcon("network-connect"), tr("Connect"))->setToolTip(tr("Connect to IRC")); - registerAction(NetworkDisconnectAll, DesktopIcon("network-disconnect"), tr("Disconnect"))->setToolTip(tr("Disconnect from IRC")); - - registerAction(BufferPart, DesktopIcon("irc-close-channel"), tr("Part"))->setToolTip(tr("Leave currently selected channel")); - registerAction(JoinChannel, DesktopIcon("irc-join-channel"), tr("Join"))->setToolTip(tr("Join a channel")); - - registerAction(NickQuery, DesktopIcon("mail-message-new"), tr("Query"))->setToolTip(tr("Start a private conversation")); // fix icon - registerAction(NickWhois, DesktopIcon("im-user"), tr("Whois"))->setToolTip(tr("Request user information")); // fix icon - - registerAction(NickOp, DesktopIcon("irc-operator"), tr("Op"))->setToolTip(tr("Give operator privileges to user")); - registerAction(NickDeop, DesktopIcon("irc-remove-operator"), tr("Deop"))->setToolTip(tr("Take operator privileges from user")); - registerAction(NickVoice, DesktopIcon("irc-voice"), tr("Voice"))->setToolTip(tr("Give voice to user")); - registerAction(NickDevoice, DesktopIcon("irc-unvoice"), tr("Devoice"))->setToolTip(tr("Take voice from user")); - registerAction(NickKick, DesktopIcon("im-kick-user"), tr("Kick"))->setToolTip(tr("Remove user from channel")); - registerAction(NickBan, DesktopIcon("im-ban-user"), tr("Ban"))->setToolTip(tr("Ban user from channel")); - registerAction(NickKickBan, DesktopIcon("im-ban-kick-user"), tr("Kick/Ban"))->setToolTip(tr("Remove and ban user from channel")); - - _networksConnectMenu = new QMenu(); - _networksConnectMenu->setSeparatorsCollapsible(false); - _networksConnectMenu->addSeparator(); - _networksConnectMenu->addAction(tr("Connect to all")); - action(NetworkConnectAll)->setMenu(_networksConnectMenu); - action(NetworkConnectAll)->setEnabled(false); - - _networksDisconnectMenu = new QMenu(); - _networksDisconnectMenu->setSeparatorsCollapsible(false); - _networksDisconnectMenu->addSeparator(); - _networksDisconnectMenu->addAction(tr("Disconnect from all")); - action(NetworkDisconnectAll)->setMenu(_networksDisconnectMenu); - action(NetworkDisconnectAll)->setEnabled(false); - - connect(Client::instance(), SIGNAL(networkCreated(NetworkId)), SLOT(networkCreated(NetworkId))); - connect(Client::instance(), SIGNAL(networkRemoved(NetworkId)), SLOT(networkRemoved(NetworkId))); - - updateStates(); + registerAction(NetworkConnectAll, DesktopIcon("network-connect"), tr("Connect"))->setToolTip(tr("Connect to IRC")); + registerAction(NetworkDisconnectAll, DesktopIcon("network-disconnect"), tr("Disconnect"))->setToolTip(tr("Disconnect from IRC")); + + registerAction(BufferPart, DesktopIcon("irc-close-channel"), tr("Part"))->setToolTip(tr("Leave currently selected channel")); + registerAction(JoinChannel, DesktopIcon("irc-join-channel"), tr("Join"))->setToolTip(tr("Join a channel")); + + registerAction(NickQuery, DesktopIcon("mail-message-new"), tr("Query"))->setToolTip(tr("Start a private conversation")); // fix icon + registerAction(NickWhois, DesktopIcon("im-user"), tr("Whois"))->setToolTip(tr("Request user information")); // fix icon + + registerAction(NickOp, DesktopIcon("irc-operator"), tr("Op"))->setToolTip(tr("Give operator privileges to user")); + registerAction(NickDeop, DesktopIcon("irc-remove-operator"), tr("Deop"))->setToolTip(tr("Take operator privileges from user")); + registerAction(NickVoice, DesktopIcon("irc-voice"), tr("Voice"))->setToolTip(tr("Give voice to user")); + registerAction(NickDevoice, DesktopIcon("irc-unvoice"), tr("Devoice"))->setToolTip(tr("Take voice from user")); + registerAction(NickKick, DesktopIcon("im-kick-user"), tr("Kick"))->setToolTip(tr("Remove user from channel")); + registerAction(NickBan, DesktopIcon("im-ban-user"), tr("Ban"))->setToolTip(tr("Ban user from channel")); + registerAction(NickKickBan, DesktopIcon("im-ban-kick-user"), tr("Kick/Ban"))->setToolTip(tr("Remove and ban user from channel")); + + _networksConnectMenu = new QMenu(); + _networksConnectMenu->setSeparatorsCollapsible(false); + _networksConnectMenu->addSeparator(); + _networksConnectMenu->addAction(tr("Connect to all")); + action(NetworkConnectAll)->setMenu(_networksConnectMenu); + action(NetworkConnectAll)->setEnabled(false); + + _networksDisconnectMenu = new QMenu(); + _networksDisconnectMenu->setSeparatorsCollapsible(false); + _networksDisconnectMenu->addSeparator(); + _networksDisconnectMenu->addAction(tr("Disconnect from all")); + action(NetworkDisconnectAll)->setMenu(_networksDisconnectMenu); + action(NetworkDisconnectAll)->setEnabled(false); + + connect(Client::instance(), SIGNAL(networkCreated(NetworkId)), SLOT(networkCreated(NetworkId))); + connect(Client::instance(), SIGNAL(networkRemoved(NetworkId)), SLOT(networkRemoved(NetworkId))); + + updateStates(); } -ToolBarActionProvider::~ToolBarActionProvider() { +ToolBarActionProvider::~ToolBarActionProvider() +{ } -void ToolBarActionProvider::disconnectedFromCore() { - _currentBuffer = QModelIndex(); - updateStates(); - NetworkModelController::disconnectedFromCore(); + +void ToolBarActionProvider::disconnectedFromCore() +{ + _currentBuffer = QModelIndex(); + updateStates(); + NetworkModelController::disconnectedFromCore(); } -void ToolBarActionProvider::updateStates() { - action(BufferPart)->setEnabled(_currentBuffer.isValid() - && _currentBuffer.data(NetworkModel::BufferTypeRole) == BufferInfo::ChannelBuffer - && _currentBuffer.data(NetworkModel::ItemActiveRole).toBool()); +void ToolBarActionProvider::updateStates() +{ + action(BufferPart)->setEnabled(_currentBuffer.isValid() + && _currentBuffer.data(NetworkModel::BufferTypeRole) == BufferInfo::ChannelBuffer + && _currentBuffer.data(NetworkModel::ItemActiveRole).toBool()); } -void ToolBarActionProvider::addActions(QToolBar *bar, ToolBarType type) { - switch(type) { + +void ToolBarActionProvider::addActions(QToolBar *bar, ToolBarType type) +{ + switch (type) { case MainToolBar: - bar->addAction(action(NetworkConnectAll)); - bar->addAction(action(NetworkDisconnectAll)); - bar->addAction(action(JoinChannel)); - bar->addAction(action(BufferPart)); - break; + bar->addAction(action(NetworkConnectAll)); + bar->addAction(action(NetworkDisconnectAll)); + bar->addAction(action(JoinChannel)); + bar->addAction(action(BufferPart)); + break; case NickToolBar: - bar->addAction(action(NickQuery)); - bar->addAction(action(NickWhois)); - bar->addSeparator(); - bar->addAction(action(NickOp)); - bar->addAction(action(NickDeop)); - bar->addAction(action(NickVoice)); - bar->addAction(action(NickDevoice)); - bar->addAction(action(NickKick)); - bar->addAction(action(NickBan)); - bar->addAction(action(NickKickBan)); - break; + bar->addAction(action(NickQuery)); + bar->addAction(action(NickWhois)); + bar->addSeparator(); + bar->addAction(action(NickOp)); + bar->addAction(action(NickDeop)); + bar->addAction(action(NickVoice)); + bar->addAction(action(NickDevoice)); + bar->addAction(action(NickKick)); + bar->addAction(action(NickBan)); + bar->addAction(action(NickKickBan)); + break; default: - return; - } + return; + } } -void ToolBarActionProvider::currentBufferChanged(const QModelIndex &index) { - _currentBuffer = index; - updateStates(); + +void ToolBarActionProvider::currentBufferChanged(const QModelIndex &index) +{ + _currentBuffer = index; + updateStates(); } -void ToolBarActionProvider::nickSelectionChanged(const QModelIndexList &indexList) { - _selectedNicks = indexList; - updateStates(); + +void ToolBarActionProvider::nickSelectionChanged(const QModelIndexList &indexList) +{ + _selectedNicks = indexList; + updateStates(); } + // override those to set indexes right -void ToolBarActionProvider::handleNetworkAction(ActionType type, QAction *action) { - setIndexList(_currentBuffer); - NetworkModelController::handleNetworkAction(type, action); +void ToolBarActionProvider::handleNetworkAction(ActionType type, QAction *action) +{ + setIndexList(_currentBuffer); + NetworkModelController::handleNetworkAction(type, action); } -void ToolBarActionProvider::handleBufferAction(ActionType type, QAction *action) { - setIndexList(_currentBuffer); - NetworkModelController::handleBufferAction(type, action); + +void ToolBarActionProvider::handleBufferAction(ActionType type, QAction *action) +{ + setIndexList(_currentBuffer); + NetworkModelController::handleBufferAction(type, action); } -void ToolBarActionProvider::handleNickAction(ActionType type, QAction *action) { - setIndexList(_selectedNicks); - NetworkModelController::handleNickAction(type, action); + +void ToolBarActionProvider::handleNickAction(ActionType type, QAction *action) +{ + setIndexList(_selectedNicks); + NetworkModelController::handleNickAction(type, action); } -void ToolBarActionProvider::handleGeneralAction(ActionType type, QAction *action) { - setIndexList(_currentBuffer); - NetworkModelController::handleGeneralAction(type, action); + +void ToolBarActionProvider::handleGeneralAction(ActionType type, QAction *action) +{ + setIndexList(_currentBuffer); + NetworkModelController::handleGeneralAction(type, action); } -void ToolBarActionProvider::networkCreated(NetworkId id) { - const Network *net = Client::network(id); - Action *act = new Action(net->networkName(), this); - _networkActions[id] = act; - act->setObjectName(QString("NetworkAction-%1").arg(id.toInt())); - act->setData(QVariant::fromValue(id)); - connect(net, SIGNAL(updatedRemotely()), SLOT(networkUpdated())); - connect(act, SIGNAL(triggered()), SLOT(connectOrDisconnectNet())); - networkUpdated(net); + +void ToolBarActionProvider::networkCreated(NetworkId id) +{ + const Network *net = Client::network(id); + Action *act = new Action(net->networkName(), this); + _networkActions[id] = act; + act->setObjectName(QString("NetworkAction-%1").arg(id.toInt())); + act->setData(QVariant::fromValue(id)); + connect(net, SIGNAL(updatedRemotely()), SLOT(networkUpdated())); + connect(act, SIGNAL(triggered()), SLOT(connectOrDisconnectNet())); + networkUpdated(net); } -void ToolBarActionProvider::networkRemoved(NetworkId id) { - Action *act = _networkActions.take(id); - if(act) - act->deleteLater(); + +void ToolBarActionProvider::networkRemoved(NetworkId id) +{ + Action *act = _networkActions.take(id); + if (act) + act->deleteLater(); } -void ToolBarActionProvider::networkUpdated(const Network *net) { - if(!net) - net = qobject_cast(sender()); - if(!net) - return; - Action *act = _networkActions.value(net->networkId()); - if(!act) - return; - - _networksConnectMenu->removeAction(act); - _networksDisconnectMenu->removeAction(act); - - QMenu *newMenu = net->connectionState() != Network::Disconnected ? _networksDisconnectMenu : _networksConnectMenu; - act->setText(net->networkName()); - - const int lastidx = newMenu->actions().count() - 2; - QAction *beforeAction = newMenu->actions().at(lastidx); - for(int i = 0; i < newMenu->actions().count() - 2; i++) { - QAction *action = newMenu->actions().at(i); - if(net->networkName().localeAwareCompare(action->text()) < 0) { - beforeAction = action; - break; + +void ToolBarActionProvider::networkUpdated(const Network *net) +{ + if (!net) + net = qobject_cast(sender()); + if (!net) + return; + Action *act = _networkActions.value(net->networkId()); + if (!act) + return; + + _networksConnectMenu->removeAction(act); + _networksDisconnectMenu->removeAction(act); + + QMenu *newMenu = net->connectionState() != Network::Disconnected ? _networksDisconnectMenu : _networksConnectMenu; + act->setText(net->networkName()); + + const int lastidx = newMenu->actions().count() - 2; + QAction *beforeAction = newMenu->actions().at(lastidx); + for (int i = 0; i < newMenu->actions().count() - 2; i++) { + QAction *action = newMenu->actions().at(i); + if (net->networkName().localeAwareCompare(action->text()) < 0) { + beforeAction = action; + break; + } } - } - newMenu->insertAction(beforeAction, act); + newMenu->insertAction(beforeAction, act); - action(NetworkConnectAll)->setEnabled(_networksConnectMenu->actions().count() > 2); - action(NetworkDisconnectAll)->setEnabled(_networksDisconnectMenu->actions().count() > 2); - action(JoinChannel)->setEnabled(_networksDisconnectMenu->actions().count() > 2); + action(NetworkConnectAll)->setEnabled(_networksConnectMenu->actions().count() > 2); + action(NetworkDisconnectAll)->setEnabled(_networksDisconnectMenu->actions().count() > 2); + action(JoinChannel)->setEnabled(_networksDisconnectMenu->actions().count() > 2); } -void ToolBarActionProvider::connectOrDisconnectNet() { - QAction *act = qobject_cast(sender()); - if(!act) - return; - const Network *net = Client::network(act->data().value()); - if(!net) - return; - if(net->connectionState() == Network::Disconnected) net->requestConnect(); - else net->requestDisconnect(); +void ToolBarActionProvider::connectOrDisconnectNet() +{ + QAction *act = qobject_cast(sender()); + if (!act) + return; + const Network *net = Client::network(act->data().value()); + if (!net) + return; + + if (net->connectionState() == Network::Disconnected) net->requestConnect(); + else net->requestDisconnect(); } + //void ToolBarActionProvider:: diff --git a/src/uisupport/toolbaractionprovider.h b/src/uisupport/toolbaractionprovider.h index 11d911d8..df304c95 100644 --- a/src/uisupport/toolbaractionprovider.h +++ b/src/uisupport/toolbaractionprovider.h @@ -25,46 +25,48 @@ class QToolBar; -class ToolBarActionProvider : public NetworkModelController { - Q_OBJECT +class ToolBarActionProvider : public NetworkModelController +{ + Q_OBJECT public: - ToolBarActionProvider(QObject *parent = 0); - virtual ~ToolBarActionProvider(); + ToolBarActionProvider(QObject *parent = 0); + virtual ~ToolBarActionProvider(); - enum ToolBarType { - MainToolBar, - ChatViewToolBar, - NickToolBar - }; + enum ToolBarType { + MainToolBar, + ChatViewToolBar, + NickToolBar + }; - void addActions(QToolBar *, ToolBarType type); + void addActions(QToolBar *, ToolBarType type); public slots: - virtual void disconnectedFromCore(); + virtual void disconnectedFromCore(); protected: - virtual void handleNetworkAction(ActionType, QAction *); - virtual void handleBufferAction(ActionType, QAction *); - virtual void handleNickAction(ActionType, QAction *); - virtual void handleGeneralAction(ActionType, QAction *); + virtual void handleNetworkAction(ActionType, QAction *); + virtual void handleBufferAction(ActionType, QAction *); + virtual void handleNickAction(ActionType, QAction *); + virtual void handleGeneralAction(ActionType, QAction *); private slots: - void networkCreated(NetworkId id); - void networkRemoved(NetworkId id); - void networkUpdated(const Network *net = 0); - void connectOrDisconnectNet(); + void networkCreated(NetworkId id); + void networkRemoved(NetworkId id); + void networkUpdated(const Network *net = 0); + void connectOrDisconnectNet(); - void currentBufferChanged(const QModelIndex &); - void nickSelectionChanged(const QModelIndexList &); + void currentBufferChanged(const QModelIndex &); + void nickSelectionChanged(const QModelIndexList &); - void updateStates(); + void updateStates(); private: - QMenu *_networksConnectMenu, *_networksDisconnectMenu; - QHash _networkActions; - QModelIndex _currentBuffer; - QModelIndexList _selectedNicks; + QMenu *_networksConnectMenu, *_networksDisconnectMenu; + QHash _networkActions; + QModelIndex _currentBuffer; + QModelIndexList _selectedNicks; }; + #endif diff --git a/src/uisupport/uisettings.cpp b/src/uisupport/uisettings.cpp index fe45fd98..6a1ce9f4 100644 --- a/src/uisupport/uisettings.cpp +++ b/src/uisupport/uisettings.cpp @@ -24,10 +24,11 @@ #include "actioncollection.h" UiSettings::UiSettings(const QString &group) - : ClientSettings(group) + : ClientSettings(group) { } + /**************************************************************************/ UiStyleSettings::UiStyleSettings() : UiSettings("UiStyle") {} @@ -35,119 +36,153 @@ UiStyleSettings::UiStyleSettings(const QString &subGroup) : UiSettings(QString(" { } -void UiStyleSettings::setCustomFormat(UiStyle::FormatType ftype, QTextCharFormat format) { - setLocalValue(QString("Format/%1").arg(ftype), format); + +void UiStyleSettings::setCustomFormat(UiStyle::FormatType ftype, QTextCharFormat format) +{ + setLocalValue(QString("Format/%1").arg(ftype), format); } -QTextCharFormat UiStyleSettings::customFormat(UiStyle::FormatType ftype) { - return localValue(QString("Format/%1").arg(ftype), QTextFormat()).value().toCharFormat(); + +QTextCharFormat UiStyleSettings::customFormat(UiStyle::FormatType ftype) +{ + return localValue(QString("Format/%1").arg(ftype), QTextFormat()).value().toCharFormat(); } -void UiStyleSettings::removeCustomFormat(UiStyle::FormatType ftype) { - removeLocalKey(QString("Format/%1").arg(ftype)); + +void UiStyleSettings::removeCustomFormat(UiStyle::FormatType ftype) +{ + removeLocalKey(QString("Format/%1").arg(ftype)); } -QList UiStyleSettings::availableFormats() { - QList formats; - QStringList list = localChildKeys("Format"); - foreach(QString type, list) { - formats << (UiStyle::FormatType)type.toInt(); - } - return formats; + +QList UiStyleSettings::availableFormats() +{ + QList formats; + QStringList list = localChildKeys("Format"); + foreach(QString type, list) { + formats << (UiStyle::FormatType)type.toInt(); + } + return formats; } + /************************************************************************** * SessionSettings **************************************************************************/ -SessionSettings::SessionSettings(const QString & sessionId, const QString & group) -: UiSettings(group), _sessionId(sessionId) +SessionSettings::SessionSettings(const QString &sessionId, const QString &group) + : UiSettings(group), _sessionId(sessionId) { - } -void SessionSettings::setValue(const QString &key, const QVariant &data) { - setLocalValue(QString("%1/%2").arg(_sessionId, key), data); + +void SessionSettings::setValue(const QString &key, const QVariant &data) +{ + setLocalValue(QString("%1/%2").arg(_sessionId, key), data); } -QVariant SessionSettings::value(const QString &key, const QVariant &def) { - return localValue(QString("%1/%2").arg(_sessionId, key), def); + +QVariant SessionSettings::value(const QString &key, const QVariant &def) +{ + return localValue(QString("%1/%2").arg(_sessionId, key), def); } -void SessionSettings::removeKey(const QString &key) { - removeLocalKey(QString("%1/%2").arg(_sessionId, key)); + +void SessionSettings::removeKey(const QString &key) +{ + removeLocalKey(QString("%1/%2").arg(_sessionId, key)); } -void SessionSettings::cleanup() { - QStringList sessions = localChildGroups(); - QString str; - SessionSettings s(sessionId()); - foreach(str, sessions) { - // load session and check age - s.setSessionId(str); - if(s.sessionAge() > 3) { - s.removeSession(); + +void SessionSettings::cleanup() +{ + QStringList sessions = localChildGroups(); + QString str; + SessionSettings s(sessionId()); + foreach(str, sessions) { + // load session and check age + s.setSessionId(str); + if (s.sessionAge() > 3) { + s.removeSession(); + } } - } } -int SessionSettings::sessionAge() { - QVariant val = localValue(QString("%1/_sessionAge").arg(_sessionId), 0); - bool b = false; - int i = val.toInt(&b); - if(b) { - return i; - } else { - // no int saved, delete session - //qDebug() << QString("deleting invalid session %1 (invalid session age found)").arg(_sessionId); - removeSession(); - } - return 10; + +int SessionSettings::sessionAge() +{ + QVariant val = localValue(QString("%1/_sessionAge").arg(_sessionId), 0); + bool b = false; + int i = val.toInt(&b); + if (b) { + return i; + } + else { + // no int saved, delete session + //qDebug() << QString("deleting invalid session %1 (invalid session age found)").arg(_sessionId); + removeSession(); + } + return 10; } -void SessionSettings::removeSession() { - QStringList keys = localChildKeys(sessionId()); - foreach(QString k, keys) { - removeKey(k); - } + +void SessionSettings::removeSession() +{ + QStringList keys = localChildKeys(sessionId()); + foreach(QString k, keys) { + removeKey(k); + } } -void SessionSettings::setSessionAge(int age) { - setValue(QString("_sessionAge"),age); + +void SessionSettings::setSessionAge(int age) +{ + setValue(QString("_sessionAge"), age); } -void SessionSettings::sessionAging() { - QStringList sessions = localChildGroups(); - QString str; - SessionSettings s(sessionId()); - foreach(str, sessions) { - // load session and check age - s.setSessionId(str); - s.setSessionAge(s.sessionAge()+1); - } + +void SessionSettings::sessionAging() +{ + QStringList sessions = localChildGroups(); + QString str; + SessionSettings s(sessionId()); + foreach(str, sessions) { + // load session and check age + s.setSessionId(str); + s.setSessionAge(s.sessionAge()+1); + } } + /************************************************************************** * ShortcutSettings **************************************************************************/ -ShortcutSettings::ShortcutSettings() : UiSettings("Shortcuts") { - +ShortcutSettings::ShortcutSettings() : UiSettings("Shortcuts") +{ } -void ShortcutSettings::clear() { - foreach(const QString &key, allLocalKeys()) + +void ShortcutSettings::clear() +{ + foreach(const QString &key, allLocalKeys()) removeLocalKey(key); } -QStringList ShortcutSettings::savedShortcuts() { - return localChildKeys(); + +QStringList ShortcutSettings::savedShortcuts() +{ + return localChildKeys(); } -QKeySequence ShortcutSettings::loadShortcut(const QString &name) { - return localValue(name, QKeySequence()).value(); + +QKeySequence ShortcutSettings::loadShortcut(const QString &name) +{ + return localValue(name, QKeySequence()).value(); } -void ShortcutSettings::saveShortcut(const QString &name, const QKeySequence &seq) { - setLocalValue(name, seq); + +void ShortcutSettings::saveShortcut(const QString &name, const QKeySequence &seq) +{ + setLocalValue(name, seq); } diff --git a/src/uisupport/uisettings.h b/src/uisupport/uisettings.h index b3822532..c147022e 100644 --- a/src/uisupport/uisettings.h +++ b/src/uisupport/uisettings.h @@ -24,62 +24,69 @@ #include "clientsettings.h" #include "uistyle.h" -class UiSettings : public ClientSettings { +class UiSettings : public ClientSettings +{ public: - UiSettings(const QString &group = "Ui"); + UiSettings(const QString &group = "Ui"); - virtual inline void setValue(const QString &key, const QVariant &data) { setLocalValue(key, data); } - virtual inline QVariant value(const QString &key, const QVariant &def = QVariant()) { return localValue(key, def); } + virtual inline void setValue(const QString &key, const QVariant &data) { setLocalValue(key, data); } + virtual inline QVariant value(const QString &key, const QVariant &def = QVariant()) { return localValue(key, def); } - inline void remove(const QString &key) { removeLocalKey(key); } + inline void remove(const QString &key) { removeLocalKey(key); } }; -class UiStyleSettings : public UiSettings { +class UiStyleSettings : public UiSettings +{ public: - UiStyleSettings(); - UiStyleSettings(const QString &subGroup); + UiStyleSettings(); + UiStyleSettings(const QString &subGroup); - void setCustomFormat(UiStyle::FormatType, QTextCharFormat); - QTextCharFormat customFormat(UiStyle::FormatType); + void setCustomFormat(UiStyle::FormatType, QTextCharFormat); + QTextCharFormat customFormat(UiStyle::FormatType); - void removeCustomFormat(UiStyle::FormatType); - QList availableFormats(); + void removeCustomFormat(UiStyle::FormatType); + QList availableFormats(); }; -class SessionSettings : public UiSettings { + +class SessionSettings : public UiSettings +{ public: - SessionSettings(const QString &sessionId, const QString &group = "Session"); + SessionSettings(const QString &sessionId, const QString &group = "Session"); - virtual void setValue(const QString &key, const QVariant &data); - virtual QVariant value(const QString &key, const QVariant &def = QVariant()); + virtual void setValue(const QString &key, const QVariant &data); + virtual QVariant value(const QString &key, const QVariant &def = QVariant()); - void removeKey(const QString &key); - void removeSession(); + void removeKey(const QString &key); + void removeSession(); - void cleanup(); - void sessionAging(); + void cleanup(); + void sessionAging(); - int sessionAge(); - void setSessionAge(int age); - inline const QString sessionId() { return _sessionId; }; - inline void setSessionId(const QString &sessionId) { _sessionId = sessionId; } + int sessionAge(); + void setSessionAge(int age); + inline const QString sessionId() { return _sessionId; }; + inline void setSessionId(const QString &sessionId) { _sessionId = sessionId; } private: - QString _sessionId; + QString _sessionId; }; -class ShortcutSettings : public UiSettings { + +class ShortcutSettings : public UiSettings +{ public: - ShortcutSettings(); + ShortcutSettings(); - //! Remove all stored shortcuts - void clear(); + //! Remove all stored shortcuts + void clear(); - QStringList savedShortcuts(); + QStringList savedShortcuts(); - void saveShortcut(const QString &name, const QKeySequence &shortcut); - QKeySequence loadShortcut(const QString &name); + void saveShortcut(const QString &name, const QKeySequence &shortcut); + QKeySequence loadShortcut(const QString &name); }; + #endif diff --git a/src/uisupport/uistyle.cpp b/src/uisupport/uistyle.cpp index f04dcf22..59a673b9 100644 --- a/src/uisupport/uistyle.cpp +++ b/src/uisupport/uistyle.cpp @@ -31,751 +31,830 @@ QHash UiStyle::_formatCodes; QString UiStyle::_timestampFormatString; UiStyle::UiStyle(QObject *parent) -: QObject(parent), - _channelJoinedIcon(SmallIcon("irc-channel-active")), - _channelPartedIcon(SmallIcon("irc-channel-inactive")), - _userOfflineIcon(SmallIcon("im-user-offline")), - _userOnlineIcon(SmallIcon("im-user")), - _userAwayIcon(SmallIcon("im-user-away")), - _categoryOpIcon(SmallIcon("irc-operator")), - _categoryVoiceIcon(SmallIcon("irc-voice")), - _opIconLimit(UserCategoryItem::categoryFromModes("o")), - _voiceIconLimit(UserCategoryItem::categoryFromModes("v")) -{ - // register FormatList if that hasn't happened yet - // FIXME I don't think this actually avoids double registration... then again... does it hurt? - if(QVariant::nameToType("UiStyle::FormatList") == QVariant::Invalid) { - qRegisterMetaType("UiStyle::FormatList"); - qRegisterMetaTypeStreamOperators("UiStyle::FormatList"); - Q_ASSERT(QVariant::nameToType("UiStyle::FormatList") != QVariant::Invalid); - } - - _uiStylePalette = QVector(NumRoles, QBrush()); - - // Now initialize the mapping between FormatCodes and FormatTypes... - _formatCodes["%O"] = Base; - _formatCodes["%B"] = Bold; - _formatCodes["%S"] = Italic; - _formatCodes["%U"] = Underline; - _formatCodes["%R"] = Reverse; - - _formatCodes["%DN"] = Nick; - _formatCodes["%DH"] = Hostmask; - _formatCodes["%DC"] = ChannelName; - _formatCodes["%DM"] = ModeFlags; - _formatCodes["%DU"] = Url; - - setTimestampFormatString("[hh:mm:ss]"); - - // BufferView / NickView settings - UiStyleSettings s; - _showBufferViewIcons = _showNickViewIcons = s.value("ShowItemViewIcons", true).toBool(); - s.notify("ShowItemViewIcons", this, SLOT(showItemViewIconsChanged(QVariant))); - - _allowMircColors = s.value("AllowMircColors", true).toBool(); - s.notify("AllowMircColors", this, SLOT(allowMircColorsChanged(QVariant))); - - loadStyleSheet(); -} - -UiStyle::~UiStyle() { - qDeleteAll(_metricsCache); -} - -void UiStyle::reload() { - loadStyleSheet(); -} - -void UiStyle::loadStyleSheet() { - qDeleteAll(_metricsCache); - _metricsCache.clear(); - _formatCache.clear(); - _formats.clear(); - - UiStyleSettings s; - - QString styleSheet; - styleSheet += loadStyleSheet("file:///" + Quassel::findDataFilePath("stylesheets/default.qss")); - styleSheet += loadStyleSheet("file:///" + Quassel::configDirPath() + "settings.qss"); - if(s.value("UseCustomStyleSheet", false).toBool()) - styleSheet += loadStyleSheet("file:///" + s.value("CustomStyleSheetPath").toString(), true); - styleSheet += loadStyleSheet("file:///" + Quassel::optionValue("qss"), true); - - if(!styleSheet.isEmpty()) { - QssParser parser; - parser.processStyleSheet(styleSheet); - QApplication::setPalette(parser.palette()); - - _uiStylePalette = parser.uiStylePalette(); - _formats = parser.formats(); - _listItemFormats = parser.listItemFormats(); - - styleSheet = styleSheet.trimmed(); - if(!styleSheet.isEmpty()) - qApp->setStyleSheet(styleSheet); // pass the remaining sections to the application - } - - emit changed(); -} - -QString UiStyle::loadStyleSheet(const QString &styleSheet, bool shouldExist) { - QString ss = styleSheet; - if(ss.startsWith("file:///")) { - ss.remove(0, 8); - if(ss.isEmpty()) - return QString(); - - QFile file(ss); - if(file.open(QFile::ReadOnly)) { - QTextStream stream(&file); - ss = stream.readAll(); - file.close(); - } else { - if(shouldExist) - qWarning() << "Could not open stylesheet file:" << file.fileName(); - return QString(); + : QObject(parent), + _channelJoinedIcon(SmallIcon("irc-channel-active")), + _channelPartedIcon(SmallIcon("irc-channel-inactive")), + _userOfflineIcon(SmallIcon("im-user-offline")), + _userOnlineIcon(SmallIcon("im-user")), + _userAwayIcon(SmallIcon("im-user-away")), + _categoryOpIcon(SmallIcon("irc-operator")), + _categoryVoiceIcon(SmallIcon("irc-voice")), + _opIconLimit(UserCategoryItem::categoryFromModes("o")), + _voiceIconLimit(UserCategoryItem::categoryFromModes("v")) +{ + // register FormatList if that hasn't happened yet + // FIXME I don't think this actually avoids double registration... then again... does it hurt? + if (QVariant::nameToType("UiStyle::FormatList") == QVariant::Invalid) { + qRegisterMetaType("UiStyle::FormatList"); + qRegisterMetaTypeStreamOperators("UiStyle::FormatList"); + Q_ASSERT(QVariant::nameToType("UiStyle::FormatList") != QVariant::Invalid); } - } - return ss; + + _uiStylePalette = QVector(NumRoles, QBrush()); + + // Now initialize the mapping between FormatCodes and FormatTypes... + _formatCodes["%O"] = Base; + _formatCodes["%B"] = Bold; + _formatCodes["%S"] = Italic; + _formatCodes["%U"] = Underline; + _formatCodes["%R"] = Reverse; + + _formatCodes["%DN"] = Nick; + _formatCodes["%DH"] = Hostmask; + _formatCodes["%DC"] = ChannelName; + _formatCodes["%DM"] = ModeFlags; + _formatCodes["%DU"] = Url; + + setTimestampFormatString("[hh:mm:ss]"); + + // BufferView / NickView settings + UiStyleSettings s; + _showBufferViewIcons = _showNickViewIcons = s.value("ShowItemViewIcons", true).toBool(); + s.notify("ShowItemViewIcons", this, SLOT(showItemViewIconsChanged(QVariant))); + + _allowMircColors = s.value("AllowMircColors", true).toBool(); + s.notify("AllowMircColors", this, SLOT(allowMircColorsChanged(QVariant))); + + loadStyleSheet(); } -void UiStyle::setTimestampFormatString(const QString &format) { - if(_timestampFormatString != format) { - _timestampFormatString = format; - // FIXME reload - } + +UiStyle::~UiStyle() +{ + qDeleteAll(_metricsCache); } -void UiStyle::allowMircColorsChanged(const QVariant &v) { - _allowMircColors = v.toBool(); - emit changed(); + +void UiStyle::reload() +{ + loadStyleSheet(); +} + + +void UiStyle::loadStyleSheet() +{ + qDeleteAll(_metricsCache); + _metricsCache.clear(); + _formatCache.clear(); + _formats.clear(); + + UiStyleSettings s; + + QString styleSheet; + styleSheet += loadStyleSheet("file:///" + Quassel::findDataFilePath("stylesheets/default.qss")); + styleSheet += loadStyleSheet("file:///" + Quassel::configDirPath() + "settings.qss"); + if (s.value("UseCustomStyleSheet", false).toBool()) + styleSheet += loadStyleSheet("file:///" + s.value("CustomStyleSheetPath").toString(), true); + styleSheet += loadStyleSheet("file:///" + Quassel::optionValue("qss"), true); + + if (!styleSheet.isEmpty()) { + QssParser parser; + parser.processStyleSheet(styleSheet); + QApplication::setPalette(parser.palette()); + + _uiStylePalette = parser.uiStylePalette(); + _formats = parser.formats(); + _listItemFormats = parser.listItemFormats(); + + styleSheet = styleSheet.trimmed(); + if (!styleSheet.isEmpty()) + qApp->setStyleSheet(styleSheet); // pass the remaining sections to the application + } + + emit changed(); } -/******** ItemView Styling *******/ -void UiStyle::showItemViewIconsChanged(const QVariant &v) { - _showBufferViewIcons = _showNickViewIcons = v.toBool(); +QString UiStyle::loadStyleSheet(const QString &styleSheet, bool shouldExist) +{ + QString ss = styleSheet; + if (ss.startsWith("file:///")) { + ss.remove(0, 8); + if (ss.isEmpty()) + return QString(); + + QFile file(ss); + if (file.open(QFile::ReadOnly)) { + QTextStream stream(&file); + ss = stream.readAll(); + file.close(); + } + else { + if (shouldExist) + qWarning() << "Could not open stylesheet file:" << file.fileName(); + return QString(); + } + } + return ss; } -QVariant UiStyle::bufferViewItemData(const QModelIndex &index, int role) const { - BufferInfo::Type type = (BufferInfo::Type)index.data(NetworkModel::BufferTypeRole).toInt(); - bool isActive = index.data(NetworkModel::ItemActiveRole).toBool(); - if(role == Qt::DecorationRole) { - if(!_showBufferViewIcons) - return QVariant(); +void UiStyle::setTimestampFormatString(const QString &format) +{ + if (_timestampFormatString != format) { + _timestampFormatString = format; + // FIXME reload + } +} - switch(type) { - case BufferInfo::ChannelBuffer: - if(isActive) - return _channelJoinedIcon; - else - return _channelPartedIcon; - case BufferInfo::QueryBuffer: - if(!isActive) - return _userOfflineIcon; - if(index.data(NetworkModel::UserAwayRole).toBool()) - return _userAwayIcon; - else - return _userOnlineIcon; - default: - return QVariant(); + +void UiStyle::allowMircColorsChanged(const QVariant &v) +{ + _allowMircColors = v.toBool(); + emit changed(); +} + + +/******** ItemView Styling *******/ + +void UiStyle::showItemViewIconsChanged(const QVariant &v) +{ + _showBufferViewIcons = _showNickViewIcons = v.toBool(); +} + + +QVariant UiStyle::bufferViewItemData(const QModelIndex &index, int role) const +{ + BufferInfo::Type type = (BufferInfo::Type)index.data(NetworkModel::BufferTypeRole).toInt(); + bool isActive = index.data(NetworkModel::ItemActiveRole).toBool(); + + if (role == Qt::DecorationRole) { + if (!_showBufferViewIcons) + return QVariant(); + + switch (type) { + case BufferInfo::ChannelBuffer: + if (isActive) + return _channelJoinedIcon; + else + return _channelPartedIcon; + case BufferInfo::QueryBuffer: + if (!isActive) + return _userOfflineIcon; + if (index.data(NetworkModel::UserAwayRole).toBool()) + return _userAwayIcon; + else + return _userOnlineIcon; + default: + return QVariant(); + } } - } - quint32 fmtType = BufferViewItem; - switch(type) { + quint32 fmtType = BufferViewItem; + switch (type) { case BufferInfo::StatusBuffer: - fmtType |= NetworkItem; - break; + fmtType |= NetworkItem; + break; case BufferInfo::ChannelBuffer: - fmtType |= ChannelBufferItem; - break; + fmtType |= ChannelBufferItem; + break; case BufferInfo::QueryBuffer: - fmtType |= QueryBufferItem; - break; + fmtType |= QueryBufferItem; + break; default: - return QVariant(); - } - - QTextCharFormat fmt = _listItemFormats.value(BufferViewItem); - fmt.merge(_listItemFormats.value(fmtType)); - - BufferInfo::ActivityLevel activity = (BufferInfo::ActivityLevel)index.data(NetworkModel::BufferActivityRole).toInt(); - if(activity & BufferInfo::Highlight) { - fmt.merge(_listItemFormats.value(BufferViewItem | HighlightedBuffer)); - fmt.merge(_listItemFormats.value(fmtType | HighlightedBuffer)); - } else if(activity & BufferInfo::NewMessage) { - fmt.merge(_listItemFormats.value(BufferViewItem | UnreadBuffer)); - fmt.merge(_listItemFormats.value(fmtType | UnreadBuffer)); - } else if(activity & BufferInfo::OtherActivity) { - fmt.merge(_listItemFormats.value(BufferViewItem | ActiveBuffer)); - fmt.merge(_listItemFormats.value(fmtType | ActiveBuffer)); - } else if(!isActive) { - fmt.merge(_listItemFormats.value(BufferViewItem | InactiveBuffer)); - fmt.merge(_listItemFormats.value(fmtType | InactiveBuffer)); - } else if(index.data(NetworkModel::UserAwayRole).toBool()) { - fmt.merge(_listItemFormats.value(BufferViewItem | UserAway)); - fmt.merge(_listItemFormats.value(fmtType | UserAway)); - } - - return itemData(role, fmt); -} - -QVariant UiStyle::nickViewItemData(const QModelIndex &index, int role) const { - NetworkModel::ItemType type = (NetworkModel::ItemType)index.data(NetworkModel::ItemTypeRole).toInt(); - - if(role == Qt::DecorationRole) { - if(!_showNickViewIcons) - return QVariant(); - - switch(type) { - case NetworkModel::UserCategoryItemType: - { - int categoryId = index.data(TreeModel::SortRole).toInt(); - if(categoryId <= _opIconLimit) - return _categoryOpIcon; - if(categoryId <= _voiceIconLimit) - return _categoryVoiceIcon; - return _userOnlineIcon; - } - case NetworkModel::IrcUserItemType: - if(index.data(NetworkModel::ItemActiveRole).toBool()) - return _userOnlineIcon; - else - return _userAwayIcon; - default: return QVariant(); } - } - QTextCharFormat fmt = _listItemFormats.value(NickViewItem); + QTextCharFormat fmt = _listItemFormats.value(BufferViewItem); + fmt.merge(_listItemFormats.value(fmtType)); + + BufferInfo::ActivityLevel activity = (BufferInfo::ActivityLevel)index.data(NetworkModel::BufferActivityRole).toInt(); + if (activity & BufferInfo::Highlight) { + fmt.merge(_listItemFormats.value(BufferViewItem | HighlightedBuffer)); + fmt.merge(_listItemFormats.value(fmtType | HighlightedBuffer)); + } + else if (activity & BufferInfo::NewMessage) { + fmt.merge(_listItemFormats.value(BufferViewItem | UnreadBuffer)); + fmt.merge(_listItemFormats.value(fmtType | UnreadBuffer)); + } + else if (activity & BufferInfo::OtherActivity) { + fmt.merge(_listItemFormats.value(BufferViewItem | ActiveBuffer)); + fmt.merge(_listItemFormats.value(fmtType | ActiveBuffer)); + } + else if (!isActive) { + fmt.merge(_listItemFormats.value(BufferViewItem | InactiveBuffer)); + fmt.merge(_listItemFormats.value(fmtType | InactiveBuffer)); + } + else if (index.data(NetworkModel::UserAwayRole).toBool()) { + fmt.merge(_listItemFormats.value(BufferViewItem | UserAway)); + fmt.merge(_listItemFormats.value(fmtType | UserAway)); + } + + return itemData(role, fmt); +} + + +QVariant UiStyle::nickViewItemData(const QModelIndex &index, int role) const +{ + NetworkModel::ItemType type = (NetworkModel::ItemType)index.data(NetworkModel::ItemTypeRole).toInt(); + + if (role == Qt::DecorationRole) { + if (!_showNickViewIcons) + return QVariant(); + + switch (type) { + case NetworkModel::UserCategoryItemType: + { + int categoryId = index.data(TreeModel::SortRole).toInt(); + if (categoryId <= _opIconLimit) + return _categoryOpIcon; + if (categoryId <= _voiceIconLimit) + return _categoryVoiceIcon; + return _userOnlineIcon; + } + case NetworkModel::IrcUserItemType: + if (index.data(NetworkModel::ItemActiveRole).toBool()) + return _userOnlineIcon; + else + return _userAwayIcon; + default: + return QVariant(); + } + } + + QTextCharFormat fmt = _listItemFormats.value(NickViewItem); - switch(type) { + switch (type) { case NetworkModel::IrcUserItemType: - fmt.merge(_listItemFormats.value(NickViewItem | IrcUserItem)); - if(!index.data(NetworkModel::ItemActiveRole).toBool()) { - fmt.merge(_listItemFormats.value(NickViewItem | UserAway)); - fmt.merge(_listItemFormats.value(NickViewItem | IrcUserItem | UserAway)); - } - break; + fmt.merge(_listItemFormats.value(NickViewItem | IrcUserItem)); + if (!index.data(NetworkModel::ItemActiveRole).toBool()) { + fmt.merge(_listItemFormats.value(NickViewItem | UserAway)); + fmt.merge(_listItemFormats.value(NickViewItem | IrcUserItem | UserAway)); + } + break; case NetworkModel::UserCategoryItemType: - fmt.merge(_listItemFormats.value(NickViewItem | UserCategoryItem)); - break; + fmt.merge(_listItemFormats.value(NickViewItem | UserCategoryItem)); + break; default: - return QVariant(); - } + return QVariant(); + } - return itemData(role, fmt); + return itemData(role, fmt); } -QVariant UiStyle::itemData(int role, const QTextCharFormat &format) const { - switch(role) { + +QVariant UiStyle::itemData(int role, const QTextCharFormat &format) const +{ + switch (role) { case Qt::FontRole: - return format.font(); + return format.font(); case Qt::ForegroundRole: - return format.property(QTextFormat::ForegroundBrush); + return format.property(QTextFormat::ForegroundBrush); case Qt::BackgroundRole: - return format.property(QTextFormat::BackgroundBrush); + return format.property(QTextFormat::BackgroundBrush); default: - return QVariant(); - } + return QVariant(); + } } + /******** Caching *******/ -QTextCharFormat UiStyle::format(quint64 key) const { - return _formats.value(key, QTextCharFormat()); +QTextCharFormat UiStyle::format(quint64 key) const +{ + return _formats.value(key, QTextCharFormat()); } -QTextCharFormat UiStyle::cachedFormat(quint32 formatType, quint32 messageLabel) const { - return _formatCache.value(formatType | ((quint64)messageLabel << 32), QTextCharFormat()); + +QTextCharFormat UiStyle::cachedFormat(quint32 formatType, quint32 messageLabel) const +{ + return _formatCache.value(formatType | ((quint64)messageLabel << 32), QTextCharFormat()); } -void UiStyle::setCachedFormat(const QTextCharFormat &format, quint32 formatType, quint32 messageLabel) const { - _formatCache[formatType | ((quint64)messageLabel << 32)] = format; + +void UiStyle::setCachedFormat(const QTextCharFormat &format, quint32 formatType, quint32 messageLabel) const +{ + _formatCache[formatType | ((quint64)messageLabel << 32)] = format; } -QFontMetricsF *UiStyle::fontMetrics(quint32 ftype, quint32 label) const { - // QFontMetricsF is not assignable, so we need to store pointers :/ - quint64 key = ftype | ((quint64)label << 32); - if(_metricsCache.contains(key)) - return _metricsCache.value(key); +QFontMetricsF *UiStyle::fontMetrics(quint32 ftype, quint32 label) const +{ + // QFontMetricsF is not assignable, so we need to store pointers :/ + quint64 key = ftype | ((quint64)label << 32); - return (_metricsCache[key] = new QFontMetricsF(format(ftype, label).font())); + if (_metricsCache.contains(key)) + return _metricsCache.value(key); + + return (_metricsCache[key] = new QFontMetricsF(format(ftype, label).font())); } + /******** Generate formats ********/ // NOTE: This and the following functions are intimately tied to the values in FormatType. Don't change this // until you _really_ know what you do! -QTextCharFormat UiStyle::format(quint32 ftype, quint32 label_) const { - if(ftype == Invalid) - return QTextCharFormat(); +QTextCharFormat UiStyle::format(quint32 ftype, quint32 label_) const +{ + if (ftype == Invalid) + return QTextCharFormat(); - quint64 label = (quint64)label_ << 32; + quint64 label = (quint64)label_ << 32; - // check if we have exactly this format readily cached already - QTextCharFormat fmt = cachedFormat(ftype, label_); - if(fmt.properties().count()) - return fmt; + // check if we have exactly this format readily cached already + QTextCharFormat fmt = cachedFormat(ftype, label_); + if (fmt.properties().count()) + return fmt; - mergeFormat(fmt, ftype, label & Q_UINT64_C(0xffff000000000000)); + mergeFormat(fmt, ftype, label & Q_UINT64_C(0xffff000000000000)); - for(quint64 mask = Q_UINT64_C(0x0000000100000000); mask <= (quint64)Selected << 32; mask <<=1) { - if(label & mask) - mergeFormat(fmt, ftype, mask | Q_UINT64_C(0xffff000000000000)); - } + for (quint64 mask = Q_UINT64_C(0x0000000100000000); mask <= (quint64)Selected << 32; mask <<= 1) { + if (label & mask) + mergeFormat(fmt, ftype, mask | Q_UINT64_C(0xffff000000000000)); + } - setCachedFormat(fmt, ftype, label_); - return fmt; + setCachedFormat(fmt, ftype, label_); + return fmt; } -void UiStyle::mergeFormat(QTextCharFormat &fmt, quint32 ftype, quint64 label) const { - mergeSubElementFormat(fmt, ftype & 0x00ff, label); - // TODO: allow combinations for mirc formats and colors (each), e.g. setting a special format for "bold and italic" - // or "foreground 01 and background 03" - if((ftype & 0xfff00)) { // element format - for(quint32 mask = 0x00100; mask <= 0x40000; mask <<= 1) { - if(ftype & mask) { - mergeSubElementFormat(fmt, ftype & (mask | 0xff), label); - } +void UiStyle::mergeFormat(QTextCharFormat &fmt, quint32 ftype, quint64 label) const +{ + mergeSubElementFormat(fmt, ftype & 0x00ff, label); + + // TODO: allow combinations for mirc formats and colors (each), e.g. setting a special format for "bold and italic" + // or "foreground 01 and background 03" + if ((ftype & 0xfff00)) { // element format + for (quint32 mask = 0x00100; mask <= 0x40000; mask <<= 1) { + if (ftype & mask) { + mergeSubElementFormat(fmt, ftype & (mask | 0xff), label); + } + } } - } - // Now we handle color codes - // We assume that those can't be combined with subelement and message types. - if(_allowMircColors) { - if(ftype & 0x00400000) - mergeSubElementFormat(fmt, ftype & 0x0f400000, label); // foreground - if(ftype & 0x00800000) - mergeSubElementFormat(fmt, ftype & 0xf0800000, label); // background - if((ftype & 0x00c00000) == 0x00c00000) - mergeSubElementFormat(fmt, ftype & 0xffc00000, label); // combination - } + // Now we handle color codes + // We assume that those can't be combined with subelement and message types. + if (_allowMircColors) { + if (ftype & 0x00400000) + mergeSubElementFormat(fmt, ftype & 0x0f400000, label); // foreground + if (ftype & 0x00800000) + mergeSubElementFormat(fmt, ftype & 0xf0800000, label); // background + if ((ftype & 0x00c00000) == 0x00c00000) + mergeSubElementFormat(fmt, ftype & 0xffc00000, label); // combination + } - // URL - if(ftype & Url) - mergeSubElementFormat(fmt, ftype & (Url | 0x000000ff), label); + // URL + if (ftype & Url) + mergeSubElementFormat(fmt, ftype & (Url | 0x000000ff), label); } + // Merge a subelement format into an existing message format -void UiStyle::mergeSubElementFormat(QTextCharFormat& fmt, quint32 ftype, quint64 label) const { - quint64 key = ftype | label; - fmt.merge(format(key & Q_UINT64_C(0x0000ffffffffff00))); // label + subelement - fmt.merge(format(key & Q_UINT64_C(0x0000ffffffffffff))); // label + subelement + msgtype - fmt.merge(format(key & Q_UINT64_C(0xffffffffffffff00))); // label + subelement + nickhash - fmt.merge(format(key & Q_UINT64_C(0xffffffffffffffff))); // label + subelement + nickhash + msgtype +void UiStyle::mergeSubElementFormat(QTextCharFormat &fmt, quint32 ftype, quint64 label) const +{ + quint64 key = ftype | label; + fmt.merge(format(key & Q_UINT64_C(0x0000ffffffffff00))); // label + subelement + fmt.merge(format(key & Q_UINT64_C(0x0000ffffffffffff))); // label + subelement + msgtype + fmt.merge(format(key & Q_UINT64_C(0xffffffffffffff00))); // label + subelement + nickhash + fmt.merge(format(key & Q_UINT64_C(0xffffffffffffffff))); // label + subelement + nickhash + msgtype } -UiStyle::FormatType UiStyle::formatType(Message::Type msgType) { - switch(msgType) { + +UiStyle::FormatType UiStyle::formatType(Message::Type msgType) +{ + switch (msgType) { case Message::Plain: - return PlainMsg; + return PlainMsg; case Message::Notice: - return NoticeMsg; + return NoticeMsg; case Message::Action: - return ActionMsg; + return ActionMsg; case Message::Nick: - return NickMsg; + return NickMsg; case Message::Mode: - return ModeMsg; + return ModeMsg; case Message::Join: - return JoinMsg; + return JoinMsg; case Message::Part: - return PartMsg; + return PartMsg; case Message::Quit: - return QuitMsg; + return QuitMsg; case Message::Kick: - return KickMsg; + return KickMsg; case Message::Kill: - return KillMsg; + return KillMsg; case Message::Server: - return ServerMsg; + return ServerMsg; case Message::Info: - return InfoMsg; + return InfoMsg; case Message::Error: - return ErrorMsg; + return ErrorMsg; case Message::DayChange: - return DayChangeMsg; + return DayChangeMsg; case Message::Topic: - return TopicMsg; + return TopicMsg; case Message::NetsplitJoin: - return NetsplitJoinMsg; + return NetsplitJoinMsg; case Message::NetsplitQuit: - return NetsplitQuitMsg; + return NetsplitQuitMsg; case Message::Invite: - return InviteMsg; - } - //Q_ASSERT(false); // we need to handle all message types - qWarning() << Q_FUNC_INFO << "Unknown message type:" << msgType; - return ErrorMsg; + return InviteMsg; + } + //Q_ASSERT(false); // we need to handle all message types + qWarning() << Q_FUNC_INFO << "Unknown message type:" << msgType; + return ErrorMsg; } -UiStyle::FormatType UiStyle::formatType(const QString & code) { - if(_formatCodes.contains(code)) return _formatCodes.value(code); - return Invalid; + +UiStyle::FormatType UiStyle::formatType(const QString &code) +{ + if (_formatCodes.contains(code)) return _formatCodes.value(code); + return Invalid; } -QString UiStyle::formatCode(FormatType ftype) { - return _formatCodes.key(ftype); + +QString UiStyle::formatCode(FormatType ftype) +{ + return _formatCodes.key(ftype); } -QList UiStyle::toTextLayoutList(const FormatList &formatList, int textLength, quint32 messageLabel) const { - QList formatRanges; - QTextLayout::FormatRange range; - int i = 0; - for(i = 0; i < formatList.count(); i++) { - range.format = format(formatList.at(i).second, messageLabel); - range.start = formatList.at(i).first; - if(i > 0) formatRanges.last().length = range.start - formatRanges.last().start; - formatRanges.append(range); - } - if(i > 0) formatRanges.last().length = textLength - formatRanges.last().start; - return formatRanges; + +QList UiStyle::toTextLayoutList(const FormatList &formatList, int textLength, quint32 messageLabel) const +{ + QList formatRanges; + QTextLayout::FormatRange range; + int i = 0; + for (i = 0; i < formatList.count(); i++) { + range.format = format(formatList.at(i).second, messageLabel); + range.start = formatList.at(i).first; + if (i > 0) formatRanges.last().length = range.start - formatRanges.last().start; + formatRanges.append(range); + } + if (i > 0) formatRanges.last().length = textLength - formatRanges.last().start; + return formatRanges; } + // This method expects a well-formatted string, there is no error checking! // Since we create those ourselves, we should be pretty safe that nobody does something crappy here. -UiStyle::StyledString UiStyle::styleString(const QString &s_, quint32 baseFormat) { - QString s = s_; - if(s.length() > 65535) { - qWarning() << QString("String too long to be styled: %1").arg(s); - return StyledString(); - } - StyledString result; - result.formatList.append(qMakePair((quint16)0, baseFormat)); - quint32 curfmt = baseFormat; - int pos = 0; quint16 length = 0; - for(;;) { - pos = s.indexOf('%', pos); - if(pos < 0) break; - if(s[pos+1] == '%') { // escaped %, we just remove one and continue - s.remove(pos, 1); - pos++; - continue; +UiStyle::StyledString UiStyle::styleString(const QString &s_, quint32 baseFormat) +{ + QString s = s_; + if (s.length() > 65535) { + qWarning() << QString("String too long to be styled: %1").arg(s); + return StyledString(); } - if(s[pos+1] == 'D' && s[pos+2] == 'c') { // color code - if(s[pos+3] == '-') { // color off - curfmt &= 0x003fffff; - length = 4; - } else { - int color = 10 * s[pos+4].digitValue() + s[pos+5].digitValue(); - //TODO: use 99 as transparent color (re mirc color "standard") - color &= 0x0f; - if(s[pos+3] == 'f') { - curfmt &= 0xf0ffffff; - curfmt |= (quint32)(color << 24) | 0x00400000; - } else { - curfmt &= 0x0fffffff; - curfmt |= (quint32)(color << 28) | 0x00800000; + StyledString result; + result.formatList.append(qMakePair((quint16)0, baseFormat)); + quint32 curfmt = baseFormat; + int pos = 0; quint16 length = 0; + for (;;) { + pos = s.indexOf('%', pos); + if (pos < 0) break; + if (s[pos+1] == '%') { // escaped %, we just remove one and continue + s.remove(pos, 1); + pos++; + continue; } - length = 6; - } - } else if(s[pos+1] == 'O') { // reset formatting - curfmt &= 0x000000ff; // we keep message type-specific formatting - length = 2; - } else if(s[pos+1] == 'R') { // reverse - // TODO: implement reverse formatting - - length = 2; - } else { // all others are toggles - QString code = QString("%") + s[pos+1]; - if(s[pos+1] == 'D') code += s[pos+2]; - FormatType ftype = formatType(code); - if(ftype == Invalid) { - pos++; - qWarning() << (QString("Invalid format code in string: %1").arg(s)); - continue; - } - curfmt ^= ftype; - length = code.length(); + if (s[pos+1] == 'D' && s[pos+2] == 'c') { // color code + if (s[pos+3] == '-') { // color off + curfmt &= 0x003fffff; + length = 4; + } + else { + int color = 10 * s[pos+4].digitValue() + s[pos+5].digitValue(); + //TODO: use 99 as transparent color (re mirc color "standard") + color &= 0x0f; + if (s[pos+3] == 'f') { + curfmt &= 0xf0ffffff; + curfmt |= (quint32)(color << 24) | 0x00400000; + } + else { + curfmt &= 0x0fffffff; + curfmt |= (quint32)(color << 28) | 0x00800000; + } + length = 6; + } + } + else if (s[pos+1] == 'O') { // reset formatting + curfmt &= 0x000000ff; // we keep message type-specific formatting + length = 2; + } + else if (s[pos+1] == 'R') { // reverse + // TODO: implement reverse formatting + + length = 2; + } + else { // all others are toggles + QString code = QString("%") + s[pos+1]; + if (s[pos+1] == 'D') code += s[pos+2]; + FormatType ftype = formatType(code); + if (ftype == Invalid) { + pos++; + qWarning() << (QString("Invalid format code in string: %1").arg(s)); + continue; + } + curfmt ^= ftype; + length = code.length(); + } + s.remove(pos, length); + if (pos == result.formatList.last().first) + result.formatList.last().second = curfmt; + else + result.formatList.append(qMakePair((quint16)pos, curfmt)); } - s.remove(pos, length); - if(pos == result.formatList.last().first) - result.formatList.last().second = curfmt; - else - result.formatList.append(qMakePair((quint16)pos, curfmt)); - } - result.plainText = s; - return result; -} - -QString UiStyle::mircToInternal(const QString &mirc_) { - QString mirc = mirc_; - mirc.replace('%', "%%"); // escape % just to be sure - mirc.replace('\t', " "); // tabs break layout, also this is italics in Konversation - mirc.replace('\x02', "%B"); - mirc.replace('\x0f', "%O"); - mirc.replace('\x12', "%R"); - mirc.replace('\x16', "%R"); - mirc.replace('\x1d', "%S"); - mirc.replace('\x1f', "%U"); - - // Now we bring the color codes (\x03) in a sane format that can be parsed more easily later. - // %Dcfxx is foreground, %Dcbxx is background color, where xx is a 2 digit dec number denoting the color code. - // %Dc- turns color off. - // Note: We use the "mirc standard" as described in . - // This means that we don't accept something like \x03,5 (even though others, like WeeChat, do). - int pos = 0; - for(;;) { - pos = mirc.indexOf('\x03', pos); - if(pos < 0) break; // no more mirc color codes - QString ins, num; - int l = mirc.length(); - int i = pos + 1; - // check for fg color - if(i < l && mirc[i].isDigit()) { - num = mirc[i++]; - if(i < l && mirc[i].isDigit()) num.append(mirc[i++]); - else num.prepend('0'); - ins = QString("%Dcf%1").arg(num); - - if(i+1 < l && mirc[i] == ',' && mirc[i+1].isDigit()) { - i++; - num = mirc[i++]; - if(i < l && mirc[i].isDigit()) num.append(mirc[i++]); - else num.prepend('0'); - ins += QString("%Dcb%1").arg(num); - } - } else { - ins = "%Dc-"; + result.plainText = s; + return result; +} + + +QString UiStyle::mircToInternal(const QString &mirc_) +{ + QString mirc = mirc_; + mirc.replace('%', "%%"); // escape % just to be sure + mirc.replace('\t', " "); // tabs break layout, also this is italics in Konversation + mirc.replace('\x02', "%B"); + mirc.replace('\x0f', "%O"); + mirc.replace('\x12', "%R"); + mirc.replace('\x16', "%R"); + mirc.replace('\x1d', "%S"); + mirc.replace('\x1f', "%U"); + + // Now we bring the color codes (\x03) in a sane format that can be parsed more easily later. + // %Dcfxx is foreground, %Dcbxx is background color, where xx is a 2 digit dec number denoting the color code. + // %Dc- turns color off. + // Note: We use the "mirc standard" as described in . + // This means that we don't accept something like \x03,5 (even though others, like WeeChat, do). + int pos = 0; + for (;;) { + pos = mirc.indexOf('\x03', pos); + if (pos < 0) break; // no more mirc color codes + QString ins, num; + int l = mirc.length(); + int i = pos + 1; + // check for fg color + if (i < l && mirc[i].isDigit()) { + num = mirc[i++]; + if (i < l && mirc[i].isDigit()) num.append(mirc[i++]); + else num.prepend('0'); + ins = QString("%Dcf%1").arg(num); + + if (i+1 < l && mirc[i] == ',' && mirc[i+1].isDigit()) { + i++; + num = mirc[i++]; + if (i < l && mirc[i].isDigit()) num.append(mirc[i++]); + else num.prepend('0'); + ins += QString("%Dcb%1").arg(num); + } + } + else { + ins = "%Dc-"; + } + mirc.replace(pos, i-pos, ins); } - mirc.replace(pos, i-pos, ins); - } - return mirc; + return mirc; } + /***********************************************************************************/ UiStyle::StyledMessage::StyledMessage(const Message &msg) - : Message(msg) -{ - if(type() == Message::Plain) - _senderHash = 0xff; - else - _senderHash = 0x00; // this means we never compute the hash for msgs that aren't plain -} - -void UiStyle::StyledMessage::style() const { - QString user = userFromMask(sender()); - QString host = hostFromMask(sender()); - QString nick = nickFromMask(sender()); - QString txt = UiStyle::mircToInternal(contents()); - QString bufferName = bufferInfo().bufferName(); - bufferName.replace('%', "%%"); // well, you _can_ have a % in a buffername apparently... -_- - host.replace('%', "%%"); // hostnames too... - user.replace('%', "%%"); // and the username... - nick.replace('%', "%%"); // ... and then there's totally RFC-violating servers like justin.tv m( - const int maxNetsplitNicks = 15; - - QString t; - switch(type()) { + : Message(msg) +{ + if (type() == Message::Plain) + _senderHash = 0xff; + else + _senderHash = 0x00; // this means we never compute the hash for msgs that aren't plain +} + + +void UiStyle::StyledMessage::style() const +{ + QString user = userFromMask(sender()); + QString host = hostFromMask(sender()); + QString nick = nickFromMask(sender()); + QString txt = UiStyle::mircToInternal(contents()); + QString bufferName = bufferInfo().bufferName(); + bufferName.replace('%', "%%"); // well, you _can_ have a % in a buffername apparently... -_- + host.replace('%', "%%"); // hostnames too... + user.replace('%', "%%"); // and the username... + nick.replace('%', "%%"); // ... and then there's totally RFC-violating servers like justin.tv m( + const int maxNetsplitNicks = 15; + + QString t; + switch (type()) { case Message::Plain: - //: Plain Message - t = tr("%1").arg(txt); break; + //: Plain Message + t = tr("%1").arg(txt); break; case Message::Notice: - //: Notice Message - t = tr("%1").arg(txt); break; + //: Notice Message + t = tr("%1").arg(txt); break; case Message::Action: - //: Action Message - t = tr("%DN%1%DN %2").arg(nick).arg(txt); - break; + //: Action Message + t = tr("%DN%1%DN %2").arg(nick).arg(txt); + break; case Message::Nick: - //: Nick Message - if(nick == contents()) t = tr("You are now known as %DN%1%DN").arg(txt); - else t = tr("%DN%1%DN is now known as %DN%2%DN").arg(nick, txt); - break; + //: Nick Message + if (nick == contents()) t = tr("You are now known as %DN%1%DN").arg(txt); + else t = tr("%DN%1%DN is now known as %DN%2%DN").arg(nick, txt); + break; case Message::Mode: - //: Mode Message - if(nick.isEmpty()) t = tr("User mode: %DM%1%DM").arg(txt); - else t = tr("Mode %DM%1%DM by %DN%2%DN").arg(txt, nick); - break; + //: Mode Message + if (nick.isEmpty()) t = tr("User mode: %DM%1%DM").arg(txt); + else t = tr("Mode %DM%1%DM by %DN%2%DN").arg(txt, nick); + break; case Message::Join: - //: Join Message - t = tr("%DN%1%DN %DH(%2@%3)%DH has joined %DC%4%DC").arg(nick, user, host, bufferName); break; + //: Join Message + t = tr("%DN%1%DN %DH(%2@%3)%DH has joined %DC%4%DC").arg(nick, user, host, bufferName); break; case Message::Part: - //: Part Message - t = tr("%DN%1%DN %DH(%2@%3)%DH has left %DC%4%DC").arg(nick, user, host, bufferName); - if(!txt.isEmpty()) t = QString("%1 (%2)").arg(t).arg(txt); - break; + //: Part Message + t = tr("%DN%1%DN %DH(%2@%3)%DH has left %DC%4%DC").arg(nick, user, host, bufferName); + if (!txt.isEmpty()) t = QString("%1 (%2)").arg(t).arg(txt); + break; case Message::Quit: - //: Quit Message - t = tr("%DN%1%DN %DH(%2@%3)%DH has quit").arg(nick, user, host); - if(!txt.isEmpty()) t = QString("%1 (%2)").arg(t).arg(txt); - break; - case Message::Kick: { + //: Quit Message + t = tr("%DN%1%DN %DH(%2@%3)%DH has quit").arg(nick, user, host); + if (!txt.isEmpty()) t = QString("%1 (%2)").arg(t).arg(txt); + break; + case Message::Kick: + { QString victim = txt.section(" ", 0, 0); QString kickmsg = txt.section(" ", 1); //: Kick Message t = tr("%DN%1%DN has kicked %DN%2%DN from %DC%3%DC").arg(nick).arg(victim).arg(bufferName); - if(!kickmsg.isEmpty()) t = QString("%1 (%2)").arg(t).arg(kickmsg); - } - break; + if (!kickmsg.isEmpty()) t = QString("%1 (%2)").arg(t).arg(kickmsg); + } + break; //case Message::Kill: FIXME case Message::Server: - //: Server Message - t = tr("%1").arg(txt); break; + //: Server Message + t = tr("%1").arg(txt); break; case Message::Info: - //: Info Message - t = tr("%1").arg(txt); break; + //: Info Message + t = tr("%1").arg(txt); break; case Message::Error: - //: Error Message - t = tr("%1").arg(txt); break; + //: Error Message + t = tr("%1").arg(txt); break; case Message::DayChange: - //: Day Change Message - t = tr("{Day changed to %1}").arg(timestamp().toString()); - break; + //: Day Change Message + t = tr("{Day changed to %1}").arg(timestamp().toString()); + break; case Message::Topic: - //: Topic Message - t = tr("%1").arg(txt); break; - case Message::NetsplitJoin: { - QStringList users = txt.split("#:#"); - QStringList servers = users.takeLast().split(" "); - - for(int i = 0; i < users.count() && i < maxNetsplitNicks; i++) - users[i] = nickFromMask(users.at(i)); - - t = tr("Netsplit between %DH%1%DH and %DH%2%DH ended. Users joined: ").arg(servers.at(0),servers.at(1)); - if(users.count() <= maxNetsplitNicks) - t.append(QString("%DN%1%DN").arg(users.join(", "))); - else - t.append(tr("%DN%1%DN (%2 more)").arg(static_cast(users.mid(0, maxNetsplitNicks)).join(", ")).arg(users.count() - maxNetsplitNicks)); - } - break; - case Message::NetsplitQuit: { - QStringList users = txt.split("#:#"); - QStringList servers = users.takeLast().split(" "); - - for(int i = 0; i < users.count() && i < maxNetsplitNicks; i++) - users[i] = nickFromMask(users.at(i)); - - t = tr("Netsplit between %DH%1%DH and %DH%2%DH. Users quit: ").arg(servers.at(0),servers.at(1)); - - if(users.count() <= maxNetsplitNicks) - t.append(QString("%DN%1%DN").arg(users.join(", "))); - else - t.append(tr("%DN%1%DN (%2 more)").arg(static_cast(users.mid(0, maxNetsplitNicks)).join(", ")).arg(users.count() - maxNetsplitNicks)); - } - break; + //: Topic Message + t = tr("%1").arg(txt); break; + case Message::NetsplitJoin: + { + QStringList users = txt.split("#:#"); + QStringList servers = users.takeLast().split(" "); + + for (int i = 0; i < users.count() && i < maxNetsplitNicks; i++) + users[i] = nickFromMask(users.at(i)); + + t = tr("Netsplit between %DH%1%DH and %DH%2%DH ended. Users joined: ").arg(servers.at(0), servers.at(1)); + if (users.count() <= maxNetsplitNicks) + t.append(QString("%DN%1%DN").arg(users.join(", "))); + else + t.append(tr("%DN%1%DN (%2 more)").arg(static_cast(users.mid(0, maxNetsplitNicks)).join(", ")).arg(users.count() - maxNetsplitNicks)); + } + break; + case Message::NetsplitQuit: + { + QStringList users = txt.split("#:#"); + QStringList servers = users.takeLast().split(" "); + + for (int i = 0; i < users.count() && i < maxNetsplitNicks; i++) + users[i] = nickFromMask(users.at(i)); + + t = tr("Netsplit between %DH%1%DH and %DH%2%DH. Users quit: ").arg(servers.at(0), servers.at(1)); + + if (users.count() <= maxNetsplitNicks) + t.append(QString("%DN%1%DN").arg(users.join(", "))); + else + t.append(tr("%DN%1%DN (%2 more)").arg(static_cast(users.mid(0, maxNetsplitNicks)).join(", ")).arg(users.count() - maxNetsplitNicks)); + } + break; case Message::Invite: - //: Invite Message - t = tr("%1").arg(txt); break; + //: Invite Message + t = tr("%1").arg(txt); break; default: - t = tr("[%1]").arg(txt); - } - _contents = UiStyle::styleString(t, UiStyle::formatType(type())); + t = tr("[%1]").arg(txt); + } + _contents = UiStyle::styleString(t, UiStyle::formatType(type())); } -const QString &UiStyle::StyledMessage::plainContents() const { - if(_contents.plainText.isNull()) - style(); - return _contents.plainText; +const QString &UiStyle::StyledMessage::plainContents() const +{ + if (_contents.plainText.isNull()) + style(); + + return _contents.plainText; } -const UiStyle::FormatList &UiStyle::StyledMessage::contentsFormatList() const { - if(_contents.plainText.isNull()) - style(); - return _contents.formatList; +const UiStyle::FormatList &UiStyle::StyledMessage::contentsFormatList() const +{ + if (_contents.plainText.isNull()) + style(); + + return _contents.formatList; } -QString UiStyle::StyledMessage::decoratedTimestamp() const { - return timestamp().toLocalTime().toString(UiStyle::timestampFormatString()); + +QString UiStyle::StyledMessage::decoratedTimestamp() const +{ + return timestamp().toLocalTime().toString(UiStyle::timestampFormatString()); } -QString UiStyle::StyledMessage::plainSender() const { - switch(type()) { + +QString UiStyle::StyledMessage::plainSender() const +{ + switch (type()) { case Message::Plain: case Message::Notice: - return nickFromMask(sender()); + return nickFromMask(sender()); default: - return QString(); - } + return QString(); + } } -QString UiStyle::StyledMessage::decoratedSender() const { - switch(type()) { + +QString UiStyle::StyledMessage::decoratedSender() const +{ + switch (type()) { case Message::Plain: - return tr("<%1>").arg(plainSender()); break; + return tr("<%1>").arg(plainSender()); break; case Message::Notice: - return tr("[%1]").arg(plainSender()); break; + return tr("[%1]").arg(plainSender()); break; case Message::Action: - return "-*-"; break; + return "-*-"; break; case Message::Nick: - return "<->"; break; + return "<->"; break; case Message::Mode: - return "***"; break; + return "***"; break; case Message::Join: - return "-->"; break; + return "-->"; break; case Message::Part: - return "<--"; break; + return "<--"; break; case Message::Quit: - return "<--"; break; + return "<--"; break; case Message::Kick: - return "<-*"; break; + return "<-*"; break; case Message::Kill: - return "<-x"; break; + return "<-x"; break; case Message::Server: - return "*"; break; + return "*"; break; case Message::Info: - return "*"; break; + return "*"; break; case Message::Error: - return "*"; break; + return "*"; break; case Message::DayChange: - return "-"; break; + return "-"; break; case Message::Topic: - return "*"; break; + return "*"; break; case Message::NetsplitJoin: - return "=>"; break; + return "=>"; break; case Message::NetsplitQuit: - return "<="; break; + return "<="; break; case Message::Invite: - return "->"; break; + return "->"; break; default: - return QString("%1").arg(plainSender()); - } + return QString("%1").arg(plainSender()); + } } + // FIXME hardcoded to 16 sender hashes -quint8 UiStyle::StyledMessage::senderHash() const { - if(_senderHash != 0xff) - return _senderHash; - - QString nick = nickFromMask(sender()).toLower(); - if(!nick.isEmpty()) { - int chopCount = 0; - while(chopCount < nick.size() && nick.at(nick.count() - 1 - chopCount) == '_') - chopCount++; - if(chopCount < nick.size()) - nick.chop(chopCount); - } - quint16 hash = qChecksum(nick.toAscii().data(), nick.toAscii().size()); - return (_senderHash = (hash & 0xf) + 1); +quint8 UiStyle::StyledMessage::senderHash() const +{ + if (_senderHash != 0xff) + return _senderHash; + + QString nick = nickFromMask(sender()).toLower(); + if (!nick.isEmpty()) { + int chopCount = 0; + while (chopCount < nick.size() && nick.at(nick.count() - 1 - chopCount) == '_') + chopCount++; + if (chopCount < nick.size()) + nick.chop(chopCount); + } + quint16 hash = qChecksum(nick.toAscii().data(), nick.toAscii().size()); + return (_senderHash = (hash & 0xf) + 1); } + /***********************************************************************************/ -QDataStream &operator<<(QDataStream &out, const UiStyle::FormatList &formatList) { - out << formatList.count(); - UiStyle::FormatList::const_iterator it = formatList.begin(); - while(it != formatList.end()) { - out << (*it).first << (*it).second; - ++it; - } - return out; -} - -QDataStream &operator>>(QDataStream &in, UiStyle::FormatList &formatList) { - quint16 cnt; - in >> cnt; - for(quint16 i = 0; i < cnt; i++) { - quint16 pos; quint32 ftype; - in >> pos >> ftype; - formatList.append(qMakePair((quint16)pos, ftype)); - } - return in; +QDataStream &operator<<(QDataStream &out, const UiStyle::FormatList &formatList) +{ + out << formatList.count(); + UiStyle::FormatList::const_iterator it = formatList.begin(); + while (it != formatList.end()) { + out << (*it).first << (*it).second; + ++it; + } + return out; +} + + +QDataStream &operator>>(QDataStream &in, UiStyle::FormatList &formatList) +{ + quint16 cnt; + in >> cnt; + for (quint16 i = 0; i < cnt; i++) { + quint16 pos; quint32 ftype; + in >> pos >> ftype; + formatList.append(qMakePair((quint16)pos, ftype)); + } + return in; } diff --git a/src/uisupport/uistyle.h b/src/uisupport/uistyle.h index db82c1aa..78bbc819 100644 --- a/src/uisupport/uistyle.h +++ b/src/uisupport/uistyle.h @@ -34,193 +34,197 @@ #include "networkmodel.h" #include "settings.h" -class UiStyle : public QObject{ - Q_OBJECT +class UiStyle : public QObject +{ + Q_OBJECT public: - UiStyle(QObject *parent = 0); - virtual ~UiStyle(); - - typedef QList > FormatList; - - //! This enumerates the possible formats a text element may have. */ - /** These formats are ordered on increasing importance, in cases where a given property is specified - * by multiple active formats. - * \NOTE: Do not change/add values here without also adapting the relevant - * methods in this class (in particular mergedFormat())! - * Also, we _do_ rely on certain properties of these values in styleString() and friends! - */ - enum FormatType { - Base = 0x00000000, - Invalid = 0xffffffff, - - // Message Formats (mutually exclusive!) - PlainMsg = 0x00000001, - NoticeMsg = 0x00000002, - ActionMsg = 0x00000003, - NickMsg = 0x00000004, - ModeMsg = 0x00000005, - JoinMsg = 0x00000006, - PartMsg = 0x00000007, - QuitMsg = 0x00000008, - KickMsg = 0x00000009, - KillMsg = 0x0000000a, - ServerMsg = 0x0000000b, - InfoMsg = 0x0000000c, - ErrorMsg = 0x0000000d, - DayChangeMsg = 0x0000000e, - TopicMsg = 0x0000000f, - NetsplitJoinMsg = 0x00000010, - NetsplitQuitMsg = 0x00000020, - InviteMsg = 0x00000030, - - // Standard Formats - Bold = 0x00000100, - Italic = 0x00000200, - Underline = 0x00000400, - Reverse = 0x00000800, - - // Individual parts of a message - Timestamp = 0x00001000, - Sender = 0x00002000, - Contents = 0x00004000, - Nick = 0x00008000, - Hostmask = 0x00010000, - ChannelName = 0x00020000, - ModeFlags = 0x00040000, - - // URL is special, we want that to take precedence over the rest... - Url = 0x00080000 - - // mIRC Colors - we assume those to be present only in plain contents - // foreground: 0x0.400000 - // background: 0x.0800000 - }; - - enum MessageLabel { - OwnMsg = 0x00000001, - Highlight = 0x00000002, - Selected = 0x00000004 // must be last! - }; - - enum ItemFormatType { - BufferViewItem = 0x00000001, - NickViewItem = 0x00000002, - - NetworkItem = 0x00000010, - ChannelBufferItem = 0x00000020, - QueryBufferItem = 0x00000040, - IrcUserItem = 0x00000080, - UserCategoryItem = 0x00000100, - - InactiveBuffer = 0x00001000, - ActiveBuffer = 0x00002000, - UnreadBuffer = 0x00004000, - HighlightedBuffer = 0x00008000, - UserAway = 0x00010000 - }; - - enum ColorRole { - MarkerLine, - NumRoles // must be last! - }; - - struct StyledString { - QString plainText; - FormatList formatList; // starting pos, ftypes - }; - - class StyledMessage; - - static FormatType formatType(Message::Type msgType); - static StyledString styleString(const QString &string, quint32 baseFormat = Base); - static QString mircToInternal(const QString &); - static inline QString timestampFormatString() { return _timestampFormatString; } - - QTextCharFormat format(quint32 formatType, quint32 messageLabel) const; - QFontMetricsF *fontMetrics(quint32 formatType, quint32 messageLabel) const; - - QList toTextLayoutList(const FormatList &, int textLength, quint32 messageLabel) const; - - inline const QBrush &brush(ColorRole role) const { return _uiStylePalette.at((int) role); } - inline void setBrush(ColorRole role, const QBrush &brush) { _uiStylePalette[(int) role] = brush; } - - QVariant bufferViewItemData(const QModelIndex &networkModelIndex, int role) const; - QVariant nickViewItemData(const QModelIndex &networkModelIndex, int role) const; + UiStyle(QObject *parent = 0); + virtual ~UiStyle(); + + typedef QList > FormatList; + + //! This enumerates the possible formats a text element may have. */ + /** These formats are ordered on increasing importance, in cases where a given property is specified + * by multiple active formats. + * \NOTE: Do not change/add values here without also adapting the relevant + * methods in this class (in particular mergedFormat())! + * Also, we _do_ rely on certain properties of these values in styleString() and friends! + */ + enum FormatType { + Base = 0x00000000, + Invalid = 0xffffffff, + + // Message Formats (mutually exclusive!) + PlainMsg = 0x00000001, + NoticeMsg = 0x00000002, + ActionMsg = 0x00000003, + NickMsg = 0x00000004, + ModeMsg = 0x00000005, + JoinMsg = 0x00000006, + PartMsg = 0x00000007, + QuitMsg = 0x00000008, + KickMsg = 0x00000009, + KillMsg = 0x0000000a, + ServerMsg = 0x0000000b, + InfoMsg = 0x0000000c, + ErrorMsg = 0x0000000d, + DayChangeMsg = 0x0000000e, + TopicMsg = 0x0000000f, + NetsplitJoinMsg = 0x00000010, + NetsplitQuitMsg = 0x00000020, + InviteMsg = 0x00000030, + + // Standard Formats + Bold = 0x00000100, + Italic = 0x00000200, + Underline = 0x00000400, + Reverse = 0x00000800, + + // Individual parts of a message + Timestamp = 0x00001000, + Sender = 0x00002000, + Contents = 0x00004000, + Nick = 0x00008000, + Hostmask = 0x00010000, + ChannelName = 0x00020000, + ModeFlags = 0x00040000, + + // URL is special, we want that to take precedence over the rest... + Url = 0x00080000 + + // mIRC Colors - we assume those to be present only in plain contents + // foreground: 0x0.400000 + // background: 0x.0800000 + }; + + enum MessageLabel { + OwnMsg = 0x00000001, + Highlight = 0x00000002, + Selected = 0x00000004 // must be last! + }; + + enum ItemFormatType { + BufferViewItem = 0x00000001, + NickViewItem = 0x00000002, + + NetworkItem = 0x00000010, + ChannelBufferItem = 0x00000020, + QueryBufferItem = 0x00000040, + IrcUserItem = 0x00000080, + UserCategoryItem = 0x00000100, + + InactiveBuffer = 0x00001000, + ActiveBuffer = 0x00002000, + UnreadBuffer = 0x00004000, + HighlightedBuffer = 0x00008000, + UserAway = 0x00010000 + }; + + enum ColorRole { + MarkerLine, + NumRoles // must be last! + }; + + struct StyledString { + QString plainText; + FormatList formatList; // starting pos, ftypes + }; + + class StyledMessage; + + static FormatType formatType(Message::Type msgType); + static StyledString styleString(const QString &string, quint32 baseFormat = Base); + static QString mircToInternal(const QString &); + static inline QString timestampFormatString() { return _timestampFormatString; } + + QTextCharFormat format(quint32 formatType, quint32 messageLabel) const; + QFontMetricsF *fontMetrics(quint32 formatType, quint32 messageLabel) const; + + QList toTextLayoutList(const FormatList &, int textLength, quint32 messageLabel) const; + + inline const QBrush &brush(ColorRole role) const { return _uiStylePalette.at((int)role); } + inline void setBrush(ColorRole role, const QBrush &brush) { _uiStylePalette[(int)role] = brush; } + + QVariant bufferViewItemData(const QModelIndex &networkModelIndex, int role) const; + QVariant nickViewItemData(const QModelIndex &networkModelIndex, int role) const; public slots: - void reload(); + void reload(); signals: - void changed(); + void changed(); protected: - void loadStyleSheet(); - QString loadStyleSheet(const QString &name, bool shouldExist = false); + void loadStyleSheet(); + QString loadStyleSheet(const QString &name, bool shouldExist = false); - QTextCharFormat format(quint64 key) const; - QTextCharFormat cachedFormat(quint32 formatType, quint32 messageLabel) const; - void setCachedFormat(const QTextCharFormat &format, quint32 formatType, quint32 messageLabel) const; - void mergeFormat(QTextCharFormat &format, quint32 formatType, quint64 messageLabel) const; - void mergeSubElementFormat(QTextCharFormat &format, quint32 formatType, quint64 messageLabel) const; + QTextCharFormat format(quint64 key) const; + QTextCharFormat cachedFormat(quint32 formatType, quint32 messageLabel) const; + void setCachedFormat(const QTextCharFormat &format, quint32 formatType, quint32 messageLabel) const; + void mergeFormat(QTextCharFormat &format, quint32 formatType, quint64 messageLabel) const; + void mergeSubElementFormat(QTextCharFormat &format, quint32 formatType, quint64 messageLabel) const; - static FormatType formatType(const QString &code); - static QString formatCode(FormatType); - static void setTimestampFormatString(const QString &format); + static FormatType formatType(const QString &code); + static QString formatCode(FormatType); + static void setTimestampFormatString(const QString &format); - QVariant itemData(int role, const QTextCharFormat &format) const; + QVariant itemData(int role, const QTextCharFormat &format) const; private slots: - void allowMircColorsChanged(const QVariant &); - void showItemViewIconsChanged(const QVariant &); + void allowMircColorsChanged(const QVariant &); + void showItemViewIconsChanged(const QVariant &); private: - QVector _uiStylePalette; - QBrush _markerLineBrush; - QHash _formats; - mutable QHash _formatCache; - mutable QHash _metricsCache; - QHash _listItemFormats; - static QHash _formatCodes; - static QString _timestampFormatString; - - QPixmap _channelJoinedIcon; - QPixmap _channelPartedIcon; - QPixmap _userOfflineIcon; - QPixmap _userOnlineIcon; - QPixmap _userAwayIcon; - QPixmap _categoryOpIcon; - QPixmap _categoryVoiceIcon; - int _opIconLimit; - int _voiceIconLimit; - bool _showNickViewIcons; - bool _showBufferViewIcons; - bool _allowMircColors; + QVector _uiStylePalette; + QBrush _markerLineBrush; + QHash _formats; + mutable QHash _formatCache; + mutable QHash _metricsCache; + QHash _listItemFormats; + static QHash _formatCodes; + static QString _timestampFormatString; + + QPixmap _channelJoinedIcon; + QPixmap _channelPartedIcon; + QPixmap _userOfflineIcon; + QPixmap _userOnlineIcon; + QPixmap _userAwayIcon; + QPixmap _categoryOpIcon; + QPixmap _categoryVoiceIcon; + int _opIconLimit; + int _voiceIconLimit; + bool _showNickViewIcons; + bool _showBufferViewIcons; + bool _allowMircColors; }; -class UiStyle::StyledMessage : public Message { - Q_DECLARE_TR_FUNCTIONS(UiStyle::StyledMessage) + +class UiStyle::StyledMessage : public Message +{ + Q_DECLARE_TR_FUNCTIONS(UiStyle::StyledMessage) public: - explicit StyledMessage(const Message &message); + explicit StyledMessage(const Message &message); - QString decoratedTimestamp() const; - QString plainSender() const; //!< Nickname (no decorations) for Plain and Notice, empty else - QString decoratedSender() const; - const QString &plainContents() const; + QString decoratedTimestamp() const; + QString plainSender() const; //!< Nickname (no decorations) for Plain and Notice, empty else + QString decoratedSender() const; + const QString &plainContents() const; - const FormatList &contentsFormatList() const; + const FormatList &contentsFormatList() const; - quint8 senderHash() const; + quint8 senderHash() const; protected: - void style() const; + void style() const; private: - mutable StyledString _contents; - mutable quint8 _senderHash; + mutable StyledString _contents; + mutable quint8 _senderHash; }; + QDataStream &operator<<(QDataStream &out, const UiStyle::FormatList &formatList); QDataStream &operator>>(QDataStream &in, UiStyle::FormatList &formatList); -- 2.20.1