From 73edffb5f0f6ecae4118c36a7ca2c0d479b7f8c6 Mon Sep 17 00:00:00 2001 From: Manuel Nickschas Date: Wed, 20 Jun 2007 19:26:32 +0000 Subject: [PATCH] Reorganizing of the Quassel architecture is almost done. Client and GUI have been split. I will now consolidate the main files and start enabling building of standalone core and client again. --- Doxyfile | 1049 +++++++++++++++++++++++++++++++- Quassel.kdevelop.filelist | 182 +++--- src/CMakeLists.txt | 40 +- src/client/CMakeLists.txt | 6 + src/client/buffer.cpp | 65 +- src/client/buffer.h | 57 +- src/client/buffertreemodel.cpp | 2 + src/client/buffertreemodel.h | 1 + src/client/client.cpp | 48 +- src/client/client.h | 24 +- src/common/CMakeLists.txt | 2 +- src/common/global.cpp | 2 +- src/common/global.h | 9 +- src/common/main_mono.cpp | 8 +- src/common/quasselui.h | 50 ++ src/qtgui/CMakeLists.txt | 13 +- src/qtgui/bufferviewfilter.h | 1 + src/qtgui/bufferwidget.cpp | 49 +- src/qtgui/chatline.cpp | 408 +++++++++++++ src/qtgui/chatline.h | 109 ++++ src/qtgui/chatwidget.cpp | 402 +----------- src/qtgui/chatwidget.h | 124 +--- src/qtgui/mainwin.cpp | 26 +- src/qtgui/mainwin.h | 56 +- templates/cpp | 2 +- templates/h | 2 +- 26 files changed, 1915 insertions(+), 822 deletions(-) create mode 100644 src/client/CMakeLists.txt create mode 100644 src/common/quasselui.h create mode 100644 src/qtgui/chatline.cpp create mode 100644 src/qtgui/chatline.h diff --git a/Doxyfile b/Doxyfile index f10fed8e..4def1635 100644 --- a/Doxyfile +++ b/Doxyfile @@ -1,16 +1,90 @@ -# Doxyfile 1.5.1-KDevelop +# Doxyfile 1.5.2 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file that +# follow. The default is UTF-8 which is also the encoding used for all text before +# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into +# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of +# possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + PROJECT_NAME = "Quassel IRC" -PROJECT_NUMBER = 0.1 + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = Pre-Release + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + OUTPUT_DIRECTORY = doc + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, +# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, +# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, +# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + OUTPUT_LANGUAGE = English -USE_WINDOWS_ENCODING = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ @@ -22,70 +96,398 @@ ABBREVIATE_BRIEF = "The $name class" \ a \ an \ the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + INLINE_INHERITED_MEMB = YES + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + STRIP_FROM_PATH = / + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + STRIP_FROM_INC_PATH = /home/sputnick/devel/local-quassel/ + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + SHORT_NAMES = YES + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + JAVADOC_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + DETAILS_AT_TOP = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + OPTIMIZE_OUTPUT_JAVA = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to +# include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + DISTRIBUTE_GROUP_DOC = YES + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + SUBGROUPING = YES + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + EXTRACT_LOCAL_CLASSES = NO + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + EXTRACT_LOCAL_METHODS = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + INTERNAL_DOCS = YES + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + HIDE_SCOPE_NAMES = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + SORT_MEMBER_DOCS = NO + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + SHOW_DIRECTORIES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + FILE_VERSION_FILTER = + #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + WARN_LOGFILE = + #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- -INPUT = gui \ - main \ - core \ - plugins + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = src + +# This tag can be used to specify the character encoding of the source files that +# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default +# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. +# See http://www.gnu.org/software/libiconv for the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py + FILE_PATTERNS = *.c \ *.cc \ *.cxx \ @@ -132,152 +534,779 @@ FILE_PATTERNS = *.c \ *.moc \ *.xpm \ *.dox + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the output. +# The symbol name can be a fully qualified name, a word, or if the wildcard * is used, +# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + FILTER_SOURCE_FILES = YES + #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + VERBATIM_HEADERS = YES + #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + IGNORE_PREFIX = + #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + TREEVIEW_WIDTH = 250 + #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + LATEX_HIDE_INDICES = NO + #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + RTF_HYPERLINKS = YES + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + RTF_EXTENSIONS_FILE = + #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + MAN_LINKS = NO + #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + XML_PROGRAMLISTING = YES + #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + GENERATE_AUTOGEN_DEF = NO + #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + PERLMOD_MAKEVAR_PREFIX = + #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + INCLUDE_PATH = /usr/include/qt4 + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + SKIP_FUNCTION_MACROS = NO + #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + GENERATE_TAGFILE = quassel.tag + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + ALLEXTERNALS = YES + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + PERL_PATH = /usr/bin/perl + #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to +# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to +# specify the directory where the mscgen tool resides. If left empty the tool is assumed to +# be found in the default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + HAVE_DOT = YES + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + UML_LOOK = YES + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + CALL_GRAPH = YES + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a caller dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. + CALLER_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + DOTFILE_DIRS = -MAX_DOT_GRAPH_WIDTH = 1024 -MAX_DOT_GRAPH_HEIGHT = 1024 -MAX_DOT_GRAPH_DEPTH = 1000 + +# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen will always +# show the root nodes and its direct children regardless of this setting. + +DOT_GRAPH_MAX_NODES = 50 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + DOT_CLEANUP = YES + #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + SEARCHENGINE = NO diff --git a/Quassel.kdevelop.filelist b/Quassel.kdevelop.filelist index 73fdb28c..572f4e00 100644 --- a/Quassel.kdevelop.filelist +++ b/Quassel.kdevelop.filelist @@ -1,87 +1,97 @@ # KDevelop Custom Project File List -client -client/buffer.cpp -client/buffer.h -client/client.cpp -client/client.h -client/clientproxy.cpp -client/clientproxy.h -CMakeLists.txt -common -common/CMakeLists.txt -common/global.cpp -common/global.h -common/logger.cpp -common/logger.h -common/main_core.cpp -common/main_gui.cpp -common/main_mono.cpp -common/message.cpp -common/message.h -common/proxy_common.h -common/settings.cpp -common/settings.h -common/util.cpp -common/util.h -core -core/backlog.cpp -core/backlog.h -core/CMakeLists.txt -core/core.cpp -core/core.h -core/coreproxy.cpp -core/coreproxy.h -core/server.cpp -core/server.h -core/sqlitestorage.cpp -core/sqlitestorage.h -core/storage.cpp -core/storage.h -plugins -plugins/plugin.h -qtgui -qtgui/bufferview.cpp -qtgui/bufferview.h -qtgui/bufferviewwidget.cpp -qtgui/bufferviewwidget.h -qtgui/bufferwidget.cpp -qtgui/bufferwidget.h -qtgui/channelwidgetinput.cpp -qtgui/channelwidgetinput.h -qtgui/chatwidget.cpp -qtgui/chatwidget.h -qtgui/CMakeLists.txt -qtgui/coreconnectdlg.cpp -qtgui/coreconnectdlg.h -qtgui/identities.cpp -qtgui/identities.h -qtgui/mainwin.cpp -qtgui/mainwin.h -qtgui/serverlist.cpp -qtgui/serverlist.h -qtgui/settingsdlg.cpp -qtgui/settingsdlg.h -qtgui/settingspages.cpp -qtgui/settingspages.h -qtgui/style.cpp -qtgui/style.h -qtgui/tabcompleter.cpp -qtgui/tabcompleter.h -qtgui/ui -qtgui/ui/aboutdlg.ui -qtgui/ui/buffermgmntsettingspage.ui -qtgui/ui/bufferviewwidget.ui -qtgui/ui/bufferwidget.ui -qtgui/ui/channelwidget.ui -qtgui/ui/connectionsettingspage.ui -qtgui/ui/coreconnectdlg.ui -qtgui/ui/coresettingspage.ui -qtgui/ui/identitiesdlg.ui -qtgui/ui/identitieseditdlg.ui -qtgui/ui/ircwidget.ui -qtgui/ui/mainwin.ui -qtgui/ui/networkeditdlg.ui -qtgui/ui/nickeditdlg.ui -qtgui/ui/servereditdlg.ui -qtgui/ui/serverlistdlg.ui -qtgui/ui/settingsdlg.ui +Makefile +src +src/client +src/client/buffer.cpp +src/client/buffer.h +src/client/client.cpp +src/client/client.h +src/client/clientproxy.cpp +src/client/clientproxy.h +src/CMakeLists.txt +src/common +src/common/CMakeLists.txt +src/common/global.cpp +src/common/global.h +src/common/logger.cpp +src/common/logger.h +src/common/main_core.cpp +src/common/main_gui.cpp +src/common/main_mono.cpp +src/common/message.cpp +src/common/message.h +src/common/proxy_common.h +src/common/settings.cpp +src/common/settings.h +src/common/util.cpp +src/common/util.h +src/core +src/core/backlog.cpp +src/core/backlog.h +src/core/CMakeLists.txt +src/core/core.cpp +src/core/core.h +src/core/coreproxy.cpp +src/core/coreproxy.h +src/core/server.cpp +src/core/server.h +src/core/sqlitestorage.cpp +src/core/sqlitestorage.h +src/core/storage.cpp +src/core/storage.h +src/plugins +src/plugins/plugin.h +src/qtgui +src/qtgui/bufferview.cpp +src/qtgui/bufferview.h +src/qtgui/bufferviewwidget.cpp +src/qtgui/bufferviewwidget.h +src/qtgui/bufferwidget.cpp +src/qtgui/bufferwidget.h +src/qtgui/channelwidgetinput.cpp +src/qtgui/channelwidgetinput.h +src/qtgui/chatwidget.cpp +src/qtgui/chatwidget.h +src/qtgui/CMakeLists.txt +src/qtgui/coreconnectdlg.cpp +src/qtgui/coreconnectdlg.h +src/qtgui/identities.cpp +src/qtgui/identities.h +src/qtgui/mainwin.cpp +src/qtgui/mainwin.h +src/qtgui/serverlist.cpp +src/qtgui/serverlist.h +src/qtgui/settingsdlg.cpp +src/qtgui/settingsdlg.h +src/qtgui/settingspages.cpp +src/qtgui/settingspages.h +src/qtgui/style.cpp +src/qtgui/style.h +src/qtgui/tabcompleter.cpp +src/qtgui/tabcompleter.h +src/qtgui/ui +src/qtgui/ui/aboutdlg.ui +src/qtgui/ui/buffermgmntsettingspage.ui +src/qtgui/ui/bufferviewwidget.ui +src/qtgui/ui/bufferwidget.ui +src/qtgui/ui/channelwidget.ui +src/qtgui/ui/connectionsettingspage.ui +src/qtgui/ui/coreconnectdlg.ui +src/qtgui/ui/coresettingspage.ui +src/qtgui/ui/identitiesdlg.ui +src/qtgui/ui/identitieseditdlg.ui +src/qtgui/ui/ircwidget.ui +src/qtgui/ui/mainwin.ui +src/qtgui/ui/networkeditdlg.ui +src/qtgui/ui/nickeditdlg.ui +src/qtgui/ui/servereditdlg.ui +src/qtgui/ui/serverlistdlg.ui +src/qtgui/ui/settingsdlg.ui +src/common/quasselui.h +src/client/CMakeLists.txt +src/qtgui/chatline.cpp +src/qtgui/chatline.h +src/client/buffertreemodel.h +src/client/buffertreemodel.cpp +src/client/treemodel.cpp +src/client/treemodel.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 31227039..24713921 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,16 +6,16 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.4.3 FATAL_ERROR) # Select if Quassel should be built in client, server or monolithic mode SET(BUILD "mono" CACHE STRING "Defines which Quassel parts are to be built. Can contain 'core', 'gui' and/or 'monolithic' (which is the default), or 'all' to build everything.") SET(BUILD_CORE ) -SET(BUILD_GUI ) +SET(BUILD_CLIENT ) SET(BUILD_MONO ) IF(BUILD MATCHES "core" OR BUILD MATCHES "all") SET(BUILD_CORE true) MESSAGE("Building Quassel core.") ENDIF(BUILD MATCHES "core" OR BUILD MATCHES "all") -IF(BUILD MATCHES "gui" OR BUILD MATCHES "all") - SET(BUILD_GUI true) +IF(BUILD MATCHES "client" OR BUILD MATCHES "all") + SET(BUILD_CLIENT true) MESSAGE("Building Quassel GUI.") -ENDIF(BUILD MATCHES "gui" OR BUILD MATCHES "all") +ENDIF(BUILD MATCHES "client" OR BUILD MATCHES "all") IF(BUILD MATCHES "mono" OR BUILD MATCHES "all") SET(BUILD_MONO true) MESSAGE("Building monolithic Quassel.") @@ -24,26 +24,26 @@ IF(NOT BUILD_MONO AND NOT BUILD_CORE AND NOT BUILD_GUI) MESSAGE(FATAL_ERROR "\nYou have not selected which parts of Quassel I should build. Aborting.\nRun 'cmake -DBUILD=', where contains one or more of 'core', 'gui' or 'monolithic', or 'all' to build everything.\n") ENDIF(NOT BUILD_MONO AND NOT BUILD_CORE AND NOT BUILD_GUI) -IF(BUILD_CORE OR BUILD_GUI) +IF(BUILD_CORE OR BUILD_CLIENT) MESSAGE(FATAL_ERROR "\nBuilding of standalone core or GUI not supported at this time. Please check back later.\n") -ENDIF(BUILD_CORE OR BUILD_GUI) +ENDIF(BUILD_CORE OR BUILD_CLIENT) SET(CMAKE_BUILD_TYPE Debug) # Define files SET(quassel_mono_SRCS common/main_mono.cpp) SET(quassel_core_SRCS common/main_core.cpp) -SET(quassel_gui_SRCS common/main_gui.cpp ${common_SRCS}) +SET(quassel_client_SRCS common/main_gui.cpp ${common_SRCS}) SET(quassel_RCCS images/icons.qrc) -SET(quassel_DIRS common qtgui core) +SET(quassel_DIRS common client core qtgui) # Build correct absolute paths for subdirs to include SET(SDIRS "") FOREACH(dir ${quassel_DIRS}) SET(SDIRS ${SDIRS} "${CMAKE_CURRENT_SOURCE_DIR}/${dir}") ENDFOREACH(dir) -INCLUDE_DIRECTORIES(${SDIRS} client plugins) -#INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) +INCLUDE_DIRECTORIES(${SDIRS} plugins) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/qtgui) # We need Qt4 support. SET(QT_MIN_VERSION "4.3.0") # 4.3 is required for SSL, crypto and some other stuff @@ -74,33 +74,37 @@ SET(TARGET_LIST ) IF(BUILD_CORE) ADD_DEFINITIONS(-DBUILD_CORE) ADD_EXECUTABLE(quasselcore ${quassel_core_SRCS} ${_RCCS}) - TARGET_LINK_LIBRARIES(quasselcore core common ${QT_LIBRARIES}) + TARGET_LINK_LIBRARIES(quasselcore common core ${QT_LIBRARIES}) SET(TARGET_LIST ${TARGET_LIST} quasselcore) + REMOVE_DEFINITIONS(-DBUILD_CORE) ENDIF(BUILD_CORE) -IF(BUILD_GUI OR BUILD_MONO) # OK, now we need QtGui! +IF(BUILD_CLIENT OR BUILD_MONO) # OK, now we need QtGui! REMOVE_DEFINITIONS(-DQT_CORE_LIB -DQT_GUI_LIB ${QT_DEFINITIONS}) SET(QT_DONT_USE_QTGUI "") SET(QT_INCLUDE_DIR "") SET(QT_LIBRARIES "") INCLUDE(${QT_USE_FILE}) + ADD_SUBDIRECTORY(client) ADD_SUBDIRECTORY(qtgui) IF(BUILD_MONO) ADD_DEFINITIONS(-DBUILD_MONO) ADD_EXECUTABLE(quassel ${quassel_mono_SRCS} ${_RCCS}) - TARGET_LINK_LIBRARIES(quassel qtgui core common ${QT_LIBRARIES}) + TARGET_LINK_LIBRARIES(quassel common client core qtgui ${QT_LIBRARIES}) SET(TARGET_LIST ${TARGET_LIST} quassel) + REMOVE_DEFINITIONS(-DBUILD_MONO) ENDIF(BUILD_MONO) - IF(BUILD_GUI) - ADD_DEFINITIONS(-DBUILD_GUI) + IF(BUILD_CLIENT) + ADD_DEFINITIONS(-DBUILD_CLIENT) ADD_EXECUTABLE(quasselgui ${quassel_gui_SRCS} ${_RCCS}) - TARGET_LINK_LIBRARIES(quasselgui qtgui common ${QT_LIBRARIES}) + TARGET_LINK_LIBRARIES(quasselclient common client qtgui ${QT_LIBRARIES}) SET(TARGET_LIST ${TARGET_LIST} quasselgui) - ENDIF(BUILD_GUI) + REMOVE_DEFINITIONS(-DBUILD_CLIENT) + ENDIF(BUILD_CLIENT) -ENDIF(BUILD_GUI OR BUILD_MONO) +ENDIF(BUILD_CLIENT OR BUILD_MONO) INSTALL(TARGETS ${TARGET_LIST} RUNTIME DESTINATION bin diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt new file mode 100644 index 00000000..40a7695f --- /dev/null +++ b/src/client/CMakeLists.txt @@ -0,0 +1,6 @@ +SET(client_SRCS buffer.cpp buffertreemodel.cpp client.cpp clientproxy.cpp treemodel.cpp) +SET(client_HDRS ) +SET(client_MOCS buffer.h buffertreemodel.h client.h clientproxy.h treemodel.h) + +QT4_WRAP_CPP(_MOC ${client_MOCS}) +ADD_LIBRARY(client ${_MOC} ${client_SRCS} ${client_HDRS}) diff --git a/src/client/buffer.cpp b/src/client/buffer.cpp index cf764c1b..c8f375d0 100644 --- a/src/client/buffer.cpp +++ b/src/client/buffer.cpp @@ -18,10 +18,9 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ +#include "client.h" #include "buffer.h" #include "util.h" -#include "chatwidget.h" -#include "bufferwidget.h" /* Buffer::Buffer(QString netname, QString bufname) { @@ -62,18 +61,53 @@ Buffer::~Buffer() { emit bufferDestroyed(this); } -void Buffer::init() { +Buffer::Type Buffer::bufferType() const { + return type; +} +bool Buffer::isActive() const { + return active; +} +QString Buffer::networkName() const { + return _networkName; } -QString Buffer::displayName() { +QString Buffer::bufferName() const { + return _bufferName; +} + +QString Buffer::displayName() const { if(bufferType() == ServerBuffer) - return tr("status"); + return tr("Status Buffer"); else return bufferName(); } +BufferId Buffer::bufferId() const { + return id; +} + +QList Buffer::contents() const { + return layoutedMsgs; +} + +VarMap Buffer::nickList() const { + return nicks; +} + +QString Buffer::topic() const { + return _topic; +} + +QString Buffer::ownNick() const { + return _ownNick; +} + +bool Buffer::isStatusBuffer() const { + return bufferType() == ServerBuffer; +} + void Buffer::setActive(bool a) { if(a != active) { active = a; @@ -81,14 +115,23 @@ void Buffer::setActive(bool a) { } } -void Buffer::appendChatLine(ChatLine *line) { - lines.append(line); - emit chatLineAppended(line); +void Buffer::appendMsg(const Message &msg) { + AbstractUiMsg *m = Client::layoutMsg(msg); + layoutedMsgs.append(m); + emit msgAppended(m); +} + +void Buffer::prependMsg(const Message &msg) { + layoutQueue.append(msg); } -void Buffer::prependChatLine(ChatLine *line) { - lines.prepend(line); - emit chatLinePrepended(line); +bool Buffer::layoutMsg() { + if(layoutQueue.count()) { + AbstractUiMsg *m = Client::layoutMsg(layoutQueue.takeFirst()); + layoutedMsgs.prepend(m); + emit msgPrepended(m); + } + return layoutQueue.count(); } void Buffer::processUserInput(QString msg) { diff --git a/src/client/buffer.h b/src/client/buffer.h index 944b07cc..2c361d3d 100644 --- a/src/client/buffer.h +++ b/src/client/buffer.h @@ -22,16 +22,11 @@ #define _BUFFER_H_ #include -#include -#include "chatwidget.h" #include "global.h" #include "message.h" +#include "quasselui.h" -class ChatWidget; -class ChatLine; -class ChatWidgetContents; -class BufferWidget; struct BufferState; //!\brief Encapsulates the contents of a single channel, query or server status context. @@ -43,10 +38,8 @@ class Buffer : public QObject { Q_OBJECT public: - //Buffer(QString network, QString buffer); Buffer(BufferId); ~Buffer(); - static void init(); enum Type { ServerBuffer, ChannelBuffer, QueryBuffer }; @@ -57,39 +50,37 @@ class Buffer : public QObject { Highlight = 0x40 }; Q_DECLARE_FLAGS(ActivityLevel, Activity) - - Type bufferType() { return type; } - bool isActive() { return active; } - - QString networkName() { return _networkName; } - QString bufferName() { return _bufferName; } - QString displayName(); - BufferId bufferId() { return id; } - QList contents() { return lines; } - VarMap nickList() { return nicks; } - QString topic() { return _topic; } - QString ownNick() { return _ownNick; } - bool isStatusBuffer() { return bufferType() == ServerBuffer; } + + Type bufferType() const; + bool isActive() const; + + QString networkName() const; + QString bufferName() const; + QString displayName() const; + BufferId bufferId() const; + QList contents() const; + VarMap nickList() const; + QString topic() const; + QString ownNick() const; + bool isStatusBuffer() const; signals: - void userInput(BufferId, QString); - //void msgDisplayed(Message); - void chatLineAppended(ChatLine *); - void chatLinePrepended(ChatLine *); + void userInput(const BufferId &, QString); void nickListChanged(VarMap nicks); void topicSet(QString topic); void ownNickSet(QString ownNick); void bufferUpdated(Buffer *); void bufferDestroyed(Buffer *); + void msgAppended(AbstractUiMsg *); + void msgPrepended(AbstractUiMsg *); + void layoutQueueEmpty(); + public slots: void setActive(bool active = true); - //void displayMsg(Message); - //void prependMessages(QList); // for backlog - void appendChatLine(ChatLine *); - void prependChatLine(ChatLine *); - //void prependChatLines(QList); - //void recvStatusMsg(QString msg); + void appendMsg(const Message &); + void prependMsg(const Message &); + bool layoutMsg(); void setTopic(QString); //void setNicks(QStringList); void addNick(QString nick, VarMap props); @@ -111,8 +102,8 @@ class Buffer : public QObject { QString _networkName, _bufferName; BufferState *state; - //QList _contents; - QList lines; + QList layoutQueue; + QList layoutedMsgs; }; Q_DECLARE_OPERATORS_FOR_FLAGS(Buffer::ActivityLevel) diff --git a/src/client/buffertreemodel.cpp b/src/client/buffertreemodel.cpp index 7030547e..2d51d85c 100644 --- a/src/client/buffertreemodel.cpp +++ b/src/client/buffertreemodel.cpp @@ -18,6 +18,8 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ +#include // FIXME Dependency on QtGui! + #include "global.h" #include "buffertreemodel.h" diff --git a/src/client/buffertreemodel.h b/src/client/buffertreemodel.h index 0848c8ff..9d71dee7 100644 --- a/src/client/buffertreemodel.h +++ b/src/client/buffertreemodel.h @@ -22,6 +22,7 @@ #define _BUFFERTREEMODEL_H_ #include +#include // FIXME Dependency on QtGui #include "treemodel.h" #include "buffer.h" diff --git a/src/client/client.cpp b/src/client/client.cpp index a04361cc..419a8a2a 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -20,8 +20,8 @@ #include "client.h" #include "clientproxy.h" -#include "mainwin.h" #include "buffer.h" +#include "buffertreemodel.h" #include "util.h" Client * Client::instanceptr = 0; @@ -38,7 +38,6 @@ QList Client::coreBuffers; Client *Client::instance() { if(instanceptr) return instanceptr; instanceptr = new Client(); - instanceptr->init(); return instanceptr; } @@ -50,8 +49,7 @@ void Client::destroy() { Client::Client() { clientProxy = ClientProxy::instance(); - //mainWin = new MainWin(); - _bufferModel = new BufferTreeModel(0); // FIXME + _bufferModel = new BufferTreeModel(this); connect(this, SIGNAL(bufferSelected(Buffer *)), _bufferModel, SLOT(selectBuffer(Buffer *))); connect(this, SIGNAL(bufferUpdated(Buffer *)), _bufferModel, SLOT(bufferUpdated(Buffer *))); @@ -62,6 +60,11 @@ Client::Client() { else clientMode = RemoteCore; } +void Client::init(AbstractUi *ui) { + instance()->mainUi = ui; + instance()->init(); +} + void Client::init() { blockSize = 0; @@ -77,7 +80,7 @@ void Client::init() { connect(clientProxy, SIGNAL(csServerState(QString, QVariant)), this, SLOT(recvNetworkState(QString, QVariant))); connect(clientProxy, SIGNAL(csServerConnected(QString)), this, SLOT(networkConnected(QString))); connect(clientProxy, SIGNAL(csServerDisconnected(QString)), this, SLOT(networkDisconnected(QString))); - connect(clientProxy, SIGNAL(csDisplayMsg(Message)), this, SLOT(recvMessage(Message))); + connect(clientProxy, SIGNAL(csDisplayMsg(Message)), this, SLOT(recvMessage(const Message &))); connect(clientProxy, SIGNAL(csDisplayStatusMsg(QString, QString)), this, SLOT(recvStatusMsg(QString, QString))); connect(clientProxy, SIGNAL(csTopicSet(QString, QString, QString)), this, SLOT(setTopic(QString, QString, QString))); connect(clientProxy, SIGNAL(csNickAdded(QString, QString, VarMap)), this, SLOT(addNick(QString, QString, VarMap))); @@ -85,7 +88,7 @@ void Client::init() { connect(clientProxy, SIGNAL(csNickRenamed(QString, QString, QString)), this, SLOT(renameNick(QString, QString, QString))); connect(clientProxy, SIGNAL(csNickUpdated(QString, QString, VarMap)), this, SLOT(updateNick(QString, QString, VarMap))); connect(clientProxy, SIGNAL(csOwnNickSet(QString, QString)), this, SLOT(setOwnNick(QString, QString))); - connect(clientProxy, SIGNAL(csBacklogData(BufferId, QList, bool)), this, SLOT(recvBacklogData(BufferId, QList, bool))); + connect(clientProxy, SIGNAL(csBacklogData(BufferId, const QList &, bool)), this, SLOT(recvBacklogData(BufferId, QList, bool))); connect(clientProxy, SIGNAL(csUpdateBufferId(BufferId)), this, SLOT(updateBufferId(BufferId))); connect(this, SIGNAL(sendInput(BufferId, QString)), clientProxy, SLOT(gsUserInput(BufferId, QString))); connect(this, SIGNAL(requestBacklog(BufferId, QVariant, QVariant)), clientProxy, SLOT(gsRequestBacklog(BufferId, QVariant, QVariant))); @@ -103,15 +106,11 @@ void Client::init() { buffer(id); // create all buffers, so we see them in the network views emit requestBacklog(id, -1, -1); // TODO: use custom settings for backlog request } - - mainWin = new MainWin(); - mainWin->init(); - } Client::~Client() { - delete mainWin; - delete _bufferModel; + //delete mainUi; + //delete _bufferModel; foreach(Buffer *buf, buffers.values()) delete buf; ClientProxy::destroy(); @@ -174,8 +173,6 @@ void Client::serverHasData() { } } -/*******************************************************************************************************************/ - void Client::networkConnected(QString net) { connected[net] = true; BufferId id = statusBufferId(net); @@ -244,7 +241,7 @@ void Client::recvNetworkState(QString net, QVariant state) { } } -void Client::recvMessage(Message msg) { +void Client::recvMessage(const Message &msg) { Buffer *b = buffer(msg.buffer); Buffer::ActivityLevel level = Buffer::OtherActivity; @@ -256,8 +253,7 @@ void Client::recvMessage(Message msg) { } emit bufferActivity(level, b); - //b->displayMsg(msg); - b->appendChatLine(new ChatLine(msg)); + b->appendMsg(msg); } void Client::recvStatusMsg(QString net, QString msg) { @@ -265,22 +261,28 @@ void Client::recvStatusMsg(QString net, QString msg) { } -void Client::recvBacklogData(BufferId id, QList msgs, bool done) { +void Client::recvBacklogData(BufferId id, const QList &msgs, bool done) { + Buffer *b = buffer(id); foreach(QVariant v, msgs) { - layoutQueue.append(v.value()); + Message msg = v.value(); + b->prependMsg(msg); + if(!layoutQueue.contains(b)) layoutQueue.append(b); } - if(!layoutTimer->isActive()) layoutTimer->start(); + if(layoutQueue.count() && !layoutTimer->isActive()) layoutTimer->start(); } - void Client::layoutMsg() { if(layoutQueue.count()) { - ChatLine *line = new ChatLine(layoutQueue.takeFirst()); - buffer(line->bufferId())->prependChatLine(line); + Buffer *b = layoutQueue.takeFirst(); // TODO make this the current buffer + if(b->layoutMsg()) layoutQueue.append(b); // Buffer has more messages in its queue --> Round Robin } if(!layoutQueue.count()) layoutTimer->stop(); } +AbstractUiMsg *Client::layoutMsg(const Message &msg) { + return instance()->mainUi->layoutMsg(msg); +} + void Client::userInput(BufferId id, QString msg) { emit sendInput(id, msg); } diff --git a/src/client/client.h b/src/client/client.h index 82e3e844..eee57fd5 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -18,28 +18,26 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ -#ifndef _GUI_H_ -#define _GUI_H_ +#ifndef _CLIENT_H_ +#define _CLIENT_H_ #include -#include #include -#include "global.h" +#include "quasselui.h" #include "buffer.h" #include "message.h" -#include "clientproxy.h" -#include "buffertreemodel.h" -//#include "bufferviewwidget.h" +#include "proxy_common.h" -class MainWin; class ClientProxy; +class BufferTreeModel; class Client : public QObject { Q_OBJECT public: static Client *instance(); + static void init(AbstractUi *); static void destroy(); static Buffer *buffer(BufferId); @@ -48,6 +46,8 @@ class Client : public QObject { static BufferTreeModel *bufferModel(); + static AbstractUiMsg *layoutMsg(const Message &); + signals: void sendInput(BufferId, QString message); void showBuffer(Buffer *); @@ -80,7 +80,7 @@ class Client : public QObject { void networkConnected(QString); void networkDisconnected(QString); void recvNetworkState(QString, QVariant); - void recvMessage(Message message); + void recvMessage(const Message &message); void recvStatusMsg(QString network, QString message); void setTopic(QString net, QString buf, QString); void addNick(QString net, QString nick, VarMap props); @@ -88,7 +88,7 @@ class Client : public QObject { void renameNick(QString net, QString oldnick, QString newnick); void updateNick(QString net, QString nick, VarMap props); void setOwnNick(QString net, QString nick); - void recvBacklogData(BufferId, QList, bool); + void recvBacklogData(BufferId, const QList &, bool); void updateBufferId(BufferId); void layoutMsg(); @@ -104,7 +104,7 @@ class Client : public QObject { enum ClientMode { LocalCore, RemoteCore }; static ClientMode clientMode; - MainWin *mainWin; + AbstractUi *mainUi; ClientProxy *clientProxy; BufferTreeModel *_bufferModel; @@ -119,7 +119,7 @@ class Client : public QObject { static QList coreBuffers; QTimer *layoutTimer; - QList layoutQueue; + QList layoutQueue; }; #endif diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index acfa640d..7f465520 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -1,5 +1,5 @@ SET(common_SRCS global.cpp logger.cpp util.cpp message.cpp settings.cpp) -SET(common_HDRS util.h message.h settings.h) +SET(common_HDRS util.h message.h settings.h quasselui.h) SET(common_MOCS global.h logger.h) QT4_WRAP_CPP(_MOC ${common_MOCS}) diff --git a/src/common/global.cpp b/src/common/global.cpp index 3c82e815..b92f7959 100644 --- a/src/common/global.cpp +++ b/src/common/global.cpp @@ -136,7 +136,7 @@ BufferId::BufferId(uint _id, QString _net, QString _buf, uint _gid) : id(_id), g } -QString BufferId::buffer() { +QString BufferId::buffer() const { if(isChannelName(buf)) return buf; else return nickFromMask(buf); } diff --git a/src/common/global.h b/src/common/global.h index fa961f2f..42856068 100644 --- a/src/common/global.h +++ b/src/common/global.h @@ -111,14 +111,15 @@ class BufferId { BufferId() { id = gid = 0; } // FIXME BufferId(uint uid, QString net, QString buf, uint gid = 0); - inline uint uid() { return id; } - inline uint groupId() { return gid; } - inline QString network() { return net; } - QString buffer(); // nickfrommask? + inline uint uid() const { return id; } + inline uint groupId() const { return gid; } + inline QString network() const { return net; } + QString buffer() const; // nickfrommask? void setGroupId(uint _gid) { gid = _gid; } inline bool operator==(const BufferId &other) const { return id == other.id; } + private: uint id; uint gid; diff --git a/src/common/main_mono.cpp b/src/common/main_mono.cpp index f0bafd9e..a7565c56 100644 --- a/src/common/main_mono.cpp +++ b/src/common/main_mono.cpp @@ -30,6 +30,7 @@ #include "coreproxy.h" #include "settings.h" #include "chatwidget.h" +#include "mainwin.h" int main(int argc, char **argv) { QApplication app(argc, argv); @@ -50,14 +51,15 @@ int main(int argc, char **argv) { Settings::init(); Style::init(); - //MainWin *mainWin = new MainWin(); + MainWin *mainWin = new MainWin(); //mainWin->show(); - //mainWin->init(); - Client::instance(); + Client::init(mainWin); + mainWin->init(); int exitCode = app.exec(); //delete core; Client::destroy(); Core::destroy(); + delete mainWin; //delete guiProxy; //delete coreProxy; //delete global; diff --git a/src/common/quasselui.h b/src/common/quasselui.h new file mode 100644 index 00000000..4209cdd9 --- /dev/null +++ b/src/common/quasselui.h @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (C) 2005-07 by The Quassel IRC Development Team * + * devel@quassel-irc.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef _QUASSELUI_H_ +#define _QUASSELUI_H_ + +#include "message.h" + +class AbstractUiMsg { + + public: + + virtual QString sender() const = 0; + virtual QString text() const = 0; + virtual MsgId msgId() const = 0; + virtual BufferId bufferId() const = 0; + virtual QDateTime timeStamp() const = 0; + +}; + + +class AbstractUi { + + public: + virtual AbstractUiMsg *layoutMsg(const Message &) = 0; + + + +}; + + + +#endif diff --git a/src/qtgui/CMakeLists.txt b/src/qtgui/CMakeLists.txt index 99c9de7c..11985659 100644 --- a/src/qtgui/CMakeLists.txt +++ b/src/qtgui/CMakeLists.txt @@ -1,27 +1,24 @@ -SET(qtgui_SRCS chatwidget.cpp channelwidgetinput.cpp tabcompleter.cpp mainwin.cpp serverlist.cpp bufferwidget.cpp +SET(qtgui_SRCS chatwidget.cpp chatline.cpp channelwidgetinput.cpp tabcompleter.cpp mainwin.cpp serverlist.cpp bufferwidget.cpp identities.cpp coreconnectdlg.cpp bufferview.cpp bufferviewwidget.cpp bufferviewfilter.cpp style.cpp settingsdlg.cpp settingspages.cpp) SET(qtgui_HDRS style.h) -SET(qtgui_MOCS chatwidget.h channelwidgetinput.h tabcompleter.h mainwin.h serverlist.h identities.h coreconnectdlg.h +SET(qtgui_MOCS chatwidget.h chatline.h channelwidgetinput.h tabcompleter.h mainwin.h serverlist.h identities.h coreconnectdlg.h bufferview.h bufferwidget.h bufferviewwidget.h bufferviewfilter.h settingsdlg.h settingspages.h) SET(qtgui_UICS identitiesdlg.ui identitieseditdlg.ui networkeditdlg.ui mainwin.ui nickeditdlg.ui serverlistdlg.ui servereditdlg.ui coreconnectdlg.ui ircwidget.ui bufferviewwidget.ui bufferwidget.ui settingsdlg.ui buffermgmntsettingspage.ui connectionsettingspage.ui) -SET(client_SRCS ../client/client.cpp ../client/clientproxy.cpp ../client/buffer.cpp ../client/treemodel.cpp ../client/buffertreemodel.cpp) -SET(client_MOCS ../client/client.h ../client/clientproxy.h ../client/buffer.h ../client/treemodel.h ../client/buffertreemodel.h) - # This prepends ui/ to the UIC names, so we don't have to do this ourselves. FOREACH(ui ${qtgui_UICS}) SET(qtgui_UICS_UI ${qtgui_UICS_UI} "ui/${ui}") ENDFOREACH(ui) QT4_WRAP_UI(_UIC ${qtgui_UICS_UI}) -QT4_WRAP_CPP(_MOC ${qtgui_MOCS} ${client_MOCS}) +QT4_WRAP_CPP(_MOC ${qtgui_MOCS}) # We need to work around a dependency bug with out-of-source builds... # Seems to be fixed! #SET_SOURCE_FILES_PROPERTIES(${gui_SRCS} PROPERTIES OBJECT_DEPENDS "${_UIC}") -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} client) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) -ADD_LIBRARY(qtgui ${qtgui_HDRS} ${qtgui_SRCS} ${client_SRCS} ${_MOC} ${_UIC}) +ADD_LIBRARY(qtgui ${qtgui_HDRS} ${qtgui_SRCS} ${_MOC} ${_UIC}) diff --git a/src/qtgui/bufferviewfilter.h b/src/qtgui/bufferviewfilter.h index 36c07078..8bce1439 100644 --- a/src/qtgui/bufferviewfilter.h +++ b/src/qtgui/bufferviewfilter.h @@ -22,6 +22,7 @@ #define _BUFFERVIEWFILTER_H_ #include +#include #include "buffer.h" #include "buffertreemodel.h" diff --git a/src/qtgui/bufferwidget.cpp b/src/qtgui/bufferwidget.cpp index 807dacf1..f1a8946c 100644 --- a/src/qtgui/bufferwidget.cpp +++ b/src/qtgui/bufferwidget.cpp @@ -20,18 +20,13 @@ #include "bufferwidget.h" #include "buffer.h" +#include "chatline.h" #include "chatwidget.h" #include "settings.h" -#include "mainwin.h" BufferWidget::BufferWidget(QWidget *parent) : QWidget(parent) { ui.setupUi(this); - //layoutThread->start(); - //connect(this, SIGNAL(aboutToClose()), layoutThread, SLOT(quit())); - //connect(this, SIGNAL(layoutMessages(LayoutTask)), layoutThread, SLOT(processTask(LayoutTask)), Qt::QueuedConnection); - //layoutThread->start(); - curBuf = 0; //setBaseSize(QSize(600,400)); //setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); @@ -41,17 +36,10 @@ BufferWidget::BufferWidget(QWidget *parent) : QWidget(parent) { } void BufferWidget::init() { - //layoutThread = new LayoutThread(); - //layoutThread = ::layoutThread; - //connect(layoutThread, SIGNAL(taskProcessed(LayoutTask)), this, SLOT(messagesLayouted(LayoutTask))); - //layoutThread->start(); - //while(!layoutThread->isRunning()) {}; + } BufferWidget::~BufferWidget() { - //emit aboutToClose(); - //layoutThread->wait(10000); - //delete layoutThread; foreach(BufferState *s, states.values()) { delete s; } @@ -93,9 +81,14 @@ void BufferWidget::setBuffer(Buffer *buf) { states[buf] = s; state = s; state->chatWidget->init(networkName, bufferName); - state->chatWidget->setContents(buf->contents()); - connect(buf, SIGNAL(chatLineAppended(ChatLine *)), state->chatWidget, SLOT(appendChatLine(ChatLine *))); - connect(buf, SIGNAL(chatLinePrepended(ChatLine *)), state->chatWidget, SLOT(prependChatLine(ChatLine *))); + QList lines; + QList msgs = buf->contents(); + foreach(AbstractUiMsg *msg, msgs) { + lines.append(dynamic_cast(msg)); + } + state->chatWidget->setContents(lines); + connect(buf, SIGNAL(msgAppended(AbstractUiMsg *)), state->chatWidget, SLOT(appendMsg(AbstractUiMsg *))); + connect(buf, SIGNAL(msgPrepended(AbstractUiMsg *)), state->chatWidget, SLOT(prependMsg(AbstractUiMsg *))); connect(buf, SIGNAL(topicSet(QString)), this, SLOT(setTopic(QString))); connect(buf, SIGNAL(ownNickSet(QString)), this, SLOT(setOwnNick(QString))); ui.stackedWidget->addWidget(s->page); @@ -116,28 +109,6 @@ void BufferWidget::setBuffer(Buffer *buf) { updateTitle(); } -/* -void BufferWidget::prependMessages(Buffer *buf, QList messages) { - LayoutTask task; - task.messages = messages; - task.buffer = buf; - task.net = buf->networkName(); - task.buf = buf->bufferName(); - //emit layoutMessages(task); - layoutThread->processTask(task); -} - -void BufferWidget::messagesLayouted(LayoutTask task) { - if(states.contains(task.buffer)) { - states[task.buffer]->chatWidget->prependChatLines(task.lines); - task.buffer->prependMessages(task.messages); - } else { - msgCache[task.buffer] = task.messages + msgCache[task.buffer]; - chatLineCache[task.buffer] = task.lines + chatLineCache[task.buffer]; - } -} -*/ - void BufferWidget::saveState() { foreach(Buffer *buf, states.keys()) { BufferState *s = states[buf]; diff --git a/src/qtgui/chatline.cpp b/src/qtgui/chatline.cpp new file mode 100644 index 00000000..5d828c1f --- /dev/null +++ b/src/qtgui/chatline.cpp @@ -0,0 +1,408 @@ +/*************************************************************************** + * Copyright (C) 2005-07 by The Quassel IRC Development Team * + * devel@quassel-irc.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "chatline.h" + +//!\brief Construct a ChatLine object from a message. +/** + * \param m The message to be layouted and rendered + * \param net The network name + * \param buf The buffer name + */ +ChatLine::ChatLine(Message m) { + hght = 0; + //networkName = m.buffer.network(); + //bufferName = m.buffer.buffer(); + msg = m; + selectionMode = None; + formatMsg(msg); +} + +ChatLine::~ChatLine() { + +} + +void ChatLine::formatMsg(Message msg) { + QString user = userFromMask(msg.sender); + QString host = hostFromMask(msg.sender); + QString nick = nickFromMask(msg.sender); + QString text = Style::mircToInternal(msg.text); + QString networkName = msg.buffer.network(); + QString bufferName = msg.buffer.buffer(); + + QString c = tr("%DT[%1]").arg(msg.timeStamp.toLocalTime().toString("hh:mm:ss")); + QString s, t; + switch(msg.type) { + case Message::Plain: + s = tr("%DS<%1>").arg(nick); t = tr("%D0%1").arg(text); break; + case Message::Server: + s = tr("%Ds*"); t = tr("%Ds%1").arg(text); break; + case Message::Error: + s = tr("%De*"); t = tr("%De%1").arg(text); break; + case Message::Join: + s = tr("%Dj-->"); t = tr("%Dj%DN%DU%1%DU%DN %DH(%2@%3)%DH has joined %DC%DU%4%DU%DC").arg(nick, user, host, bufferName); break; + case Message::Part: + s = tr("%Dp<--"); t = tr("%Dp%DN%DU%1%DU%DN %DH(%2@%3)%DH has left %DC%DU%4%DU%DC").arg(nick, user, host, bufferName); + if(!text.isEmpty()) t = QString("%1 (%2)").arg(t).arg(text); + break; + case Message::Quit: + s = tr("%Dq<--"); t = tr("%Dq%DN%DU%1%DU%DN %DH(%2@%3)%DH has quit").arg(nick, user, host); + if(!text.isEmpty()) t = QString("%1 (%2)").arg(t).arg(text); + break; + case Message::Kick: + { s = tr("%Dk<-*"); + QString victim = text.section(" ", 0, 0); + //if(victim == ui.ownNick->currentText()) victim = tr("you"); + QString kickmsg = text.section(" ", 1); + t = tr("%Dk%DN%DU%1%DU%DN has kicked %DN%DU%2%DU%DN from %DC%DU%3%DU%DC").arg(nick).arg(victim).arg(bufferName); + if(!kickmsg.isEmpty()) t = QString("%1 (%2)").arg(t).arg(kickmsg); + } + break; + case Message::Nick: + s = tr("%Dr<->"); + if(nick == msg.text) t = tr("%DrYou are now known as %DN%1%DN").arg(msg.text); + else t = tr("%Dr%DN%1%DN is now known as %DN%DU%2%DU%DN").arg(nick, msg.text); + break; + case Message::Mode: + s = tr("%Dm***"); + if(nick.isEmpty()) t = tr("%DmUser mode: %DM%1%DM").arg(msg.text); + else t = tr("%DmMode %DM%1%DM by %DN%DU%2%DU%DN").arg(msg.text, nick); + break; + case Message::Action: + s = tr("%Da-*-"); + t = tr("%Da%DN%DU%1%DU%DN %2").arg(nick).arg(msg.text); + break; + default: + s = tr("%De%1").arg(msg.sender); + t = tr("%De[%1]").arg(msg.text); + } + QTextOption tsOption, senderOption, textOption; + tsFormatted = Style::internalToFormatted(c); + senderFormatted = Style::internalToFormatted(s); + textFormatted = Style::internalToFormatted(t); + precomputeLine(); +} + +QList ChatLine::calcFormatRanges(const Style::FormattedString &fs, QTextLayout::FormatRange additional) { + QList ranges; + QList formats = fs.formats; + formats.append(additional); + int cur = -1; + FormatRange range, lastrange; + for(int i = 0; i < fs.text.length(); i++) { + QTextCharFormat format; + foreach(QTextLayout::FormatRange f, formats) { + if(i >= f.start && i < f.start + f.length) format.merge(f.format); + } + if(cur < 0) { + range.start = 0; range.length = 1; range.format= format; + cur = 0; + } else { + if(format == range.format) range.length++; + else { + QFontMetrics metrics(range.format.font()); + range.height = metrics.lineSpacing(); + ranges.append(range); + range.start = i; range.length = 1; range.format = format; + cur++; + } + } + } + if(cur >= 0) { + QFontMetrics metrics(range.format.font()); + range.height = metrics.lineSpacing(); + ranges.append(range); + } + return ranges; +} + +void ChatLine::setSelection(SelectionMode mode, int start, int end) { + selectionMode = mode; + //tsFormat.clear(); senderFormat.clear(); textFormat.clear(); + QPalette pal = QApplication::palette(); + QTextLayout::FormatRange tsSel, senderSel, textSel; + switch (mode) { + case None: + tsFormat = calcFormatRanges(tsFormatted); + senderFormat = calcFormatRanges(senderFormatted); + textFormat = calcFormatRanges(textFormatted); + break; + case Partial: + selectionStart = qMin(start, end); selectionEnd = qMax(start, end); + textSel.format.setForeground(pal.brush(QPalette::HighlightedText)); + textSel.format.setBackground(pal.brush(QPalette::Highlight)); + textSel.start = selectionStart; + textSel.length = selectionEnd - selectionStart; + //textFormat.append(textSel); + textFormat = calcFormatRanges(textFormatted, textSel); + foreach(FormatRange fr, textFormat); + break; + case Full: + tsSel.format.setForeground(pal.brush(QPalette::HighlightedText)); + tsSel.format.setBackground(pal.brush(QPalette::Highlight)); + tsSel.start = 0; tsSel.length = tsFormatted.text.length(); + tsFormat = calcFormatRanges(tsFormatted, tsSel); + senderSel.format.setForeground(pal.brush(QPalette::HighlightedText)); + senderSel.format.setBackground(pal.brush(QPalette::Highlight)); + senderSel.start = 0; senderSel.length = senderFormatted.text.length(); + senderFormat = calcFormatRanges(senderFormatted, senderSel); + textSel.format.setForeground(pal.brush(QPalette::HighlightedText)); + textSel.format.setBackground(pal.brush(QPalette::Highlight)); + textSel.start = 0; textSel.length = textFormatted.text.length(); + textFormat = calcFormatRanges(textFormatted, textSel); + break; + } +} + +uint ChatLine::msgId() const { + return msg.buffer.uid(); +} + +BufferId ChatLine::bufferId() const { + return msg.buffer; +} + +QDateTime ChatLine::timeStamp() const { + return msg.timeStamp; +} + +QString ChatLine::sender() const { + return senderFormatted.text; +} + +QString ChatLine::text() const { + return textFormatted.text; +} + +bool ChatLine::isUrl(int c) const { + if(c < 0 || c >= charUrlIdx.count()) return false;; + return charUrlIdx[c] >= 0; +} + +QUrl ChatLine::getUrl(int c) const { + if(c < 0 || c >= charUrlIdx.count()) return QUrl(); + int i = charUrlIdx[c]; + if(i >= 0) return textFormatted.urls[i].url; + else return QUrl(); +} + +//!\brief Return the cursor position for the given coordinate pos. +/** + * \param pos The position relative to the ChatLine + * \return The cursor position, [or -3 for invalid,] or -2 for timestamp, or -1 for sender + */ +int ChatLine::posToCursor(QPointF pos) { + if(pos.x() < tsWidth + (int)Style::sepTsSender()/2) return -2; + qreal textStart = tsWidth + Style::sepTsSender() + senderWidth + Style::sepSenderText(); + if(pos.x() < textStart) return -1; + int x = (int)(pos.x() - textStart); + for(int l = lineLayouts.count() - 1; l >=0; l--) { + LineLayout line = lineLayouts[l]; + if(pos.y() >= line.y) { + int offset = charPos[line.start]; x += offset; + for(int i = line.start + line.length - 1; i >= line.start; i--) { + if((charPos[i] + charPos[i+1])/2 <= x) return i+1; // FIXME: Optimize this! + } + return line.start; + } + } +} + +void ChatLine::precomputeLine() { + tsFormat = calcFormatRanges(tsFormatted); + senderFormat = calcFormatRanges(senderFormatted); + textFormat = calcFormatRanges(textFormatted); + + minHeight = 0; + foreach(FormatRange fr, tsFormat) minHeight = qMax(minHeight, fr.height); + foreach(FormatRange fr, senderFormat) minHeight = qMax(minHeight, fr.height); + + words.clear(); + charPos.resize(textFormatted.text.length() + 1); + charHeights.resize(textFormatted.text.length()); + charUrlIdx.fill(-1, textFormatted.text.length()); + for(int i = 0; i < textFormatted.urls.count(); i++) { + Style::UrlInfo url = textFormatted.urls[i]; + for(int j = url.start; j < url.end; j++) charUrlIdx[j] = i; + } + if(!textFormat.count()) return; + int idx = 0; int cnt = 0; int w = 0; int h = 0; + QFontMetrics metrics(textFormat[0].format.font()); + Word wr; + wr.start = -1; wr.trailing = -1; + for(int i = 0; i < textFormatted.text.length(); ) { + charPos[i] = w; charHeights[i] = textFormat[idx].height; + w += metrics.charWidth(textFormatted.text, i); + if(!textFormatted.text[i].isSpace()) { + if(wr.trailing >= 0) { + // new word after space + words.append(wr); + wr.start = -1; + } + if(wr.start < 0) { + wr.start = i; wr.length = 1; wr.trailing = -1; wr.height = textFormat[idx].height; + } else { + wr.length++; wr.height = qMax(wr.height, textFormat[idx].height); + } + } else { + if(wr.start < 0) { + wr.start = i; wr.length = 0; wr.trailing = 1; wr.height = 0; + } else { + wr.trailing++; + } + } + if(++i < textFormatted.text.length() && ++cnt >= textFormat[idx].length) { + cnt = 0; idx++; + Q_ASSERT(idx < textFormat.count()); + metrics = QFontMetrics(textFormat[idx].format.font()); + } + } + charPos[textFormatted.text.length()] = w; + if(wr.start >= 0) words.append(wr); +} + +qreal ChatLine::layout(qreal tsw, qreal senderw, qreal textw) { + tsWidth = tsw; senderWidth = senderw; textWidth = textw; + if(textw <= 0) return minHeight; + lineLayouts.clear(); LineLayout line; + int h = 0; + int offset = 0; int numWords = 0; + line.y = 0; + line.start = 0; + line.height = minHeight; // first line needs room for ts and sender + for(int i = 0; i < words.count(); i++) { + int lastpos = charPos[words[i].start + words[i].length]; // We use charPos[lastchar + 1], 'coz last char needs to fit + if(lastpos - offset <= textw) { + line.height = qMax(line.height, words[i].height); + line.length = words[i].start + words[i].length - line.start; + numWords++; + } else { + // we need to wrap! + if(numWords > 0) { + // ok, we had some words before, so store the layout and start a new line + h += line.height; + line.length = words[i-1].start + words[i-1].length - line.start; + lineLayouts.append(line); + line.y += line.height; + line.start = words[i].start; + line.height = words[i].height; + offset = charPos[words[i].start]; + } + numWords = 1; + // check if the word fits into the current line + if(lastpos - offset <= textw) { + line.length = words[i].length; + } else { + // we need to break a word in the middle + int border = (int)textw + offset; // save some additions + line.start = words[i].start; + line.length = 1; + line.height = charHeights[line.start]; + int j = line.start + 1; + for(int l = 1; l < words[i].length; j++, l++) { + if(charPos[j+1] < border) { + line.length++; + line.height = qMax(line.height, charHeights[j]); + continue; + } else { + h += line.height; + lineLayouts.append(line); + line.y += line.height; + line.start = j; + line.height = charHeights[j]; + line.length = 1; + offset = charPos[j]; + border = (int)textw + offset; + } + } + } + } + } + h += line.height; + if(numWords > 0) { + lineLayouts.append(line); + } + hght = h; + return hght; +} + +//!\brief Draw ChatLine on the given QPainter at the given position. +void ChatLine::draw(QPainter *p, const QPointF &pos) { + QPalette pal = QApplication::palette(); + + if(selectionMode == Full) { + p->setPen(Qt::NoPen); + p->setBrush(pal.brush(QPalette::Highlight)); + p->drawRect(QRectF(pos, QSizeF(tsWidth + Style::sepTsSender() + senderWidth + Style::sepSenderText() + textWidth, height()))); + } else if(selectionMode == Partial) { + + } /* + p->setClipRect(QRectF(pos, QSizeF(tsWidth, height()))); + tsLayout.draw(p, pos, tsFormat); + p->setClipRect(QRectF(pos + QPointF(tsWidth + Style::sepTsSender(), 0), QSizeF(senderWidth, height()))); + senderLayout.draw(p, pos + QPointF(tsWidth + Style::sepTsSender(), 0), senderFormat); + p->setClipping(false); + textLayout.draw(p, pos + QPointF(tsWidth + Style::sepTsSender() + senderWidth + Style::sepSenderText(), 0), textFormat); + */ + //p->setClipRect(QRectF(pos, QSizeF(tsWidth, 15))); + //p->drawRect(QRectF(pos, QSizeF(tsWidth, minHeight))); + p->setBackgroundMode(Qt::OpaqueMode); + QPointF tp = pos; + QRectF rect(pos, QSizeF(tsWidth, minHeight)); + QRectF brect; + foreach(FormatRange fr, tsFormat) { + p->setFont(fr.format.font()); + p->setPen(QPen(fr.format.foreground(), 0)); p->setBackground(fr.format.background()); + p->drawText(rect, Qt::AlignLeft|Qt::TextSingleLine, tsFormatted.text.mid(fr.start, fr.length), &brect); + rect.setLeft(brect.right()); + } + rect = QRectF(pos + QPointF(tsWidth + Style::sepTsSender(), 0), QSizeF(senderWidth, minHeight)); + for(int i = senderFormat.count() - 1; i >= 0; i--) { + FormatRange fr = senderFormat[i]; + p->setFont(fr.format.font()); p->setPen(QPen(fr.format.foreground(), 0)); p->setBackground(fr.format.background()); + p->drawText(rect, Qt::AlignRight|Qt::TextSingleLine, senderFormatted.text.mid(fr.start, fr.length), &brect); + rect.setRight(brect.left()); + } + QPointF tpos = pos + QPointF(tsWidth + Style::sepTsSender() + senderWidth + Style::sepSenderText(), 0); + qreal h = 0; int l = 0; + rect = QRectF(tpos + QPointF(0, h), QSizeF(textWidth, lineLayouts[l].height)); + int offset = 0; + foreach(FormatRange fr, textFormat) { + if(l >= lineLayouts.count()) break; + p->setFont(fr.format.font()); p->setPen(QPen(fr.format.foreground(), 0)); p->setBackground(fr.format.background()); + int start, end, frend, llend; + do { + frend = fr.start + fr.length; + if(frend <= lineLayouts[l].start) break; + llend = lineLayouts[l].start + lineLayouts[l].length; + start = qMax(fr.start, lineLayouts[l].start); end = qMin(frend, llend); + rect.setLeft(tpos.x() + charPos[start] - offset); + p->drawText(rect, Qt::AlignLeft|Qt::TextSingleLine, textFormatted.text.mid(start, end - start), &brect); + if(llend <= end) { + h += lineLayouts[l].height; + l++; + if(l < lineLayouts.count()) { + rect = QRectF(tpos + QPointF(0, h), QSizeF(textWidth, lineLayouts[l].height)); + offset = charPos[lineLayouts[l].start]; + } + } + } while(end < frend && l < lineLayouts.count()); + } +} diff --git a/src/qtgui/chatline.h b/src/qtgui/chatline.h new file mode 100644 index 00000000..b42982c8 --- /dev/null +++ b/src/qtgui/chatline.h @@ -0,0 +1,109 @@ +/*************************************************************************** + * Copyright (C) 2005-07 by The Quassel IRC Development Team * + * devel@quassel-irc.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef _CHATLINE_H_ +#define _CHATLINE_H_ + +#include + +#include "util.h" +#include "style.h" +#include "quasselui.h" + +//FIXME: chatline doku +//!\brief Containing the layout and providing the rendering of a single message. +/** A ChatLine takes a Message object, + * formats it (by turning the various message types into a human-readable form and afterwards pumping it through + * our Style engine), and stores it as a number of QTextLayouts representing the three fields of a chat line + * (timestamp, sender and text). These layouts already include any rendering information such as font, + * color, or selected characters. By calling layout(), they can be quickly layouted to fit a given set of field widths. + * Afterwards, they can quickly be painted whenever necessary. + * + * By separating the complex and slow task of interpreting and formatting Message objects (which happens exactly once + * per message) from the actual layouting and painting, we gain a lot of speed compared to the standard Qt rendering + * functions. + */ +class ChatLine : public QObject, public AbstractUiMsg { + Q_OBJECT + + public: + ChatLine(Message message); + virtual ~ChatLine(); + + qreal layout(qreal tsWidth, qreal nickWidth, qreal textWidth); + qreal height() const { return hght; } + int posToCursor(QPointF pos); + void draw(QPainter *p, const QPointF &pos); + + enum SelectionMode { None, Partial, Full }; + void setSelection(SelectionMode, int start = 0, int end = 0); + + QDateTime timeStamp() const; + QString sender() const; + QString text() const; + MsgId msgId() const; + BufferId bufferId() const; + + bool isUrl(int pos) const; + QUrl getUrl(int pos) const; + + public slots: + + private: + qreal hght; + Message msg; + qreal tsWidth, senderWidth, textWidth; + Style::FormattedString tsFormatted, senderFormatted, textFormatted; + + struct FormatRange { + int start; + int length; + int height; + QTextCharFormat format; + }; + struct Word { + int start; + int length; + int trailing; + int height; + }; + struct LineLayout { + int y; + int height; + int start; + int length; + }; + QVector charPos; + QVector charWidths; + QVector charHeights; + QVector charUrlIdx; + QList tsFormat, senderFormat, textFormat; + QList words; + QList lineLayouts; + int minHeight; + + SelectionMode selectionMode; + int selectionStart, selectionEnd; + void formatMsg(Message); + void precomputeLine(); + QList calcFormatRanges(const Style::FormattedString &, QTextLayout::FormatRange additional = QTextLayout::FormatRange()); +}; + +#endif diff --git a/src/qtgui/chatwidget.cpp b/src/qtgui/chatwidget.cpp index 51ab625c..d67eb9ef 100644 --- a/src/qtgui/chatwidget.cpp +++ b/src/qtgui/chatwidget.cpp @@ -21,8 +21,8 @@ #include "util.h" #include "style.h" #include "chatwidget.h" -#include -#include +#include "chatline.h" + ChatWidget::ChatWidget(QWidget *parent) : QAbstractScrollArea(parent) { scrollTimer = new QTimer(this); @@ -140,6 +140,12 @@ void ChatWidget::clear() { //contents->clear(); } +void ChatWidget::prependMsg(AbstractUiMsg *msg) { + ChatLine *line = dynamic_cast(msg); + Q_ASSERT(line); + prependChatLine(line); +} + void ChatWidget::prependChatLine(ChatLine *line) { qreal h = line->layout(tsWidth, senderWidth, textWidth); for(int i = 1; i < ycoords.count(); i++) ycoords[i] += h; @@ -181,6 +187,11 @@ void ChatWidget::prependChatLines(QList clist) { viewport()->update(); } +void ChatWidget::appendMsg(AbstractUiMsg *msg) { + ChatLine *line = dynamic_cast(msg); + Q_ASSERT(line); + appendChatLine(line); +} void ChatWidget::appendChatLine(ChatLine *line) { qreal h = line->layout(tsWidth, senderWidth, textWidth); @@ -193,6 +204,7 @@ void ChatWidget::appendChatLine(ChatLine *line) { viewport()->update(); } + void ChatWidget::appendChatLines(QList list) { foreach(ChatLine *line, list) { qreal h = line->layout(tsWidth, senderWidth, textWidth); @@ -525,392 +537,6 @@ QString ChatWidget::selectionToString() { /************************************************************************************/ -//!\brief Construct a ChatLine object from a message. -/** - * \param m The message to be layouted and rendered - * \param net The network name - * \param buf The buffer name - */ -ChatLine::ChatLine(Message m) : QObject() { - hght = 0; - //networkName = m.buffer.network(); - //bufferName = m.buffer.buffer(); - msg = m; - selectionMode = None; - formatMsg(msg); -} - -ChatLine::~ChatLine() { - -} - -void ChatLine::formatMsg(Message msg) { - QString user = userFromMask(msg.sender); - QString host = hostFromMask(msg.sender); - QString nick = nickFromMask(msg.sender); - QString text = Style::mircToInternal(msg.text); - QString networkName = msg.buffer.network(); - QString bufferName = msg.buffer.buffer(); - - QString c = tr("%DT[%1]").arg(msg.timeStamp.toLocalTime().toString("hh:mm:ss")); - QString s, t; - switch(msg.type) { - case Message::Plain: - s = tr("%DS<%1>").arg(nick); t = tr("%D0%1").arg(text); break; - case Message::Server: - s = tr("%Ds*"); t = tr("%Ds%1").arg(text); break; - case Message::Error: - s = tr("%De*"); t = tr("%De%1").arg(text); break; - case Message::Join: - s = tr("%Dj-->"); t = tr("%Dj%DN%DU%1%DU%DN %DH(%2@%3)%DH has joined %DC%DU%4%DU%DC").arg(nick, user, host, bufferName); break; - case Message::Part: - s = tr("%Dp<--"); t = tr("%Dp%DN%DU%1%DU%DN %DH(%2@%3)%DH has left %DC%DU%4%DU%DC").arg(nick, user, host, bufferName); - if(!text.isEmpty()) t = QString("%1 (%2)").arg(t).arg(text); - break; - case Message::Quit: - s = tr("%Dq<--"); t = tr("%Dq%DN%DU%1%DU%DN %DH(%2@%3)%DH has quit").arg(nick, user, host); - if(!text.isEmpty()) t = QString("%1 (%2)").arg(t).arg(text); - break; - case Message::Kick: - { s = tr("%Dk<-*"); - QString victim = text.section(" ", 0, 0); - //if(victim == ui.ownNick->currentText()) victim = tr("you"); - QString kickmsg = text.section(" ", 1); - t = tr("%Dk%DN%DU%1%DU%DN has kicked %DN%DU%2%DU%DN from %DC%DU%3%DU%DC").arg(nick).arg(victim).arg(bufferName); - if(!kickmsg.isEmpty()) t = QString("%1 (%2)").arg(t).arg(kickmsg); - } - break; - case Message::Nick: - s = tr("%Dr<->"); - if(nick == msg.text) t = tr("%DrYou are now known as %DN%1%DN").arg(msg.text); - else t = tr("%Dr%DN%1%DN is now known as %DN%DU%2%DU%DN").arg(nick, msg.text); - break; - case Message::Mode: - s = tr("%Dm***"); - if(nick.isEmpty()) t = tr("%DmUser mode: %DM%1%DM").arg(msg.text); - else t = tr("%DmMode %DM%1%DM by %DN%DU%2%DU%DN").arg(msg.text, nick); - break; - case Message::Action: - s = tr("%Da-*-"); - t = tr("%Da%DN%DU%1%DU%DN %2").arg(nick).arg(msg.text); - break; - default: - s = tr("%De%1").arg(msg.sender); - t = tr("%De[%1]").arg(msg.text); - } - QTextOption tsOption, senderOption, textOption; - tsFormatted = Style::internalToFormatted(c); - senderFormatted = Style::internalToFormatted(s); - textFormatted = Style::internalToFormatted(t); - precomputeLine(); -} - -QList ChatLine::calcFormatRanges(const Style::FormattedString &fs, QTextLayout::FormatRange additional) { - QList ranges; - QList formats = fs.formats; - formats.append(additional); - int cur = -1; - FormatRange range, lastrange; - for(int i = 0; i < fs.text.length(); i++) { - QTextCharFormat format; - foreach(QTextLayout::FormatRange f, formats) { - if(i >= f.start && i < f.start + f.length) format.merge(f.format); - } - if(cur < 0) { - range.start = 0; range.length = 1; range.format= format; - cur = 0; - } else { - if(format == range.format) range.length++; - else { - QFontMetrics metrics(range.format.font()); - range.height = metrics.lineSpacing(); - ranges.append(range); - range.start = i; range.length = 1; range.format = format; - cur++; - } - } - } - if(cur >= 0) { - QFontMetrics metrics(range.format.font()); - range.height = metrics.lineSpacing(); - ranges.append(range); - } - return ranges; -} - -void ChatLine::setSelection(SelectionMode mode, int start, int end) { - selectionMode = mode; - //tsFormat.clear(); senderFormat.clear(); textFormat.clear(); - QPalette pal = QApplication::palette(); - QTextLayout::FormatRange tsSel, senderSel, textSel; - switch (mode) { - case None: - tsFormat = calcFormatRanges(tsFormatted); - senderFormat = calcFormatRanges(senderFormatted); - textFormat = calcFormatRanges(textFormatted); - break; - case Partial: - selectionStart = qMin(start, end); selectionEnd = qMax(start, end); - textSel.format.setForeground(pal.brush(QPalette::HighlightedText)); - textSel.format.setBackground(pal.brush(QPalette::Highlight)); - textSel.start = selectionStart; - textSel.length = selectionEnd - selectionStart; - //textFormat.append(textSel); - textFormat = calcFormatRanges(textFormatted, textSel); - foreach(FormatRange fr, textFormat); - break; - case Full: - tsSel.format.setForeground(pal.brush(QPalette::HighlightedText)); - tsSel.format.setBackground(pal.brush(QPalette::Highlight)); - tsSel.start = 0; tsSel.length = tsFormatted.text.length(); - tsFormat = calcFormatRanges(tsFormatted, tsSel); - senderSel.format.setForeground(pal.brush(QPalette::HighlightedText)); - senderSel.format.setBackground(pal.brush(QPalette::Highlight)); - senderSel.start = 0; senderSel.length = senderFormatted.text.length(); - senderFormat = calcFormatRanges(senderFormatted, senderSel); - textSel.format.setForeground(pal.brush(QPalette::HighlightedText)); - textSel.format.setBackground(pal.brush(QPalette::Highlight)); - textSel.start = 0; textSel.length = textFormatted.text.length(); - textFormat = calcFormatRanges(textFormatted, textSel); - break; - } -} - -uint ChatLine::msgId() { - return msg.buffer.uid(); -} - -BufferId ChatLine::bufferId() { - return msg.buffer; -} - -QDateTime ChatLine::timeStamp() { - return msg.timeStamp; -} - -QString ChatLine::sender() { - return senderFormatted.text; -} - -QString ChatLine::text() { - return textFormatted.text; -} - -bool ChatLine::isUrl(int c) { - if(c < 0 || c >= charUrlIdx.count()) return false;; - return charUrlIdx[c] >= 0; -} - -QUrl ChatLine::getUrl(int c) { - if(c < 0 || c >= charUrlIdx.count()) return QUrl(); - int i = charUrlIdx[c]; - if(i >= 0) return textFormatted.urls[i].url; - else return QUrl(); -} - -//!\brief Return the cursor position for the given coordinate pos. -/** - * \param pos The position relative to the ChatLine - * \return The cursor position, [or -3 for invalid,] or -2 for timestamp, or -1 for sender - */ -int ChatLine::posToCursor(QPointF pos) { - if(pos.x() < tsWidth + (int)Style::sepTsSender()/2) return -2; - qreal textStart = tsWidth + Style::sepTsSender() + senderWidth + Style::sepSenderText(); - if(pos.x() < textStart) return -1; - int x = (int)(pos.x() - textStart); - for(int l = lineLayouts.count() - 1; l >=0; l--) { - LineLayout line = lineLayouts[l]; - if(pos.y() >= line.y) { - int offset = charPos[line.start]; x += offset; - for(int i = line.start + line.length - 1; i >= line.start; i--) { - if((charPos[i] + charPos[i+1])/2 <= x) return i+1; // FIXME: Optimize this! - } - return line.start; - } - } -} - -void ChatLine::precomputeLine() { - tsFormat = calcFormatRanges(tsFormatted); - senderFormat = calcFormatRanges(senderFormatted); - textFormat = calcFormatRanges(textFormatted); - - minHeight = 0; - foreach(FormatRange fr, tsFormat) minHeight = qMax(minHeight, fr.height); - foreach(FormatRange fr, senderFormat) minHeight = qMax(minHeight, fr.height); - - words.clear(); - charPos.resize(textFormatted.text.length() + 1); - charHeights.resize(textFormatted.text.length()); - charUrlIdx.fill(-1, textFormatted.text.length()); - for(int i = 0; i < textFormatted.urls.count(); i++) { - Style::UrlInfo url = textFormatted.urls[i]; - for(int j = url.start; j < url.end; j++) charUrlIdx[j] = i; - } - if(!textFormat.count()) return; - int idx = 0; int cnt = 0; int w = 0; int h = 0; - QFontMetrics metrics(textFormat[0].format.font()); - Word wr; - wr.start = -1; wr.trailing = -1; - for(int i = 0; i < textFormatted.text.length(); ) { - charPos[i] = w; charHeights[i] = textFormat[idx].height; - w += metrics.charWidth(textFormatted.text, i); - if(!textFormatted.text[i].isSpace()) { - if(wr.trailing >= 0) { - // new word after space - words.append(wr); - wr.start = -1; - } - if(wr.start < 0) { - wr.start = i; wr.length = 1; wr.trailing = -1; wr.height = textFormat[idx].height; - } else { - wr.length++; wr.height = qMax(wr.height, textFormat[idx].height); - } - } else { - if(wr.start < 0) { - wr.start = i; wr.length = 0; wr.trailing = 1; wr.height = 0; - } else { - wr.trailing++; - } - } - if(++i < textFormatted.text.length() && ++cnt >= textFormat[idx].length) { - cnt = 0; idx++; - Q_ASSERT(idx < textFormat.count()); - metrics = QFontMetrics(textFormat[idx].format.font()); - } - } - charPos[textFormatted.text.length()] = w; - if(wr.start >= 0) words.append(wr); -} - -qreal ChatLine::layout(qreal tsw, qreal senderw, qreal textw) { - tsWidth = tsw; senderWidth = senderw; textWidth = textw; - if(textw <= 0) return minHeight; - lineLayouts.clear(); LineLayout line; - int h = 0; - int offset = 0; int numWords = 0; - line.y = 0; - line.start = 0; - line.height = minHeight; // first line needs room for ts and sender - for(int i = 0; i < words.count(); i++) { - int lastpos = charPos[words[i].start + words[i].length]; // We use charPos[lastchar + 1], 'coz last char needs to fit - if(lastpos - offset <= textw) { - line.height = qMax(line.height, words[i].height); - line.length = words[i].start + words[i].length - line.start; - numWords++; - } else { - // we need to wrap! - if(numWords > 0) { - // ok, we had some words before, so store the layout and start a new line - h += line.height; - line.length = words[i-1].start + words[i-1].length - line.start; - lineLayouts.append(line); - line.y += line.height; - line.start = words[i].start; - line.height = words[i].height; - offset = charPos[words[i].start]; - } - numWords = 1; - // check if the word fits into the current line - if(lastpos - offset <= textw) { - line.length = words[i].length; - } else { - // we need to break a word in the middle - int border = (int)textw + offset; // save some additions - line.start = words[i].start; - line.length = 1; - line.height = charHeights[line.start]; - int j = line.start + 1; - for(int l = 1; l < words[i].length; j++, l++) { - if(charPos[j+1] < border) { - line.length++; - line.height = qMax(line.height, charHeights[j]); - continue; - } else { - h += line.height; - lineLayouts.append(line); - line.y += line.height; - line.start = j; - line.height = charHeights[j]; - line.length = 1; - offset = charPos[j]; - border = (int)textw + offset; - } - } - } - } - } - h += line.height; - if(numWords > 0) { - lineLayouts.append(line); - } - hght = h; - return hght; -} - -//!\brief Draw ChatLine on the given QPainter at the given position. -void ChatLine::draw(QPainter *p, const QPointF &pos) { - QPalette pal = QApplication::palette(); - - if(selectionMode == Full) { - p->setPen(Qt::NoPen); - p->setBrush(pal.brush(QPalette::Highlight)); - p->drawRect(QRectF(pos, QSizeF(tsWidth + Style::sepTsSender() + senderWidth + Style::sepSenderText() + textWidth, height()))); - } else if(selectionMode == Partial) { - - } /* - p->setClipRect(QRectF(pos, QSizeF(tsWidth, height()))); - tsLayout.draw(p, pos, tsFormat); - p->setClipRect(QRectF(pos + QPointF(tsWidth + Style::sepTsSender(), 0), QSizeF(senderWidth, height()))); - senderLayout.draw(p, pos + QPointF(tsWidth + Style::sepTsSender(), 0), senderFormat); - p->setClipping(false); - textLayout.draw(p, pos + QPointF(tsWidth + Style::sepTsSender() + senderWidth + Style::sepSenderText(), 0), textFormat); - */ - //p->setClipRect(QRectF(pos, QSizeF(tsWidth, 15))); - //p->drawRect(QRectF(pos, QSizeF(tsWidth, minHeight))); - p->setBackgroundMode(Qt::OpaqueMode); - QPointF tp = pos; - QRectF rect(pos, QSizeF(tsWidth, minHeight)); - QRectF brect; - foreach(FormatRange fr, tsFormat) { - p->setFont(fr.format.font()); - p->setPen(QPen(fr.format.foreground(), 0)); p->setBackground(fr.format.background()); - p->drawText(rect, Qt::AlignLeft|Qt::TextSingleLine, tsFormatted.text.mid(fr.start, fr.length), &brect); - rect.setLeft(brect.right()); - } - rect = QRectF(pos + QPointF(tsWidth + Style::sepTsSender(), 0), QSizeF(senderWidth, minHeight)); - for(int i = senderFormat.count() - 1; i >= 0; i--) { - FormatRange fr = senderFormat[i]; - p->setFont(fr.format.font()); p->setPen(QPen(fr.format.foreground(), 0)); p->setBackground(fr.format.background()); - p->drawText(rect, Qt::AlignRight|Qt::TextSingleLine, senderFormatted.text.mid(fr.start, fr.length), &brect); - rect.setRight(brect.left()); - } - QPointF tpos = pos + QPointF(tsWidth + Style::sepTsSender() + senderWidth + Style::sepSenderText(), 0); - qreal h = 0; int l = 0; - rect = QRectF(tpos + QPointF(0, h), QSizeF(textWidth, lineLayouts[l].height)); - int offset = 0; - foreach(FormatRange fr, textFormat) { - if(l >= lineLayouts.count()) break; - p->setFont(fr.format.font()); p->setPen(QPen(fr.format.foreground(), 0)); p->setBackground(fr.format.background()); - int start, end, frend, llend; - do { - frend = fr.start + fr.length; - if(frend <= lineLayouts[l].start) break; - llend = lineLayouts[l].start + lineLayouts[l].length; - start = qMax(fr.start, lineLayouts[l].start); end = qMin(frend, llend); - rect.setLeft(tpos.x() + charPos[start] - offset); - p->drawText(rect, Qt::AlignLeft|Qt::TextSingleLine, textFormatted.text.mid(start, end - start), &brect); - if(llend <= end) { - h += lineLayouts[l].height; - l++; - if(l < lineLayouts.count()) { - rect = QRectF(tpos + QPointF(0, h), QSizeF(textWidth, lineLayouts[l].height)); - offset = charPos[lineLayouts[l].start]; - } - } - } while(end < frend && l < lineLayouts.count()); - } -} /******************************************************************************************************************/ diff --git a/src/qtgui/chatwidget.h b/src/qtgui/chatwidget.h index 2fdd8957..f15be23f 100644 --- a/src/qtgui/chatwidget.h +++ b/src/qtgui/chatwidget.h @@ -21,13 +21,14 @@ #ifndef _CHATWIDGET_H_ #define _CHATWIDGET_H_ -#include "style.h" -#include "message.h" -#include "buffer.h" -#include +//#include "style.h" +//#include "message.h" +//#include "buffer.h" +//#include #include class ChatLine; +class AbstractUiMsg; //!\brief Scroll area showing part of the chat messages for a given buffer. /** The contents of the scroll area, i.e. a widget of type ChatWidgetContents, @@ -52,6 +53,10 @@ class ChatWidget : public QAbstractScrollArea { public slots: void clear(); + + void prependMsg(AbstractUiMsg *); + void appendMsg(AbstractUiMsg *); + void prependChatLine(ChatLine *); void appendChatLine(ChatLine *); void prependChatLines(QList); @@ -118,115 +123,4 @@ class ChatWidget : public QAbstractScrollArea { }; -//FIXME: chatline doku -//!\brief Containing the layout and providing the rendering of a single message. -/** A ChatLine takes a Message object, - * formats it (by turning the various message types into a human-readable form and afterwards pumping it through - * our Style engine), and stores it as a number of QTextLayouts representing the three fields of a chat line - * (timestamp, sender and text). These layouts already include any rendering information such as font, - * color, or selected characters. By calling layout(), they can be quickly layouted to fit a given set of field widths. - * Afterwards, they can quickly be painted whenever necessary. - * - * By separating the complex and slow task of interpreting and formatting Message objects (which happens exactly once - * per message) from the actual layouting and painting, we gain a lot of speed compared to the standard Qt rendering - * functions. - */ -class ChatLine : public QObject { - Q_OBJECT - - public: - ChatLine(Message message); - ~ChatLine(); - - qreal layout(qreal tsWidth, qreal nickWidth, qreal textWidth); - qreal height() { return hght; } - int posToCursor(QPointF pos); - void draw(QPainter *p, const QPointF &pos); - - enum SelectionMode { None, Partial, Full }; - void setSelection(SelectionMode, int start = 0, int end = 0); - QDateTime timeStamp(); - QString sender(); - QString text(); - uint msgId(); - BufferId bufferId(); - - bool isUrl(int pos); - QUrl getUrl(int pos); - - public slots: - - private: - qreal hght; - Message msg; - qreal tsWidth, senderWidth, textWidth; - Style::FormattedString tsFormatted, senderFormatted, textFormatted; - - struct FormatRange { - int start; - int length; - int height; - QTextCharFormat format; - }; - struct Word { - int start; - int length; - int trailing; - int height; - }; - struct LineLayout { - int y; - int height; - int start; - int length; - }; - QVector charPos; - QVector charWidths; - QVector charHeights; - QVector charUrlIdx; - QList tsFormat, senderFormat, textFormat; - QList words; - QList lineLayouts; - int minHeight; - - SelectionMode selectionMode; - int selectionStart, selectionEnd; - void formatMsg(Message); - void precomputeLine(); - QList calcFormatRanges(const Style::FormattedString &, QTextLayout::FormatRange additional = QTextLayout::FormatRange()); -}; - -/* -struct LayoutTask { - QList messages; - Buffer *buffer; - QString net, buf; - QList lines; -}; - -Q_DECLARE_METATYPE(LayoutTask); - -class LayoutThread : public QThread { - Q_OBJECT - - public: - LayoutThread(); - virtual ~LayoutThread(); - virtual void run(); - - public: - void processTask(LayoutTask task); - - signals: - void taskProcessed(LayoutTask task); - - private: - QList queue; - QMutex mutex; - QWaitCondition condition; - bool abort; - -}; -*/ - #endif diff --git a/src/qtgui/mainwin.cpp b/src/qtgui/mainwin.cpp index 05cd7d3d..0ef57c18 100644 --- a/src/qtgui/mainwin.cpp +++ b/src/qtgui/mainwin.cpp @@ -30,6 +30,7 @@ #include "mainwin.h" #include "buffer.h" +#include "chatline.h" #include "serverlist.h" #include "coreconnectdlg.h" #include "settingsdlg.h" @@ -50,27 +51,6 @@ MainWin::MainWin() : QMainWindow() { } void MainWin::init() { -/* - connect(guiProxy, SIGNAL(csServerState(QString, QVariant)), this, SLOT(recvNetworkState(QString, QVariant))); - connect(guiProxy, SIGNAL(csServerConnected(QString)), this, SLOT(networkConnected(QString))); - connect(guiProxy, SIGNAL(csServerDisconnected(QString)), this, SLOT(networkDisconnected(QString))); - connect(guiProxy, SIGNAL(csDisplayMsg(Message)), this, SLOT(recvMessage(Message))); - connect(guiProxy, SIGNAL(csDisplayStatusMsg(QString, QString)), this, SLOT(recvStatusMsg(QString, QString))); - connect(guiProxy, SIGNAL(csTopicSet(QString, QString, QString)), this, SLOT(setTopic(QString, QString, QString))); - connect(guiProxy, SIGNAL(csNickAdded(QString, QString, VarMap)), this, SLOT(addNick(QString, QString, VarMap))); - connect(guiProxy, SIGNAL(csNickRemoved(QString, QString)), this, SLOT(removeNick(QString, QString))); - connect(guiProxy, SIGNAL(csNickRenamed(QString, QString, QString)), this, SLOT(renameNick(QString, QString, QString))); - connect(guiProxy, SIGNAL(csNickUpdated(QString, QString, VarMap)), this, SLOT(updateNick(QString, QString, VarMap))); - connect(guiProxy, SIGNAL(csOwnNickSet(QString, QString)), this, SLOT(setOwnNick(QString, QString))); - connect(guiProxy, SIGNAL(csBacklogData(BufferId, QList, bool)), this, SLOT(recvBacklogData(BufferId, QList, bool))); - connect(guiProxy, SIGNAL(csUpdateBufferId(BufferId)), this, SLOT(updateBufferId(BufferId))); - connect(this, SIGNAL(sendInput(BufferId, QString)), guiProxy, SLOT(gsUserInput(BufferId, QString))); - connect(this, SIGNAL(requestBacklog(BufferId, QVariant, QVariant)), guiProxy, SLOT(gsRequestBacklog(BufferId, QVariant, QVariant))); - - //layoutThread = new LayoutThread(); - //layoutThread->start(); - //while(!layoutThread->isRunning()) {}; -*/ ui.bufferWidget->init(); show(); @@ -179,6 +159,10 @@ void MainWin::registerBufferViewDock(BufferViewDock *dock) { */ } +AbstractUiMsg *MainWin::layoutMsg(const Message &msg) { + return new ChatLine(msg); +} + void MainWin::showServerList() { // if(!serverListDlg) { // serverListDlg = new ServerListDlg(this); diff --git a/src/qtgui/mainwin.h b/src/qtgui/mainwin.h index d8936583..15852a82 100644 --- a/src/qtgui/mainwin.h +++ b/src/qtgui/mainwin.h @@ -24,7 +24,8 @@ #include #include "ui_mainwin.h" -#include "global.h" +#include "quasselui.h" +//#include "global.h" #include "message.h" #include "chatwidget.h" #include "bufferviewfilter.h" @@ -42,7 +43,7 @@ class SettingsDlg; * dockwidgets and of course the chat window, this class also stores all data it * receives from the core, and it maintains a list of all known nicks. */ -class MainWin : public QMainWindow { +class MainWin : public QMainWindow, public AbstractUi { Q_OBJECT public: @@ -52,36 +53,14 @@ class MainWin : public QMainWindow { void init(); void registerBufferViewDock(BufferViewDock *); + AbstractUiMsg *layoutMsg(const Message &); + protected: void closeEvent(QCloseEvent *event); - signals: - //void sendInput(BufferId, QString message); - //void bufferSelected(Buffer *); - //void bufferUpdated(Buffer *); - //void bufferActivity(Buffer::ActivityLevel, Buffer *); - //void bufferDestroyed(Buffer *); - //void backlogReceived(Buffer *, QList); - //void requestBacklog(BufferId, QVariant, QVariant); - - void importOldBacklog(); + //void importOldBacklog(); private slots: - - //void userInput(BufferId, QString); - //void networkConnected(QString); - //void networkDisconnected(QString); - //void recvNetworkState(QString, QVariant); - //void recvMessage(Message message); - //void recvStatusMsg(QString network, QString message); - //void setTopic(QString net, QString buf, QString); - //void addNick(QString net, QString nick, VarMap props); - //void removeNick(QString net, QString nick); - //void renameNick(QString net, QString oldnick, QString newnick); - //void updateNick(QString net, QString nick, VarMap props); - //void setOwnNick(QString net, QString nick); - //void recvBacklogData(BufferId, QList, bool); - //void updateBufferId(BufferId); void showServerList(); void showSettingsDlg(); @@ -91,43 +70,26 @@ class MainWin : public QMainWindow { void importBacklog(); + signals: + void importOldBacklog(); + private: Ui::MainWin ui; void setupMenus(); void setupViews(); void setupSettingsDlg(); - //void syncToCore(); // implemented in main_mono.cpp or main_gui.cpp - //Buffer * getBuffer(QString net, QString buf); - //Buffer *getBuffer(BufferId); - //BufferId getStatusBufferId(QString net); - //BufferId getBufferId(QString net, QString buf); - //void buffersUpdated(); QSystemTrayIcon *systray; - //QWorkspace *workspace; - //QWidget *widget; - //BufferWidget *bufferWidget; ServerListDlg *serverListDlg; CoreConnectDlg *coreConnectDlg; SettingsDlg *settingsDlg; - //QString currentNetwork, currentBuffer; - //QHash > buffers; uint currentBuffer; - //QHash buffers; - //QHash bufferIds; - //QHash > nicks; - //QHash connected; - //QHash ownNick; - //QHash > coreBackLog; - //QList coreBuffers; QList netViews; - //QTimer *layoutTimer; - //QList layoutQueue; }; #endif diff --git a/templates/cpp b/templates/cpp index 53f70707..9151cb79 100644 --- a/templates/cpp +++ b/templates/cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-07 by The Quassel Team * + * Copyright (C) 2005-07 by The Quassel IRC Development Team * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * diff --git a/templates/h b/templates/h index 21a1438d..2a25675a 100644 --- a/templates/h +++ b/templates/h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-07 by The Quassel Team * + * Copyright (C) 2005-07 by The Quassel IRC Development Team * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * -- 2.20.1