commit ce290e834f2d006904b2aa77845cd4ff6e8ec240 Author: Andrew Lee (李健秋) Date: Sun Aug 16 00:43:27 2015 +0800 Adding upstream version 0.6.0. Signed-off-by: Andrew Lee (李健秋) diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..2834917 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,22 @@ +Project maintainer: Petr Vanek + +Contributors: + +Alexander Sokolov +Alf Gaida +Christian Surlykke +Daniel O'Neill +Erik Ridderby +Felix Schnizlein +Francisco Ballina +Ilya87 +Jerome Leclanche +Johannes Jordan +Ludger Krämer +Maxim Bourmitrov +Mikhail Ivchenko +Sweet Tea Dorminy +Vladimir Kuznetsov +Matteo Pasotti +@kulti +@pisculichi diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..16d0d44 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,238 @@ +cmake_minimum_required(VERSION 2.8) + +project(qterminal) + +option(USE_SYSTEM_QXT "Use system Qxt Library for global shortcuts" ON) +option(USE_QT5 "Build using Qt5. Default OFF." OFF) + +set(STR_VERSION "0.6.0") + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") +set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules") + +if(USE_QT5 AND USE_SYSTEM_QXT) + message(FATAL_ERROR "Unable to use system qxt with qt5 now") +endif() + +if(USE_QT5) + find_package(Qt5Widgets REQUIRED) + find_package(Qt5LinguistTools REQUIRED) + find_package(QTermWidget5 REQUIRED) + message(STATUS "Qt5 version: ${Qt5Core_VERSION_STRING}") +else() + find_package(QTermWidget4 REQUIRED) +endif() + +include(${QTERMWIDGET_USE_FILE}) + +if(USE_SYSTEM_QXT) + message(STATUS "Using system Qxt...") + find_package(Qxt REQUIRED COMPONENTS QxtCore QxtGui) + if(NOT QXT_FOUND) + message(FATAL_ERROR "System Qxt not found. Install Qxt devel package or use -DUSE_SYSTEM_QXT=0 to build with internal copy of this library") + endif() + + set(QXT_INCLUDE_DIRS "${QXT_INCLUDE_PATH}/QxtCore" "${QXT_INCLUDE_PATH}/QxtGui") +else() + message(STATUS "Using bundled Qxt...") + set(QXT_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src/third-party") +endif() + + +if(APPLE) + find_library(CARBON_LIBRARY Carbon REQUIRED) + message(STATUS "CARBON_LIBRARY: ${CARBON_LIBRARY}") +elseif(UNIX) + find_package(X11 REQUIRED) + message(STATUS "X11_X11_LIB: ${X11_X11_LIB}") +endif () + +add_definitions(-DSTR_VERSION=\"${STR_VERSION}\") + + +set(EXE_NAME qterminal) + +set(QTERM_SRC + src/main.cpp + src/mainwindow.cpp + src/tabwidget.cpp + src/termwidget.cpp + src/termwidgetholder.cpp + src/properties.cpp + src/propertiesdialog.cpp + src/bookmarkswidget.cpp + src/fontdialog.cpp +) + +set(QTERM_MOC_SRC + src/mainwindow.h + src/tabwidget.h + src/termwidget.h + src/termwidgetholder.h + src/propertiesdialog.h + src/bookmarkswidget.h + src/fontdialog.h +) + +if(NOT QXT_FOUND) + set(QTERM_SRC ${QTERM_SRC} src/third-party/qxtglobalshortcut.cpp) + set(QTERM_MOC_SRC ${QTERM_MOC_SRC} src/third-party/qxtglobalshortcut.h) + + if(WIN32) + set(QTERM_SRC ${QTERM_SRC} src/third-party/qxtglobalshortcut_win.cpp) + elseif(APPLE) + set(QTERM_SRC ${QTERM_SRC} src/third-party/qxtglobalshortcut_mac.cpp) + else() + set(QTERM_SRC ${QTERM_SRC} src/third-party/qxtglobalshortcut_x11.cpp) + endif() +endif() + +set(QTERM_UI_SRC + src/forms/qterminal.ui + src/forms/propertiesdialog.ui + src/forms/bookmarkswidget.ui + src/forms/fontdialog.ui +) + +set(QTERM_RCC_SRC + src/icons.qrc +) + +set(QTERM_TS + src/translations/qterminal_cs.ts + src/translations/qterminal_de.ts + src/translations/qterminal_es.ts + src/translations/qterminal_et.ts + src/translations/qterminal_it.ts + src/translations/qterminal_ru.ts +) + +if(USE_QT5) + qt5_wrap_ui( QTERM_UI ${QTERM_UI_SRC} ) + qt5_wrap_cpp( QTERM_MOC ${QTERM_MOC_SRC} ) + qt5_add_resources( QTERM_RCC ${QTERM_RCC_SRC} ) + qt5_add_translation( QTERM_QM ${QTERM_TS} ) + # bundled qt5 version of libqxt requires private headers (as for 2014-05-27) + include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS}) +else() + qt4_wrap_ui(QTERM_UI ${QTERM_UI_SRC}) + qt4_wrap_cpp(QTERM_MOC ${QTERM_MOC_SRC}) + qt4_add_resources(QTERM_RCC ${QTERM_RCC_SRC}) + qt4_add_translation(QTERM_QM ${QTERM_TS}) +endif() + +include_directories ( + "${CMAKE_SOURCE_DIR}" + "${CMAKE_SOURCE_DIR}/src" + "${CMAKE_BINARY_DIR}" + ${QTERMWIDGET_INCLUDE_DIRS} + ${QXT_INCLUDE_DIRS} +) +if(X11_FOUND) + include_directories("${X11_INCLUDE_DIR}") +endif() + + +# TODO/FIXME: apple bundle +set(GUI_TYPE "") +set(APPLE_BUNDLE_SOURCES "") +if(APPLEBUNDLE) + add_definitions(-DAPPLE_BUNDLE) + set(GUI_TYPE MACOSX_BUNDLE) + + # create Info.plist file + set(MACOSX_BUNDLE_ICON_FILE qterminal.icns) + set(MACOSX_BUNDLE_INFO_STRING "QTerminal ${STR_VERSION}") + set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.qterminal") + set(MACOSX_BUNDLE_LONG_VERSION_STRING "${STR_VERSION}") + set(MACOSX_BUNDLE_BUNDLE_NAME "${EXE_NAME}") + set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${STR_VERSION}") + set(MACOSX_BUNDLE_BUNDLE_VERSION "${STR_VERSION}") + set(MACOSX_BUNDLE_COPYRIGHT "(c) Petr Vanek <petr@yarpen.cz>") + + set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/macosx/qterminal.icns" + PROPERTIES MACOSX_PACKAGE_LOCATION Resources + ) + # use icon for app bundle to be visible in finder + set(APPLE_BUNDLE_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/macosx/qterminal.icns") +else() + set(TRANSLATIONS_DIR "${CMAKE_INSTALL_PREFIX}/share/qterminal/translations") + add_definitions(-DTRANSLATIONS_DIR=\"${TRANSLATIONS_DIR}\") +endif() + +add_executable(${EXE_NAME} ${GUI_TYPE} + ${QTERM_SRC} + ${QTERM_UI} + ${QTERM_MOC} + ${QTERM_RCC} + ${APPLE_BUNDLE_SOURCES} + ${QTERM_QM} +) +target_link_libraries(${EXE_NAME} + ${QTERMWIDGET_QT_LIBRARIES} + ${QTERMWIDGET_LIBRARIES} + util +) +if(QXT_FOUND) + target_link_libraries(${EXE_NAME} ${QXT_CORE_LIB} ${QXT_GUI_LIB}) +endif() + +if(APPLE) + target_link_libraries(${EXE_NAME} ${CARBON_LIBRARY}) +endif() + +if(X11_FOUND) + target_link_libraries(${EXE_NAME} ${X11_X11_LIB}) +endif() + + +install(FILES qterminal.desktop DESTINATION share/applications) +install(FILES qterminal_drop.desktop DESTINATION share/applications) + + +if(NOT APPLEBUNDLE) + install(TARGETS ${EXE_NAME} RUNTIME DESTINATION bin) + install(FILES ${QTERM_QM} DESTINATION ${TRANSLATIONS_DIR}) + install(FILES src/icons/qterminal.png DESTINATION share/pixmaps) +else() + message(STATUS "APPLEBUNDLE") + + install(CODE "message(STATUS \"Cleaning previously installed bundle (rm -r)\")") + install(CODE "execute_process(COMMAND rm -r ${CMAKE_INSTALL_PREFIX}/${EXE_NAME}.app)") + + install(TARGETS ${EXE_NAME} DESTINATION "${CMAKE_INSTALL_PREFIX}") + + # helper stuff to create real apple bundle. + # Black magic is summoned here... + if(APPLEBUNDLE_STANDALONE) + message(STATUS "APPLEBUNDLE_STANDALONE") + configure_file("${CMAKE_SOURCE_DIR}/bundle.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/bundle.cmake" @ONLY) + install(SCRIPT "${CMAKE_SOURCE_DIR}/bundle.cmake") + endif() + + # bundle required keytabs from the qtermwidget package as well + install(CODE "message(STATUS \"Bundling (cp) keytab files from ${QTERMWIDGET_SHARE}/qtermwidget/\")") + install(CODE "execute_process(COMMAND cp -r ${QTERMWIDGET_SHARE}/qtermwidget/ ${CMAKE_INSTALL_PREFIX}/${EXE_NAME}.app/Contents/Resources)") + + install(FILES ${QTERM_QM} DESTINATION ${CMAKE_INSTALL_PREFIX}/${EXE_NAME}.app/Contents/translations) +endif() + + +# make lupdate +# it generates new translation files +add_custom_target(lupdate + ${QT_QMAKE_EXECUTABLE} -project -o "${CMAKE_CURRENT_BINARY_DIR}/qterminal.pro" + COMMAND ${QT_LUPDATE_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/qterminal.pro" + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" +) + +# make dist custom target +set(CPACK_PACKAGE_NAME "qterminal") +set(CPACK_PACKAGE_VERSION ${STR_VERSION}) +set(CPACK_SOURCE_GENERATOR "TGZ;TBZ2") +set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") +set(CPACK_IGNORE_FILES "/CVS/;/\\\\.svn/;/\\\\.git/;\\\\.swp$;\\\\.#;/#;\\\\.tar.gz$;/CMakeFiles/;CMakeCache.txt;\\\\.qm$;/build/;\\\\.diff$;.DS_Store'") +set(CPACK_SOURCE_IGNORE_FILES ${CPACK_IGNORE_FILES}) +include(CPack) +# simulate autotools' "make dist" +add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..a849a6d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,23 @@ +# Bug reports + +Please file bugs on the qterminal github tracker: + https://github.com/qterminal/qterminal/ + +Please file qtermwidget-related bugs on the qtermwidget github tracker: + https://github.com/qterminal/qtermwidget/ + + +# Code contributions + +For all code contributions, please open a pull request on Github: + https://github.com/qterminal/qterminal/ + +Make sure your code is clean, devoid of debug statements and respects the style +of the rest of the file (including line length and indentation). + +Do not pollute the git history with unnecessary commits! Make sure each of your +commits compiles to ensure ease of bisection and have clear separation of one +feature or bugfix per commit. + +Please also make sure you set your `git.name` and `git.email` options properly: + https://help.github.com/articles/setting-your-email-in-git/ diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/Doxyfile b/Doxyfile new file mode 100644 index 0000000..956c4e2 --- /dev/null +++ b/Doxyfile @@ -0,0 +1,1630 @@ +# Doxyfile 1.7.1 + +# 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 = QTerminal + +# 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 = 0.2 + +# 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 = docs + +# 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, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# 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 = + +# 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 = NO + +# 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 = YES + +# 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 = + +# 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 = NO + +# 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 regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_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 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 + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# 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 + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# 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 = NO + +# 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 + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# 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 = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# 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 = YES + +# 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 this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = 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 = NO + +# 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 = NO + +# 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 = NO + +# 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 FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# 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 = YES + +# 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_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = 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 = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = 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 = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# 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 = NO + +# 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 +#--------------------------------------------------------------------------- + +# 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 *.f90 + +FILE_PATTERNS = *.cpp *.h + +# 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 = NO + +#--------------------------------------------------------------------------- +# 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 = NO + +# 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 +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# 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 documentation. + +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 = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the stylesheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# 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 HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# 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 compiled 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 CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# 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 + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# 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 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value 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 (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = 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 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvances is that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# 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 = YES + +# 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. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +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 = YES + +# 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 + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = 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 = NO + +# 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 = NO + +# 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 = + +# 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 = YES + +#--------------------------------------------------------------------------- +# 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 = + +# 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 = NO + +# 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 + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans.ttf + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# 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 = NO + +# 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 options 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 = NO + +# 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 = NO + +# 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 = + +# The 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 if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. 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 diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..6f3d270 --- /dev/null +++ b/INSTALL @@ -0,0 +1,16 @@ +Requirements: + Qt4 or Qt5 + cmake + qtermwidget (https://github.com/qterminal/qtermwidget) + +Build: + A shadow build (out of source) is strongly recommended + http://www.cmake.org/Wiki/CMake_FAQ#Out-of-source_build_trees + + 1) mkdir -p build && cd build + 2a) cmake path/to/source -DUSE_QT5=true # Qt 5 + 2b) cmake path/to/source # Qt 4 only + 3) make + 4) optional: make install + + Read cmake docs to fine tune the build process (CMAKE_INSTALL_PREFIX, etc...) diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/README b/README new file mode 100644 index 0000000..283403d --- /dev/null +++ b/README @@ -0,0 +1,8 @@ +qterminal + +## Installation +See the INSTALL file for details + +## Translations + - Edit src/CMakeLists.txt to add a new ts file. + - make lupdate updates ts files to be translated (lrelease is called automatically in make) diff --git a/cmake/modules/FindQxt.cmake b/cmake/modules/FindQxt.cmake new file mode 100644 index 0000000..b50508f --- /dev/null +++ b/cmake/modules/FindQxt.cmake @@ -0,0 +1,62 @@ +# QXT_FOUND +# QXT_INCLUDE_PATH +# QXT_CORE_LIB +# QXT_GUI_LIB + +IF (WIN32) + FIND_PATH( QXT_INCLUDE_PATH QxtCore + $ENV{PROGRAMFILES}/QxtCore + PATHS/include/ + DOC "The directory where QxtCore resides") + FIND_LIBRARY( QXT_CORE_LIB + NAMES QxtCore + PATHS/lib + $ENV{PROGRAMFILES}/lib + DOC "The Qxt core library") + FIND_LIBRARY( QXT_GUI_LIB + NAMES QxtGui + PATHS/lib + $ENV{PROGRAMFILES}/lib + DOC "The Qxt gui library") +ELSE (WIN32) + FIND_PATH( QXT_INCLUDE_PATH QxtCore + /usr/include + /usr/include/qxt + /usr/local/include + /sw/include + /opt/local/include + DOC "The directory where QxtCore resides") + FIND_LIBRARY( QXT_CORE_LIB + NAMES QxtCore + PATHS + /usr/lib64 + /usr/lib + /usr/local/lib64 + /usr/local/lib + /sw/lib + /opt/local/lib + DOC "The Qxt core library") + FIND_LIBRARY( QXT_GUI_LIB + NAMES QxtGui + PATHS + /usr/lib64 + /usr/lib + /usr/local/lib64 + /usr/local/lib + /sw/lib + /opt/local/lib + DOC "The Qxt gui library") +ENDIF (WIN32) + +message(STATUS "Qxt includes: ${QXT_INCLUDE_PATH}") +message(STATUS "Qxt libs: ${QXT_CORE_LIB} ${QXT_GUI_LIB}") +IF (QXT_INCLUDE_PATH) + SET( QXT_FOUND 1 CACHE STRING "Set to 1 if QXT is found, 0 otherwise") +ELSE (QXT_INCLUDE_PATH) + SET( QXT_FOUND 0 CACHE STRING "Set to 1 if QXT is found, 0 otherwise") +ENDIF (QXT_INCLUDE_PATH) + +SET( QXT_LIBS ${QXT_CORE_LIB} ${QXT_GUI_LIB} ) + +MARK_AS_ADVANCED( QXT_FOUND ) + diff --git a/qterminal.desktop b/qterminal.desktop new file mode 100644 index 0000000..6b34a58 --- /dev/null +++ b/qterminal.desktop @@ -0,0 +1,52 @@ +[Desktop Entry] +Name=QTerminal +Type=Application +GenericName=Terminal emulator + +Comment=Terminal emulator +Comment[ru_RU]=Эмулятор терминала +Comment[fr]=Terminal + +Icon=utilities-terminal +Exec=qterminal +Terminal=false +Categories=Qt;System;TerminalEmulator; +Actions=Dropdown; + +[Desktop Action Dropdown] +Name=Drop-down terminal +Icon=qterminal +Exec=qterminal --drop + +Name[en_GB]=Drop-down Terminal +Name[bg]=Падащ терминал +Name[ca]=Terminal desplegable +Name[ca@valencia]=Terminal desplegable +Name[cs]=Vysouvací terminál +Name[da]=Terminal der ruller ned +Name[de]=Aufklapp-Terminal +Name[es]=Terminal de menú desplegable +Name[et]=Lahtikeriv terminal +Name[fr]=Terminal déroulant +Name[hr]=Spuštajući terminal +Name[hu]=Legördülő terminál +Name[it]=Terminale a discesa +Name[ja]=ドロップダウン式ターミナル +Name[km]=ស្ថានីយ​ទម្លាក់​ចុះ +Name[ko]=위에서 내려오는 터미널 +Name[nb]=Nedtrekksterminal +Name[nds]=Utklapp-Konsool +Name[nl]=Uitvouwbare terminalemulator +Name[pa]=ਲਟਕਦਾ ਟਰਮੀਨਲ +Name[pt]=Terminal Deslizante +Name[pt_BR]=Terminal suspenso +Name[ro]=Terminal derulant +Name[ru]=Выпадающий терминал +Name[sk]=Rozbaľovací terminál +Name[sv]=Rullgardinsterminal +Name[th]=เทอร์มินัลแบบหย่อนลง +Name[tr]=Yukarıdan Açılan Uçbirim +Name[uk]=Спадний термінал +Name[x-test]=xxDrop-down Terminalxx +Name[zh_CN]=拉幕式终端 +Name[zh_TW]=下拉式終端機 diff --git a/qterminal.pro b/qterminal.pro new file mode 100644 index 0000000..4979ad9 --- /dev/null +++ b/qterminal.pro @@ -0,0 +1,32 @@ +TARGET = qterminal +TEMPLATE = app +# qt5 only. Please use cmake - it's an official build tool for this software +QT += widgets + +CONFIG += link_pkgconfig +PKGCONFIG += qtermwidget5 + +DEFINES += STR_VERSION=\\\"0.5.0\\\" + +SOURCES += $$files(src/*.cpp) +HEADERS += $$files(src/*.h) + +INCLUDEPATH += src + +RESOURCES += src/icons.qrc +FORMS += $$files(src/forms/*.ui) + +unix { + isEmpty(PREFIX) { + PREFIX = /usr/local + } + BINDIR = $$PREFIX/bin + + INSTALLS += target shortcut + target.path = $$BINDIR + + DATADIR = $$PREFIX/share + shortcut.path = $$DATADIR/applications + shortcut.files = qterminal.desktop +} + diff --git a/qterminal_drop.desktop b/qterminal_drop.desktop new file mode 100644 index 0000000..3c0e182 --- /dev/null +++ b/qterminal_drop.desktop @@ -0,0 +1,49 @@ +[Desktop Entry] +Type=Application +Exec=qterminal --drop +Terminal=false +Categories=Qt;System;TerminalEmulator; +Icon=qterminal + +Name=QTerminal drop down +GenericName=Drop-down Terminal + +GenericName[bg]=Падащ терминал +GenericName[ca]=Terminal desplegable +GenericName[ca@valencia]=Terminal desplegable +GenericName[cs]=Vysouvací terminál +GenericName[da]=Terminal der ruller ned +GenericName[de]=Aufklapp-Terminal +GenericName[en_GB]=Drop-down Terminal +GenericName[es]=Terminal de menú desplegable +GenericName[et]=Lahtikeriv terminal +GenericName[fr]=Terminal déroulant +GenericName[hr]=Spuštajući terminal +GenericName[hu]=Legördülő terminál +GenericName[it]=Terminale a discesa +GenericName[ja]=ドロップダウン式ターミナル +GenericName[km]=ស្ថានីយ​ទម្លាក់​ចុះ +GenericName[ko]=위에서 내려오는 터미널 +GenericName[nb]=Nedtrekksterminal +GenericName[nds]=Utklapp-Konsool +GenericName[nl]=Uitvouwbare terminalemulator +GenericName[pa]=ਲਟਕਦਾ ਟਰਮੀਨਲ +GenericName[pt]=Terminal Deslizante +GenericName[pt_BR]=Terminal suspenso +GenericName[ro]=Terminal derulant + +GenericName[ru]=Выпадающий терминал +Comment[ru]=Вападающий эмулятор терминала. + +GenericName[sk]=Rozbaľovací terminál +GenericName[sv]=Rullgardinsterminal +GenericName[th]=เทอร์มินัลแบบหย่อนลง +GenericName[tr]=Yukarıdan Açılan Uçbirim +GenericName[uk]=Спадний термінал +GenericName[x-test]=xxDrop-down Terminalxx +GenericName[zh_CN]=拉幕式终端 +GenericName[zh_TW]=下拉式終端機 + +Comment=A drop-down terminal emulator. + + diff --git a/src/bookmarkswidget.cpp b/src/bookmarkswidget.cpp new file mode 100644 index 0000000..e202922 --- /dev/null +++ b/src/bookmarkswidget.cpp @@ -0,0 +1,419 @@ +#if QT_VERSION < 0x050000 +#include +#else +#include +#endif + +#include + +#include "bookmarkswidget.h" +#include "properties.h" +#include "config.h" + + +class AbstractBookmarkItem +{ +public: + enum ItemType { + Root = 0, + Group = 1, + Command = 2 + }; + + AbstractBookmarkItem(AbstractBookmarkItem* parent = 0) + { + m_parent = parent; + } + ~AbstractBookmarkItem() + { + qDeleteAll(m_children); + } + + ItemType type() { return m_type; } + QString value() { return m_value; } + QString display() { return m_display; } + + void addChild(AbstractBookmarkItem* item) { m_children << item; } + int childCount() { return m_children.count(); } + QList children() { return m_children; } + AbstractBookmarkItem *child(int number) { return m_children.value(number); } + AbstractBookmarkItem *parent() { return m_parent; } + + int childNumber() const + { + if (m_parent) + return m_parent->children().indexOf(const_cast(this)); + + return 0; + } + +protected: + ItemType m_type; + AbstractBookmarkItem *m_parent; + QList m_children; + QString m_value; + QString m_display; +}; + +class BookmarkRootItem : public AbstractBookmarkItem +{ +public: + BookmarkRootItem() + : AbstractBookmarkItem() + { + m_type = AbstractBookmarkItem::Root; + m_value = m_display = "root"; + } +}; + +class BookmarkCommandItem : public AbstractBookmarkItem +{ +public: + BookmarkCommandItem(const QString &name, const QString &command, AbstractBookmarkItem *parent) + : AbstractBookmarkItem(parent) + { + m_type = AbstractBookmarkItem::Command; + m_value = command; + m_display = name; + } +}; + + +class BookmarkGroupItem : public AbstractBookmarkItem +{ +public: + BookmarkGroupItem(const QString &name, AbstractBookmarkItem *parent) + : AbstractBookmarkItem(parent) + { + m_type = AbstractBookmarkItem::Group; + m_display = name; + } +}; + +class BookmarkLocalGroupItem : public BookmarkGroupItem +{ +public: + BookmarkLocalGroupItem(AbstractBookmarkItem *parent) + : BookmarkGroupItem(QObject::tr("Local Bookmarks"), parent) + { +#if QT_VERSION < 0x050000 + QList locations; + locations << QDesktopServices::DesktopLocation + << QDesktopServices::DocumentsLocation + << QDesktopServices::TempLocation + << QDesktopServices::HomeLocation + << QDesktopServices::MusicLocation + << QDesktopServices::PicturesLocation; + + QString path; + QString name; + QString cmd; + QDir d; + + // standard $HOME subdirs + foreach (QDesktopServices::StandardLocation i, locations) + { + path = QDesktopServices::storageLocation(i); + if (!d.exists(path)) + { + //qDebug() << "Dir:" << path << "does not exist. Skipping."; + continue; + } + // it works in Qt5, not in Qt4 + // name = QDesktopServices::displayName(i); + name = path; + + path.replace(" ", "\\ "); + cmd = "cd " + path; + + addChild(new BookmarkCommandItem(name, cmd, this)); + } +#else + QList locations; + locations << QStandardPaths::DesktopLocation + << QStandardPaths::DocumentsLocation + << QStandardPaths::TempLocation + << QStandardPaths::HomeLocation + << QStandardPaths::MusicLocation + << QStandardPaths::PicturesLocation; + + QString path; + QString name; + QString cmd; + QDir d; + + // standard $HOME subdirs + foreach (QStandardPaths::StandardLocation i, locations) + { + path = QStandardPaths::writableLocation(i); + if (!d.exists(path)) + { + //qDebug() << "Dir:" << path << "does not exist. Skipping."; + continue; + } + name = QStandardPaths::displayName(i); + + path.replace(" ", "\\ "); + cmd = "cd " + path; + + addChild(new BookmarkCommandItem(name, cmd, this)); + } +#endif + + // system env - include dirs in the tree + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + foreach (QString i, env.keys()) + { + path = env.value(i); + if (!d.exists(path) || !QFileInfo(path).isDir()) + { + //qDebug() << "Env Dir:" << path << "does not exist. Skipping."; + continue; + } + path.replace(" ", "\\ "); + cmd = "cd " + path; + addChild(new BookmarkCommandItem(i, cmd, this)); + } + } +}; + +class BookmarkFileGroupItem : public BookmarkGroupItem +{ + // hierarchy handling + // m_pos to group map. Example: group1.group2=item + QHash m_map; + // current position level. Example "group1", "group2" + QStringList m_pos; + +public: + BookmarkFileGroupItem(AbstractBookmarkItem *parent, const QString &fname) + : BookmarkGroupItem(QObject::tr("Synchronized Bookmarks"), parent) + { + QFile f(fname); + if (!f.open(QIODevice::ReadOnly)) + { + qDebug() << "Canot open file" << fname; + // TODO/FIXME: message box + return; + } + + QXmlStreamReader xml; + xml.setDevice(&f); + + while (true) + { + xml.readNext(); + + switch (xml.tokenType()) + { + case QXmlStreamReader::StartElement: + { + AbstractBookmarkItem *parent = m_map.contains(xmlPos()) ? m_map[xmlPos()] : this; + QString tag = xml.name().toString(); + if (tag == "group") + { + QString name = xml.attributes().value("name").toString(); + m_pos.append(name); + + BookmarkGroupItem *i = new BookmarkGroupItem(name, parent); + parent->addChild(i); + + m_map[xmlPos()] = i; + } + else if (tag == "command") + { + QString name = xml.attributes().value("name").toString(); + QString cmd = xml.attributes().value("value").toString(); + + BookmarkCommandItem *i = new BookmarkCommandItem(name, cmd, parent); + parent->addChild(i); + } + break; + } + case QXmlStreamReader::EndElement: + { + QString tag = xml.name().toString(); + if (tag == "group") + { + m_pos.removeLast(); + } + break; + } + case QXmlStreamReader::Invalid: + qDebug() << "XML error: " << xml.errorString().data() + << xml.lineNumber() << xml.columnNumber(); + m_map.clear(); + return; + break; + case QXmlStreamReader::EndDocument: + m_map.clear(); + return; + break; + } // switch + } // while + } // constructor + + QString xmlPos() + { + return m_pos.join("."); + } +}; + + +BookmarksModel::BookmarksModel(QObject *parent) + : QAbstractItemModel(parent), + m_root(0) +{ + setup(); +} + +void BookmarksModel::setup() +{ + if (m_root) + delete m_root; + m_root = new BookmarkRootItem(); + m_root->addChild(new BookmarkLocalGroupItem(m_root)); + m_root->addChild(new BookmarkFileGroupItem(m_root, Properties::Instance()->bookmarksFile)); + beginResetModel(); + endResetModel(); +} + +BookmarksModel::~BookmarksModel() +{ + if (m_root) + delete m_root; +} + +int BookmarksModel::columnCount(const QModelIndex & /* parent */) const +{ + return 2; +} + +QVariant BookmarksModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + switch (role) + { + case Qt::DisplayRole: + case Qt::EditRole: + return index.column() == 0 ? getItem(index)->display() : getItem(index)->value(); + case Qt::FontRole: + { + QFont f; + if (static_cast(index.internalPointer())->type() == AbstractBookmarkItem::Group) + { + f.setBold(true); + } + return f; + } + default: + return QVariant(); + } +} + +AbstractBookmarkItem *BookmarksModel::getItem(const QModelIndex &index) const +{ + if (index.isValid()) + { + AbstractBookmarkItem *item = static_cast(index.internalPointer()); + if (item) + return item; + } + return m_root; + } + +QVariant BookmarksModel::headerData(int section, Qt::Orientation orientation, + int role) const +{ + return QVariant(); +} + +QModelIndex BookmarksModel::index(int row, int column, const QModelIndex &parent) const +{ + if (parent.isValid() && parent.column() != 0) + return QModelIndex(); + + AbstractBookmarkItem *parentItem = getItem(parent); + + AbstractBookmarkItem *childItem = parentItem->child(row); + if (childItem) + return createIndex(row, column, childItem); + else + return QModelIndex(); +} + + +QModelIndex BookmarksModel::parent(const QModelIndex &index) const +{ + if (!index.isValid()) + return QModelIndex(); + + AbstractBookmarkItem *childItem = getItem(index); + AbstractBookmarkItem *parentItem = childItem->parent(); + + if (parentItem == m_root) + return QModelIndex(); + + return createIndex(parentItem->childNumber(), 0, parentItem); +} + +int BookmarksModel::rowCount(const QModelIndex &parent) const +{ + AbstractBookmarkItem *parentItem = getItem(parent); + return parentItem->childCount(); +} + +#if 0 +bool BookmarksModel::setData(const QModelIndex &index, const QVariant &value, + int role) +{ + if (role != Qt::EditRole) + return false; + + AbstractBookmarkItem *item = getItem(index); + bool result = item->setData(index.column(), value); + + if (result) + emit dataChanged(index, index); + + return result; +} +#endif + + +BookmarksWidget::BookmarksWidget(QWidget *parent) + : QWidget(parent) +{ + setupUi(this); + + m_model = new BookmarksModel(this); + treeView->setModel(m_model); + treeView->header()->hide(); + + connect(treeView, SIGNAL(doubleClicked(QModelIndex)), + this, SLOT(handleCommand(QModelIndex))); +} + +BookmarksWidget::~BookmarksWidget() +{ +} + +void BookmarksWidget::setup() +{ + m_model->setup(); + + treeView->expandAll(); + treeView->resizeColumnToContents(0); + treeView->resizeColumnToContents(1); +} + +void BookmarksWidget::handleCommand(const QModelIndex& index) +{ + AbstractBookmarkItem *item = static_cast(index.internalPointer()); + if (!item && item->type() != AbstractBookmarkItem::Command) + return; + + emit callCommand(item->value() + "\n"); // TODO/FIXME: decide how to handle EOL +} diff --git a/src/bookmarkswidget.h b/src/bookmarkswidget.h new file mode 100644 index 0000000..b5e3415 --- /dev/null +++ b/src/bookmarkswidget.h @@ -0,0 +1,58 @@ +#ifndef BOOKMARKSWIDGET_H +#define BOOKMARKSWIDGET_H + +#include "ui_bookmarkswidget.h" + +class AbstractBookmarkItem; +class BookmarksModel; + + +class BookmarksWidget : public QWidget, Ui::BookmarksWidget +{ + Q_OBJECT + +public: + BookmarksWidget(QWidget *parent=NULL); + ~BookmarksWidget(); + + void setup(); + +signals: + void callCommand(const QString &cmd); + +private: + BookmarksModel *m_model; + +private slots: + void handleCommand(const QModelIndex& index); +}; + + +class BookmarksModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + BookmarksModel(QObject *parent = 0); + ~BookmarksModel(); + + void setup(); + + QVariant data(const QModelIndex &index, int role) const; + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + + QModelIndex index(int row, int column, + const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &index) const; + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + +private: + AbstractBookmarkItem *getItem(const QModelIndex &index) const; + AbstractBookmarkItem *m_root; +}; + +#endif + diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..7997e74 --- /dev/null +++ b/src/config.h @@ -0,0 +1,110 @@ +/*************************************************************************** + * Copyright (C) 2006 by Vladimir Kuznetsov * + * vovanec@gmail.com * + * * + * 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 CONFIG_H +#define CONFIG_H + +#define ADD_TAB "Add Tab" +#define RENAME_TAB "Rename Tab" +#define CLOSE_TAB "Close Tab" +#define NEW_WINDOW "New Window" + +#define QUIT "Quit" +#define PREFERENCES "Preferences..." + +#define TAB_NEXT "Next Tab" +#define TAB_PREV "Previous Tab" + +#define CLEAR_TERMINAL "Clear Active Terminal" + +#define SPLIT_HORIZONTAL "Split Terminal Horizontally" +#define SPLIT_VERTICAL "Split Terminal Vertically" + +#define SUB_COLLAPSE "Collapse Subterminal" +#define SUB_NEXT "Next Subterminal" +#define SUB_PREV "Previous Subterminal" + +#define MOVE_LEFT "Move Tab Left" +#define MOVE_RIGHT "Move Tab Right" + +#define COPY_SELECTION "Copy Selection" +#define PASTE_CLIPBOARD "Paste Clipboard" +#define PASTE_SELECTION "Paste Selection" + +#define ZOOM_IN "Zoom in" +#define ZOOM_OUT "Zoom out" +#define ZOOM_RESET "Zoom reset" + +#define FIND "Find" + +#define TOGGLE_MENU "Toggle Menu" +#define TOGGLE_BOOKMARKS "Toggle Bookmarks" + +/* Some defaults for QTerminal application */ + +#define DEFAULT_WIDTH 800 +#define DEFAULT_HEIGHT 600 +#define DEFAULT_FONT "Monospace" + +// ACTIONS +#define CLEAR_TERMINAL_SHORTCUT "Ctrl+Shift+X" +#define TAB_PREV_SHORTCUT "Shift+Left" +#define TAB_NEXT_SHORTCUT "Shift+Right" +#define SUB_PREV_SHORTCUT "Shift+Down" +#define SUB_NEXT_SHORTCUT "Shift+Up" + +#ifdef Q_WS_MAC +// It's tricky - Ctrl is "command" key on mac's keyboards +#define COPY_SELECTION_SHORTCUT "Ctrl+C" +#define PASTE_CLIPBOARD_SHORTCUT "Ctrl+V" +#define FIND_SHORTCUT "Ctrl+F" +#define NEW_WINDOW_SHORTCUT "Ctrl+N" +#define ADD_TAB_SHORTCUT "Ctrl+T" +#define CLOSE_TAB_SHORTCUT "Ctrl+W" +#define TOGGLE_MENU_SHORTCUT "Ctrl+M" +#define TOGGLE_BOOKMARKS_SHORTCUT "Ctrl+B" +#else +#define COPY_SELECTION_SHORTCUT "Ctrl+Shift+C" +#define PASTE_CLIPBOARD_SHORTCUT "Ctrl+Shift+V" +#define PASTE_SELECTION_SHORTCUT "Shift+Ins" +#define FIND_SHORTCUT "Ctrl+Shift+F" +#define NEW_WINDOW_SHORTCUT "Ctrl+Shift+N" +#define ADD_TAB_SHORTCUT "Ctrl+Shift+T" +#define CLOSE_TAB_SHORTCUT "Ctrl+Shift+W" +#define TOGGLE_MENU_SHORTCUT "Ctrl+Shift+M" +#define TOGGLE_BOOKMARKS_SHORTCUT "Ctrl+Shift+B" +#endif + +#define ZOOM_IN_SHORTCUT "Ctrl++" +#define ZOOM_OUT_SHORTCUT "Ctrl+-" +#define ZOOM_RESET_SHORTCUT "Ctrl+0" + +#define MOVE_LEFT_SHORTCUT "Shift+Alt+Left" +#define MOVE_RIGHT_SHORTCUT "Shift+Alt+Right" + +#define RENAME_SESSION_SHORTCUT "Shift+Alt+S" + +// XON/XOFF features: + +#define FLOW_CONTROL_ENABLED false +#define FLOW_CONTROL_WARNING_ENABLED false + +#endif diff --git a/src/fontdialog.cpp b/src/fontdialog.cpp new file mode 100644 index 0000000..183ad16 --- /dev/null +++ b/src/fontdialog.cpp @@ -0,0 +1,39 @@ + +#include "fontdialog.h" + +FontDialog::FontDialog(const QFont &f) + : QDialog(0) +{ + setupUi(this); + + fontComboBox->setFontFilters(QFontComboBox::MonospacedFonts + | QFontComboBox::NonScalableFonts + | QFontComboBox::ScalableFonts); + + fontComboBox->setCurrentFont(f); + fontComboBox->setEditable(false); + + sizeSpinBox->setValue(f.pointSize()); + + setFontSample(); + + connect(fontComboBox, SIGNAL(currentFontChanged(QFont)), + this, SLOT(setFontSample())); + connect(sizeSpinBox, SIGNAL(valueChanged(int)), + this, SLOT(setFontSample())); +} + +QFont FontDialog::getFont() +{ + QFont f = fontComboBox->currentFont(); + f.setPointSize(sizeSpinBox->value()); + return f; +} + +void FontDialog::setFontSample() +{ + QFont f = getFont(); + previewLabel->setFont(f); + QString sample("%1 %2 pt"); + previewLabel->setText(sample.arg(f.family()).arg(f.pointSize())); +} diff --git a/src/fontdialog.h b/src/fontdialog.h new file mode 100644 index 0000000..7522173 --- /dev/null +++ b/src/fontdialog.h @@ -0,0 +1,21 @@ +#ifndef FONT_DIALOG +#define FONT_DIALOG + +#include "ui_fontdialog.h" +#include "properties.h" + + + +class FontDialog : public QDialog, public Ui::FontDialog +{ + Q_OBJECT +public: + FontDialog(const QFont &f); + QFont getFont(); + +private slots: + void setFontSample(); + +}; + +#endif diff --git a/src/forms/bookmarkswidget.ui b/src/forms/bookmarkswidget.ui new file mode 100644 index 0000000..ee74a5e --- /dev/null +++ b/src/forms/bookmarkswidget.ui @@ -0,0 +1,50 @@ + + + BookmarksWidget + + + + 0 + 0 + 323 + 450 + + + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + + + Filter: + + + + + + + + + + true + + + + + + + + diff --git a/src/forms/fontdialog.ui b/src/forms/fontdialog.ui new file mode 100644 index 0000000..964f48a --- /dev/null +++ b/src/forms/fontdialog.ui @@ -0,0 +1,114 @@ + + + FontDialog + + + + 0 + 0 + 296 + 187 + + + + Select Terminal Font + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + Font: + + + + + + + + + + Size: + + + + + + + 6 + + + 10 + + + + + + + Preview + + + + + + + + + + + + + + Select Terminal Font + + + + + + + + + buttonBox + accepted() + FontDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + FontDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/forms/propertiesdialog.ui b/src/forms/propertiesdialog.ui new file mode 100644 index 0000000..296724d --- /dev/null +++ b/src/forms/propertiesdialog.ui @@ -0,0 +1,630 @@ + + + PropertiesDialog + + + + 0 + 0 + 463 + 386 + + + + QTerminal Properties + + + + + + Qt::Horizontal + + + QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 100 + 16777215 + + + + + Terminal Font + + + + + Look and Feel + + + + + History + + + + + Emulation + + + + + Shortcuts + + + + + DropDown + + + + + Bookmarks + + + + + + + + QFrame::StyledPanel + + + 1 + + + + + + + Font + + + + + + QFrame::StyledPanel + + + + + + true + + + + + + + Qt::Horizontal + + + + 117 + 20 + + + + + + + + &Set Font... + + + + + + + + + + Qt::Vertical + + + + 20 + 3 + + + + + + + + Note: only fixed width font are allowed to be used in terminal + + + true + + + + + + + + + + + + + + Action after paste clipboard + + + + + + + Color Scheme: + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 0 + + + + + + + + Tabs Position: + + + + + + + GUI Style: + + + + + + + % + + + 1 + + + 99 + + + + + + + Terminal Transparency: + + + + + + + % + + + 1 + + + 100 + + + 100 + + + + + + + Scrollbar Position: + + + + + + + &Application Transparency: + + + appOpacityBox + + + + + + + + + + &Highlight Current Terminal With Border + + + + + + + Ask for Window Closing Confirmation + + + + + + + + + + Open New Sub-Terminals in Current Working Dir + + + + + + + Show Main Menu + + + + + + + Always Show Tabs + + + + + + + + + + + History + + + + + + Limited to: + + + + + + + 100 + + + 1000000 + + + 1000 + + + + + + + Unlimited + + + + + + + Qt::Vertical + + + + 150 + 139 + + + + + + + + + + + + + + + Emulation Type + + + + + + + + + Select emulation behaviour. It does not mean that for example "linux" has to be used only on Linux OS. Feel free to use it on Mac too etc.<p>Default is the failback type with minimal feature set. + + + Qt::RichText + + + true + + + + + + + + + + Qt::Vertical + + + + 20 + 57 + + + + + + + + + + + + true + + + QAbstractItemView::ScrollPerPixel + + + QAbstractItemView::ScrollPerPixel + + + true + + + 105 + + + false + + + + Shortcut + + + + + Key + + + + + + + + + + + + Show on start + + + + + + + Size + + + + + + + + Height %: + + + + + + + + + + Width %: + + + + + + + + + + + + + + + + + Shortcut: + + + + + + + + + + + + Qt::Vertical + + + + 20 + 78 + + + + + + + + + + + + Edit File Content + + + + + + + Bera Sans Mono [bitstream] + 11 + + + + QPlainTextEdit::NoWrap + + + + + + + + + + Use Bookmarks + + + + + + + + + Bookmark FIle: + + + + + + + + + + Find... + + + + + + + + + You can specify your own bookmarks file location. It allows easy bookmark sharing with tools like OwnCloud or Dropbox. + + + true + + + + + + + + + + + + + buttonBox + accepted() + PropertiesDialog + accept() + + + 224 + 227 + + + 157 + 248 + + + + + buttonBox + rejected() + PropertiesDialog + reject() + + + 292 + 233 + + + 286 + 248 + + + + + listWidget + currentRowChanged(int) + stackedWidget + setCurrentIndex(int) + + + 96 + 70 + + + 147 + 24 + + + + + diff --git a/src/forms/qterminal.ui b/src/forms/qterminal.ui new file mode 100644 index 0000000..f44ddde --- /dev/null +++ b/src/forms/qterminal.ui @@ -0,0 +1,141 @@ + + + mainWindow + + + + 0 + 0 + 600 + 420 + + + + MainWindow + + + true + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 320 + 200 + + + + QTabWidget::South + + + QTabWidget::Rounded + + + -1 + + + Qt::ElideNone + + + + + + + + + 0 + 0 + 600 + 19 + + + + + File + + + + + + + + Actions + + + + + Help + + + + + + + View + + + + + Edit + + + + + + + + + + + + + + About... + + + + + About Qt... + + + + + &Preferences... + + + + + + + + &Quit + + + + + + TabWidget + QTabWidget +
tabwidget.h
+ 1 +
+
+ + + + +
diff --git a/src/icons.qrc b/src/icons.qrc new file mode 100644 index 0000000..eafc173 --- /dev/null +++ b/src/icons.qrc @@ -0,0 +1,16 @@ + + + icons/index.theme + icons/qterminal.png + icons/list-add.png + icons/list-remove.png + icons/edit-copy.png + icons/edit-paste.png + icons/document-close.png + icons/application-exit.png + icons/locked.png + icons/notlocked.png + icons/zoom-in.png + icons/zoom-out.png + + diff --git a/src/icons/application-exit.png b/src/icons/application-exit.png new file mode 100644 index 0000000..dd76354 Binary files /dev/null and b/src/icons/application-exit.png differ diff --git a/src/icons/document-close.png b/src/icons/document-close.png new file mode 100644 index 0000000..23b0947 Binary files /dev/null and b/src/icons/document-close.png differ diff --git a/src/icons/edit-copy.png b/src/icons/edit-copy.png new file mode 100644 index 0000000..d4180c6 Binary files /dev/null and b/src/icons/edit-copy.png differ diff --git a/src/icons/edit-paste.png b/src/icons/edit-paste.png new file mode 100644 index 0000000..4a109a1 Binary files /dev/null and b/src/icons/edit-paste.png differ diff --git a/src/icons/index.theme b/src/icons/index.theme new file mode 100644 index 0000000..0f9a3f1 --- /dev/null +++ b/src/icons/index.theme @@ -0,0 +1,31 @@ +[Icon Theme] +Name=QTerminal +Comment=Default Icons used in QTerminal +Inherits=default +Directories=16x16,22x22,24x24,32x32,scalable + +[16x16] +Size=16 +Type=Fixed + +[22x22] +Size=22 +Type=Fixed + +[24x24] +Size=24 +Type=Fixed + +[32x32] +Size=32 +Type=Fixed + +[64x64] +Size=64 +Type=Fixed + +[scalable] +Size=48 +Type=Scalable +MinSize=32 +MaxSize=256 diff --git a/src/icons/list-add.png b/src/icons/list-add.png new file mode 100644 index 0000000..5724694 Binary files /dev/null and b/src/icons/list-add.png differ diff --git a/src/icons/list-remove.png b/src/icons/list-remove.png new file mode 100644 index 0000000..53506b0 Binary files /dev/null and b/src/icons/list-remove.png differ diff --git a/src/icons/locked.png b/src/icons/locked.png new file mode 100644 index 0000000..c6d26f9 Binary files /dev/null and b/src/icons/locked.png differ diff --git a/src/icons/notlocked.png b/src/icons/notlocked.png new file mode 100644 index 0000000..143bee4 Binary files /dev/null and b/src/icons/notlocked.png differ diff --git a/src/icons/qterminal.png b/src/icons/qterminal.png new file mode 100644 index 0000000..8e2f3c1 Binary files /dev/null and b/src/icons/qterminal.png differ diff --git a/src/icons/zoom-in.png b/src/icons/zoom-in.png new file mode 100644 index 0000000..8660d29 Binary files /dev/null and b/src/icons/zoom-in.png differ diff --git a/src/icons/zoom-out.png b/src/icons/zoom-out.png new file mode 100644 index 0000000..23e2a76 Binary files /dev/null and b/src/icons/zoom-out.png differ diff --git a/src/macosx/bundle.cmake.in b/src/macosx/bundle.cmake.in new file mode 100644 index 0000000..52c9f1d --- /dev/null +++ b/src/macosx/bundle.cmake.in @@ -0,0 +1,60 @@ +# +# This is evil! I don't know why it works this way. +# But it works. +# +# First - collect all Qt and App plugins. Then call that bloody +# cmake FIXUP_BUNDLE macro which copis all files into MacOS directory. +# So it's moved back to plugins tree where its expected by a) Qt b) application +# +# I hate it. +# + +# Dunno what id this var for... +SET(DIRS @QT_LIBRARY_DIRS@;@QT_PLUGINS_DIR@;@CMAKE_INSTALL_PREFIX@/Contents/plugins/) + +# qt_menu.nib is mandatory for mac +if (@QT_USE_FRAMEWORKS@) + file(COPY @QT_LIBRARY_DIR@/QtGui.framework/Resources/qt_menu.nib + DESTINATION @CMAKE_INSTALL_PREFIX@/@EXE_NAME@.app/Contents/Resources) +else () + file(COPY @QT_LIBRARY_DIR@/Resources/qt_menu.nib + DESTINATION @CMAKE_INSTALL_PREFIX@/@EXE_NAME@.app/Contents/Resources) +endif () + +# the qt.conf is mandatory too +file(WRITE @CMAKE_INSTALL_PREFIX@/@EXE_NAME@.app/Contents/Resources/qt.conf "[Paths] +Plugins = plugins") + +# copy all (required) Qt plugs into bundle +message(STATUS "Searching for Qt plugs in: @QT_PLUGINS_DIR@/*@CMAKE_SHARED_LIBRARY_SUFFIX@") +file(COPY @QT_PLUGINS_DIR@/ + DESTINATION @CMAKE_INSTALL_PREFIX@/@EXE_NAME@.app/Contents/plugins/ + REGEX "(designer|script|debug|sql|odbc|phonon|svg|mng|tiff|gif|bearer|accessible|)" EXCLUDE) + #REGEX "(.*)" EXCLUDE) + +# try to FIXUP_BUNDLE - to change otool -L paths +# currently it creates lots of false warnings when plugins are compiled as dylibs +# warning: cannot resolve item 'libfoobar.dylib' +# etc. Ignore it. +message(STATUS "Searching for plugs in bundle: @CMAKE_INSTALL_PREFIX@/@EXE_NAME@.app/Contents/plugins/*@CMAKE_SHARED_LIBRARY_SUFFIX@") +file(GLOB_RECURSE inplugs + @CMAKE_INSTALL_PREFIX@/@EXE_NAME@.app/Contents/plugins/*@CMAKE_SHARED_LIBRARY_SUFFIX@) + +#message(STATUS "Dylibs: ${inplugs}") +#message(STATUS "DIR: ${DIRS}") + +include(BundleUtilities) +fixup_bundle(@CMAKE_INSTALL_PREFIX@/@EXE_NAME@.app "${inplugs}" @CMAKE_INSTALL_PREFIX@/Contents/plugins/)#${DIRS} ) + +# FIXUP_BUNDLE copies it into MacOS dir. But we need it in plugins *tree*, +# not a flat dir. +foreach (item IN LISTS inplugs) + #message(STATUS "IN: ${item}") + get_filename_component(fname ${item} NAME) + message(STATUS "Moving ${fname} back to plugins tree: ${item}") + #message(STATUS " ${fname}") + #message(STATUS " src: @CMAKE_INSTALL_PREFIX@/@EXE_NAME@.app/Contents/MacOS/${fname}") + #message(STATUS " tgt: ${item}") + execute_process(COMMAND mv @CMAKE_INSTALL_PREFIX@/@EXE_NAME@.app/Contents/MacOS/${fname} ${item}) +endforeach() + diff --git a/src/macosx/qterminal.icns b/src/macosx/qterminal.icns new file mode 100644 index 0000000..c96faf8 Binary files /dev/null and b/src/macosx/qterminal.icns differ diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..af996a6 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,154 @@ +/*************************************************************************** + * Copyright (C) 2006 by Vladimir Kuznetsov * + * vovanec@gmail.com * + * * + * 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 +#include + +#include +#include +#include + +#include "mainwindow.h" + +#define out + +const char* const short_options = "vhw:e:dp:"; + +const struct option long_options[] = { + {"version", 0, NULL, 'v'}, + {"help", 0, NULL, 'h'}, + {"workdir", 1, NULL, 'w'}, + {"execute", 1, NULL, 'e'}, + {"drop", 0, NULL, 'd'}, + {"profile", 1, NULL, 'p'}, + {NULL, 0, NULL, 0} +}; + +void print_usage_and_exit(int code) +{ + printf("QTerminal %s\n", STR_VERSION); + puts("Usage: qterminal [OPTION]...\n"); + puts(" -d, --drop Start in \"dropdown mode\" (like Yakuake or Tilda)"); + puts(" -e, --execute Execute command instead of shell"); + puts(" -h, --help Print this help"); + puts(" -p, --profile Load qterminal with specific options"); + puts(" -v, --version Prints application version and exits"); + puts(" -w, --workdir Start session with specified work directory"); + puts("\nHomepage: "); + puts("Report bugs to "); + exit(code); +} + +void print_version_and_exit(int code=0) +{ + printf("%s\n", STR_VERSION); + exit(code); +} + +void parse_args(int argc, char* argv[], QString& workdir, QString & shell_command, out bool& dropMode) +{ + int next_option; + dropMode = false; + do{ + next_option = getopt_long(argc, argv, short_options, long_options, NULL); + switch(next_option) + { + case 'h': + print_usage_and_exit(0); + case 'w': + workdir = QString(optarg); + break; + case 'e': + shell_command = QString(optarg); + // #15 "Raw" -e params + // Passing "raw" params (like konsole -e mcedit /tmp/tmp.txt") is more preferable - then I can call QString("qterminal -e ") + cmd_line in other programs + while (optind < argc) + { + //printf("arg: %d - %s\n", optind, argv[optind]); + shell_command += ' ' + QString(argv[optind++]); + } + break; + case 'd': + dropMode = true; + break; + case 'p': + Properties::Instance(QString(optarg)); + break; + case '?': + print_usage_and_exit(1); + case 'v': + print_version_and_exit(); + } + } + while(next_option != -1); +} + +int main(int argc, char *argv[]) +{ + setenv("TERM", "xterm", 1); // TODO/FIXME: why? + + QApplication::setApplicationName("qterminal"); + QApplication::setApplicationVersion(STR_VERSION); + QApplication::setOrganizationDomain("qterminal.org"); + // Warning: do not change settings format. It can screw bookmarks later. + QSettings::setDefaultFormat(QSettings::IniFormat); + + QApplication app(argc, argv); + QString workdir, shell_command; + bool dropMode; + parse_args(argc, argv, workdir, shell_command, dropMode); + + if (workdir.isEmpty()) + workdir = QDir::currentPath(); + + // icons + /* setup our custom icon theme if there is no system theme (OS X, Windows) */ + if (QIcon::themeName().isEmpty()) + QIcon::setThemeName("QTerminal"); + + // translations + QString fname = QString("qterminal_%1.qm").arg(QLocale::system().name().left(2)); + QTranslator translator; +#ifdef TRANSLATIONS_DIR + qDebug() << "TRANSLATIONS_DIR: Loading translation file" << fname << "from dir" << TRANSLATIONS_DIR; + qDebug() << "load success:" << translator.load(fname, TRANSLATIONS_DIR, "_"); +#endif +#ifdef APPLE_BUNDLE + qDebug() << "APPLE_BUNDLE: Loading translator file" << fname << "from dir" << QApplication::applicationDirPath()+"../translations"; + qDebug() << "load success:" << translator.load(fname, QApplication::applicationDirPath()+"../translations", "_"); +#endif + app.installTranslator(&translator); + + MainWindow *window; + if (dropMode) + { + QWidget *hiddenPreviewParent = new QWidget(0, Qt::Tool); + window = new MainWindow(workdir, shell_command, dropMode, hiddenPreviewParent); + if (Properties::Instance()->dropShowOnStart) + window->show(); + } + else + { + window = new MainWindow(workdir, shell_command, dropMode); + window->show(); + } + + return app.exec(); +} diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp new file mode 100644 index 0000000..fc85cce --- /dev/null +++ b/src/mainwindow.cpp @@ -0,0 +1,621 @@ +/*************************************************************************** + * Copyright (C) 2006 by Vladimir Kuznetsov * + * vovanec@gmail.com * + * * + * 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 +#include +#include +#include + +#include "mainwindow.h" +#include "tabwidget.h" +#include "termwidgetholder.h" +#include "config.h" +#include "properties.h" +#include "propertiesdialog.h" +#include "bookmarkswidget.h" + + +// TODO/FXIME: probably remove. QSS makes it unusable on mac... +#define QSS_DROP "MainWindow {border: 1px solid rgba(0, 0, 0, 50%);}\n" + +MainWindow::MainWindow(const QString& work_dir, + const QString& command, + bool dropMode, + QWidget * parent, + Qt::WindowFlags f) + : QMainWindow(parent,f), + m_initShell(command), + m_initWorkDir(work_dir), + m_dropLockButton(0), + m_dropMode(dropMode) +{ + setupUi(this); + Properties::Instance()->loadSettings(); + migrate_settings(); + + m_bookmarksDock = new QDockWidget(tr("Bookmarks"), this); + BookmarksWidget *bookmarksWidget = new BookmarksWidget(m_bookmarksDock); + m_bookmarksDock->setWidget(bookmarksWidget); + addDockWidget(Qt::LeftDockWidgetArea, m_bookmarksDock); + connect(bookmarksWidget, SIGNAL(callCommand(QString)), + this, SLOT(bookmarksWidget_callCommand(QString))); + + connect(m_bookmarksDock, SIGNAL(visibilityChanged(bool)), + this, SLOT(bookmarksDock_visibilityChanged(bool))); + + connect(actAbout, SIGNAL(triggered()), SLOT(actAbout_triggered())); + connect(actAboutQt, SIGNAL(triggered()), qApp, SLOT(aboutQt())); + connect(&m_dropShortcut, SIGNAL(activated()), SLOT(showHide())); + + setContentsMargins(0, 0, 0, 0); + if (m_dropMode) { + this->enableDropMode(); + setStyleSheet(QSS_DROP); + } + else { + restoreGeometry(Properties::Instance()->mainWindowGeometry); + restoreState(Properties::Instance()->mainWindowState); + } + + connect(consoleTabulator, SIGNAL(closeTabNotification()), SLOT(close())); + consoleTabulator->setWorkDirectory(work_dir); + consoleTabulator->setTabPosition((QTabWidget::TabPosition)Properties::Instance()->tabsPos); + //consoleTabulator->setShellProgram(command); + consoleTabulator->addNewTab(command); + + setWindowTitle("QTerminal"); + setWindowIcon(QIcon::fromTheme("utilities-terminal")); + + setup_FileMenu_Actions(); + setup_ActionsMenu_Actions(); + setup_ViewMenu_Actions(); + + // Add global rename Session shortcut + renameSession = new QAction(tr("Rename Session"), this); + renameSession->setShortcut(QKeySequence(tr(RENAME_SESSION_SHORTCUT))); + connect(renameSession, SIGNAL(triggered()), consoleTabulator, SLOT(renameSession())); +} + +MainWindow::~MainWindow() +{ +} + +void MainWindow::migrate_settings() +{ + // Deal with rearrangements of settings. + // If this method becomes unbearably huge we should look at the config-update + // system used by kde and razor. + QSettings settings; + QString last_version = settings.value("version", "0.0.0").toString(); + // Handle configchanges in 0.4.0 (renaming 'Paste Selection' -> 'Paste Clipboard') + if (last_version < "0.4.0") + { + qDebug() << "Migrating settings from" << last_version << "to 0.4.0"; + settings.beginGroup("Shortcuts"); + QString tmp = settings.value("Paste Selection", PASTE_CLIPBOARD_SHORTCUT).toString(); + settings.setValue(PASTE_CLIPBOARD, tmp); + settings.remove("Paste Selection"); + settings.endGroup(); + + settings.setValue("version", "0.4.0"); + } +} + + +void MainWindow::enableDropMode() +{ + setWindowFlags(Qt::Dialog | Qt::WindowStaysOnTopHint | Qt::CustomizeWindowHint); + + m_dropLockButton = new QToolButton(this); + consoleTabulator->setCornerWidget(m_dropLockButton, Qt::BottomRightCorner); + m_dropLockButton->setCheckable(true); + m_dropLockButton->connect(m_dropLockButton, SIGNAL(clicked(bool)), this, SLOT(setKeepOpen(bool))); + setKeepOpen(Properties::Instance()->dropKeepOpen); + m_dropLockButton->setAutoRaise(true); + + + setDropShortcut(Properties::Instance()->dropShortCut); + realign(); +} + +void MainWindow::setDropShortcut(QKeySequence dropShortCut) +{ + if (!m_dropMode) + return; + + if (m_dropShortcut.shortcut() != dropShortCut) + { + m_dropShortcut.setShortcut(dropShortCut); + qWarning() << tr("Press \"%1\" to see the terminal.").arg(dropShortCut.toString()); + } +} + +void MainWindow::setup_ActionsMenu_Actions() +{ + QSettings settings; + settings.beginGroup("Shortcuts"); + + QKeySequence seq; + + Properties::Instance()->actions[CLEAR_TERMINAL] = new QAction(QIcon::fromTheme("edit-clear"), tr("Clear Current Tab"), this); + seq = QKeySequence::fromString(settings.value(CLEAR_TERMINAL, CLEAR_TERMINAL_SHORTCUT).toString()); + Properties::Instance()->actions[CLEAR_TERMINAL]->setShortcut(seq); + connect(Properties::Instance()->actions[CLEAR_TERMINAL], SIGNAL(triggered()), consoleTabulator, SLOT(clearActiveTerminal())); + menu_Actions->addAction(Properties::Instance()->actions[CLEAR_TERMINAL]); + + menu_Actions->addSeparator(); + + Properties::Instance()->actions[TAB_NEXT] = new QAction(QIcon::fromTheme("go-next"), tr("Next Tab"), this); + seq = QKeySequence::fromString( settings.value(TAB_NEXT, TAB_NEXT_SHORTCUT).toString() ); + Properties::Instance()->actions[TAB_NEXT]->setShortcut(seq); + connect(Properties::Instance()->actions[TAB_NEXT], SIGNAL(triggered()), consoleTabulator, SLOT(switchToRight())); + menu_Actions->addAction(Properties::Instance()->actions[TAB_NEXT]); + + Properties::Instance()->actions[TAB_PREV] = new QAction(QIcon::fromTheme("go-previous"), tr("Previous Tab"), this); + seq = QKeySequence::fromString( settings.value(TAB_PREV, TAB_PREV_SHORTCUT).toString() ); + Properties::Instance()->actions[TAB_PREV]->setShortcut(seq); + connect(Properties::Instance()->actions[TAB_PREV], SIGNAL(triggered()), consoleTabulator, SLOT(switchToLeft())); + menu_Actions->addAction(Properties::Instance()->actions[TAB_PREV]); + + Properties::Instance()->actions[MOVE_LEFT] = new QAction(tr("Move Tab Left"), this); + seq = QKeySequence::fromString( settings.value(MOVE_LEFT, MOVE_LEFT_SHORTCUT).toString() ); + Properties::Instance()->actions[MOVE_LEFT]->setShortcut(seq); + connect(Properties::Instance()->actions[MOVE_LEFT], SIGNAL(triggered()), consoleTabulator, SLOT(moveLeft())); + menu_Actions->addAction(Properties::Instance()->actions[MOVE_LEFT]); + + Properties::Instance()->actions[MOVE_RIGHT] = new QAction(tr("Move Tab Right"), this); + seq = QKeySequence::fromString( settings.value(MOVE_RIGHT, MOVE_RIGHT_SHORTCUT).toString() ); + Properties::Instance()->actions[MOVE_RIGHT]->setShortcut(seq); + connect(Properties::Instance()->actions[MOVE_RIGHT], SIGNAL(triggered()), consoleTabulator, SLOT(moveRight())); + menu_Actions->addAction(Properties::Instance()->actions[MOVE_RIGHT]); + + menu_Actions->addSeparator(); + + Properties::Instance()->actions[SPLIT_HORIZONTAL] = new QAction(tr("Split Terminal Horizontally"), this); + seq = QKeySequence::fromString( settings.value(SPLIT_HORIZONTAL).toString() ); + Properties::Instance()->actions[SPLIT_HORIZONTAL]->setShortcut(seq); + connect(Properties::Instance()->actions[SPLIT_HORIZONTAL], SIGNAL(triggered()), consoleTabulator, SLOT(splitHorizontally())); + menu_Actions->addAction(Properties::Instance()->actions[SPLIT_HORIZONTAL]); + + Properties::Instance()->actions[SPLIT_VERTICAL] = new QAction(tr("Split Terminal Vertically"), this); + seq = QKeySequence::fromString( settings.value(SPLIT_VERTICAL).toString() ); + Properties::Instance()->actions[SPLIT_VERTICAL]->setShortcut(seq); + connect(Properties::Instance()->actions[SPLIT_VERTICAL], SIGNAL(triggered()), consoleTabulator, SLOT(splitVertically())); + menu_Actions->addAction(Properties::Instance()->actions[SPLIT_VERTICAL]); + + Properties::Instance()->actions[SUB_COLLAPSE] = new QAction(tr("Collapse Subterminal"), this); + seq = QKeySequence::fromString( settings.value(SUB_COLLAPSE).toString() ); + Properties::Instance()->actions[SUB_COLLAPSE]->setShortcut(seq); + connect(Properties::Instance()->actions[SUB_COLLAPSE], SIGNAL(triggered()), consoleTabulator, SLOT(splitCollapse())); + menu_Actions->addAction(Properties::Instance()->actions[SUB_COLLAPSE]); + + Properties::Instance()->actions[SUB_NEXT] = new QAction(QIcon::fromTheme("go-up"), tr("Next Subterminal"), this); + seq = QKeySequence::fromString( settings.value(SUB_NEXT, SUB_NEXT_SHORTCUT).toString() ); + Properties::Instance()->actions[SUB_NEXT]->setShortcut(seq); + connect(Properties::Instance()->actions[SUB_NEXT], SIGNAL(triggered()), consoleTabulator, SLOT(switchNextSubterminal())); + menu_Actions->addAction(Properties::Instance()->actions[SUB_NEXT]); + + Properties::Instance()->actions[SUB_PREV] = new QAction(QIcon::fromTheme("go-down"), tr("Previous Subterminal"), this); + seq = QKeySequence::fromString( settings.value(SUB_PREV, SUB_PREV_SHORTCUT).toString() ); + Properties::Instance()->actions[SUB_PREV]->setShortcut(seq); + connect(Properties::Instance()->actions[SUB_PREV], SIGNAL(triggered()), consoleTabulator, SLOT(switchPrevSubterminal())); + menu_Actions->addAction(Properties::Instance()->actions[SUB_PREV]); + + menu_Actions->addSeparator(); + + // Copy and Paste are only added to the table for the sake of bindings at the moment; there is no Edit menu, only a context menu. + Properties::Instance()->actions[COPY_SELECTION] = new QAction(QIcon::fromTheme("edit-copy"), tr("Copy Selection"), this); + seq = QKeySequence::fromString( settings.value(COPY_SELECTION, COPY_SELECTION_SHORTCUT).toString() ); + Properties::Instance()->actions[COPY_SELECTION]->setShortcut(seq); + connect(Properties::Instance()->actions[COPY_SELECTION], SIGNAL(triggered()), consoleTabulator, SLOT(copySelection())); + menu_Edit->addAction(Properties::Instance()->actions[COPY_SELECTION]); + + Properties::Instance()->actions[PASTE_CLIPBOARD] = new QAction(QIcon::fromTheme("edit-paste"), tr("Paste Clipboard"), this); + seq = QKeySequence::fromString( settings.value(PASTE_CLIPBOARD, PASTE_CLIPBOARD_SHORTCUT).toString() ); + Properties::Instance()->actions[PASTE_CLIPBOARD]->setShortcut(seq); + connect(Properties::Instance()->actions[PASTE_CLIPBOARD], SIGNAL(triggered()), consoleTabulator, SLOT(pasteClipboard())); + menu_Edit->addAction(Properties::Instance()->actions[PASTE_CLIPBOARD]); + + Properties::Instance()->actions[PASTE_SELECTION] = new QAction(QIcon::fromTheme("edit-paste"), tr("Paste Selection"), this); + seq = QKeySequence::fromString( settings.value(PASTE_SELECTION, PASTE_SELECTION_SHORTCUT).toString() ); + Properties::Instance()->actions[PASTE_SELECTION]->setShortcut(seq); + connect(Properties::Instance()->actions[PASTE_SELECTION], SIGNAL(triggered()), consoleTabulator, SLOT(pasteSelection())); + menu_Edit->addAction(Properties::Instance()->actions[PASTE_SELECTION]); + + Properties::Instance()->actions[ZOOM_IN] = new QAction(QIcon::fromTheme("zoom-in"), tr("Zoom in"), this); + seq = QKeySequence::fromString( settings.value(ZOOM_IN, ZOOM_IN_SHORTCUT).toString() ); + Properties::Instance()->actions[ZOOM_IN]->setShortcut(seq); + connect(Properties::Instance()->actions[ZOOM_IN], SIGNAL(triggered()), consoleTabulator, SLOT(zoomIn())); + menu_Edit->addAction(Properties::Instance()->actions[ZOOM_IN]); + + Properties::Instance()->actions[ZOOM_OUT] = new QAction(QIcon::fromTheme("zoom-out"), tr("Zoom out"), this); + seq = QKeySequence::fromString( settings.value(ZOOM_OUT, ZOOM_OUT_SHORTCUT).toString() ); + Properties::Instance()->actions[ZOOM_OUT]->setShortcut(seq); + connect(Properties::Instance()->actions[ZOOM_OUT], SIGNAL(triggered()), consoleTabulator, SLOT(zoomOut())); + menu_Edit->addAction(Properties::Instance()->actions[ZOOM_OUT]); + + Properties::Instance()->actions[ZOOM_RESET] = new QAction(QIcon::fromTheme("zoom-original"), tr("Zoom reset"), this); + seq = QKeySequence::fromString( settings.value(ZOOM_RESET, ZOOM_RESET_SHORTCUT).toString() ); + Properties::Instance()->actions[ZOOM_RESET]->setShortcut(seq); + connect(Properties::Instance()->actions[ZOOM_RESET], SIGNAL(triggered()), consoleTabulator, SLOT(zoomReset())); + menu_Edit->addAction(Properties::Instance()->actions[ZOOM_RESET]); + + menu_Actions->addSeparator(); + + Properties::Instance()->actions[FIND] = new QAction(QIcon::fromTheme("edit-find"), tr("Find..."), this); + seq = QKeySequence::fromString( settings.value(FIND, FIND_SHORTCUT).toString() ); + Properties::Instance()->actions[FIND]->setShortcut(seq); + connect(Properties::Instance()->actions[FIND], SIGNAL(triggered()), this, SLOT(find())); + menu_Actions->addAction(Properties::Instance()->actions[FIND]); + +#if 0 + act = new QAction(this); + act->setSeparator(true); + + // TODO/FIXME: unimplemented for now + act = new QAction(tr("Save Session"), this); + // do not use sequences for this task - it collides with eg. mc shorcuts + // and mainly - it's not used too often + //act->setShortcut(QKeySequence::Save); + connect(act, SIGNAL(triggered()), consoleTabulator, SLOT(saveSession())); + + act = new QAction(tr("Load Session"), this); + // do not use sequences for this task - it collides with eg. mc shorcuts + // and mainly - it's not used too often + //act->setShortcut(QKeySequence::Open); + connect(act, SIGNAL(triggered()), consoleTabulator, SLOT(loadSession())); +#endif + + Properties::Instance()->actions[TOGGLE_MENU] = new QAction(tr("Toggle Menu"), this); + seq = QKeySequence::fromString( settings.value(TOGGLE_MENU, TOGGLE_MENU_SHORTCUT).toString() ); + Properties::Instance()->actions[TOGGLE_MENU]->setShortcut(seq); + connect(Properties::Instance()->actions[TOGGLE_MENU], SIGNAL(triggered()), this, SLOT(toggleMenu())); + // tis is correct - add action to main window - not to menu to keep toggle working + + settings.endGroup(); + + // apply props + propertiesChanged(); +} +void MainWindow::setup_FileMenu_Actions() +{ + QSettings settings; + settings.beginGroup("Shortcuts"); + + QKeySequence seq; + + Properties::Instance()->actions[ADD_TAB] = new QAction(QIcon::fromTheme("list-add"), tr("New Tab"), this); + seq = QKeySequence::fromString( settings.value(ADD_TAB, ADD_TAB_SHORTCUT).toString() ); + Properties::Instance()->actions[ADD_TAB]->setShortcut(seq); + connect(Properties::Instance()->actions[ADD_TAB], SIGNAL(triggered()), consoleTabulator, SLOT(addNewTab())); + menu_File->addAction(Properties::Instance()->actions[ADD_TAB]); + + Properties::Instance()->actions[CLOSE_TAB] = new QAction(QIcon::fromTheme("list-remove"), tr("Close Tab"), this); + seq = QKeySequence::fromString( settings.value(CLOSE_TAB, CLOSE_TAB_SHORTCUT).toString() ); + Properties::Instance()->actions[CLOSE_TAB]->setShortcut(seq); + connect(Properties::Instance()->actions[CLOSE_TAB], SIGNAL(triggered()), consoleTabulator, SLOT(removeCurrentTab())); + menu_File->addAction(Properties::Instance()->actions[CLOSE_TAB]); + + Properties::Instance()->actions[NEW_WINDOW] = new QAction(QIcon::fromTheme("window-new"), tr("New Window"), this); + seq = QKeySequence::fromString( settings.value(NEW_WINDOW, NEW_WINDOW_SHORTCUT).toString() ); + Properties::Instance()->actions[NEW_WINDOW]->setShortcut(seq); + connect(Properties::Instance()->actions[NEW_WINDOW], SIGNAL(triggered()), this, SLOT(newTerminalWindow())); + menu_File->addAction(Properties::Instance()->actions[NEW_WINDOW]); + + menu_File->addSeparator(); + + Properties::Instance()->actions[PREFERENCES] = actProperties; + connect(actProperties, SIGNAL(triggered()), SLOT(actProperties_triggered())); + menu_File->addAction(Properties::Instance()->actions[PREFERENCES]); + + menu_File->addSeparator(); + + Properties::Instance()->actions[QUIT] = actQuit; + connect(actQuit, SIGNAL(triggered()), SLOT(close())); + menu_File->addAction(Properties::Instance()->actions[QUIT]); + + settings.endGroup(); +} + +void MainWindow::setup_ViewMenu_Actions() +{ + toggleBorder = new QAction(tr("Hide Window Borders"), this); + //toggleBorder->setObjectName("toggle_Borderless"); + toggleBorder->setCheckable(true); +// TODO/FIXME: it's broken somehow. When I call toggleBorderless() here the non-responsive window appear +// toggleBorder->setChecked(Properties::Instance()->borderless); +// if (Properties::Instance()->borderless) +// toggleBorderless(); + connect(toggleBorder, SIGNAL(triggered()), this, SLOT(toggleBorderless())); + menu_Window->addAction(toggleBorder); + toggleBorder->setVisible(!m_dropMode); + + toggleTabbar = new QAction(tr("Show Tab Bar"), this); + //toggleTabbar->setObjectName("toggle_TabBar"); + toggleTabbar->setCheckable(true); + toggleTabbar->setChecked(!Properties::Instance()->tabBarless); + toggleTabBar(); + connect(toggleTabbar, SIGNAL(triggered()), this, SLOT(toggleTabBar())); + menu_Window->addAction(toggleTabbar); + + QSettings settings; + settings.beginGroup("Shortcuts"); + Properties::Instance()->actions[TOGGLE_BOOKMARKS] = m_bookmarksDock->toggleViewAction(); + QKeySequence seq = QKeySequence::fromString( settings.value(TOGGLE_BOOKMARKS, TOGGLE_BOOKMARKS_SHORTCUT).toString() ); + Properties::Instance()->actions[TOGGLE_BOOKMARKS]->setShortcut(seq); + menu_Window->addAction(Properties::Instance()->actions[TOGGLE_BOOKMARKS]); + settings.endGroup(); + + menu_Window->addSeparator(); + + /* tabs position */ + tabPosition = new QActionGroup(this); + QAction *tabBottom = new QAction(tr("Bottom"), this); + QAction *tabTop = new QAction(tr("Top"), this); + QAction *tabRight = new QAction(tr("Right"), this); + QAction *tabLeft = new QAction(tr("Left"), this); + tabPosition->addAction(tabTop); + tabPosition->addAction(tabBottom); + tabPosition->addAction(tabLeft); + tabPosition->addAction(tabRight); + + for(int i = 0; i < tabPosition->actions().size(); ++i) + tabPosition->actions().at(i)->setCheckable(true); + + if( tabPosition->actions().count() > Properties::Instance()->tabsPos ) + tabPosition->actions().at(Properties::Instance()->tabsPos)->setChecked(true); + + connect(tabPosition, SIGNAL(triggered(QAction *)), + consoleTabulator, SLOT(changeTabPosition(QAction *)) ); + + tabPosMenu = new QMenu(tr("Tabs Layout"), menu_Window); + tabPosMenu->setObjectName("tabPosMenu"); + + for(int i=0; i < tabPosition->actions().size(); ++i) { + tabPosMenu->addAction(tabPosition->actions().at(i)); + } + + connect(menu_Window, SIGNAL(hovered(QAction *)), + this, SLOT(updateActionGroup(QAction *))); + menu_Window->addMenu(tabPosMenu); + /* */ + + /* Scrollbar */ + scrollBarPosition = new QActionGroup(this); + QAction *scrollNone = new QAction(tr("None"), this); + QAction *scrollRight = new QAction(tr("Right"), this); + QAction *scrollLeft = new QAction(tr("Left"), this); + + /* order of insertion is dep. on QTermWidget::ScrollBarPosition enum */ + scrollBarPosition->addAction(scrollNone); + scrollBarPosition->addAction(scrollLeft); + scrollBarPosition->addAction(scrollRight); + + for(int i = 0; i < scrollBarPosition->actions().size(); ++i) + scrollBarPosition->actions().at(i)->setCheckable(true); + + if( Properties::Instance()->scrollBarPos < scrollBarPosition->actions().size() ) + scrollBarPosition->actions().at(Properties::Instance()->scrollBarPos)->setChecked(true); + + connect(scrollBarPosition, SIGNAL(triggered(QAction *)), + consoleTabulator, SLOT(changeScrollPosition(QAction *)) ); + + scrollPosMenu = new QMenu(tr("Scrollbar Layout"), menu_Window); + scrollPosMenu->setObjectName("scrollPosMenu"); + + for(int i=0; i < scrollBarPosition->actions().size(); ++i) { + scrollPosMenu->addAction(scrollBarPosition->actions().at(i)); + } + + menu_Window->addMenu(scrollPosMenu); +} + +void MainWindow::on_consoleTabulator_currentChanged(int) +{ +} + +void MainWindow::toggleTabBar() +{ + Properties::Instance()->tabBarless = !toggleTabbar->isChecked(); + consoleTabulator->showHideTabBar(); +} + +void MainWindow::toggleBorderless() +{ + setWindowFlags(windowFlags() ^ Qt::FramelessWindowHint); + show(); + setWindowState(Qt::WindowActive); /* don't loose focus on the window */ + Properties::Instance()->borderless = toggleBorder->isChecked(); + realign(); +} + +void MainWindow::toggleMenu() +{ + m_menuBar->setVisible(!m_menuBar->isVisible()); + Properties::Instance()->menuVisible = m_menuBar->isVisible(); +} + +void MainWindow::closeEvent(QCloseEvent *ev) +{ + if (!Properties::Instance()->askOnExit + || !consoleTabulator->count()) + { + // #80 - do not save state and geometry in drop mode + if (!m_dropMode) + { + Properties::Instance()->mainWindowGeometry = saveGeometry(); + Properties::Instance()->mainWindowState = saveState(); + } + Properties::Instance()->saveSettings(); + ev->accept(); + return; + } + + // ask user for cancel only when there is at least one terminal active in this window + QDialog * dia = new QDialog(this); + dia->setObjectName("exitDialog"); + dia->setWindowTitle(tr("Exit QTerminal")); + + QCheckBox * dontAskCheck = new QCheckBox(tr("Do not ask again"), dia); + QDialogButtonBox * buttonBox = new QDialogButtonBox(QDialogButtonBox::Yes | QDialogButtonBox::No, Qt::Horizontal, dia); + + connect(buttonBox, SIGNAL(accepted()), dia, SLOT(accept())); + connect(buttonBox, SIGNAL(rejected()), dia, SLOT(reject())); + + QVBoxLayout * lay = new QVBoxLayout(); + lay->addWidget(new QLabel(tr("Are you sure you want to exit?"))); + lay->addWidget(dontAskCheck); + lay->addWidget(buttonBox); + dia->setLayout(lay); + + if (dia->exec() == QDialog::Accepted) { + Properties::Instance()->mainWindowGeometry = saveGeometry(); + Properties::Instance()->mainWindowState = saveState(); + Properties::Instance()->askOnExit = !dontAskCheck->isChecked(); + Properties::Instance()->saveSettings(); + ev->accept(); + } else { + ev->ignore(); + } + + dia->deleteLater(); +} + +void MainWindow::actAbout_triggered() +{ + QMessageBox::about(this, QString("QTerminal ") + STR_VERSION, tr("A lightweight multiplatform terminal emulator")); +} + +void MainWindow::actProperties_triggered() +{ + PropertiesDialog *p = new PropertiesDialog(this); + connect(p, SIGNAL(propertiesChanged()), this, SLOT(propertiesChanged())); + p->exec(); +} + +void MainWindow::propertiesChanged() +{ + QApplication::setStyle(Properties::Instance()->guiStyle); + setWindowOpacity(Properties::Instance()->appOpacity/100.0); + consoleTabulator->setTabPosition((QTabWidget::TabPosition)Properties::Instance()->tabsPos); + consoleTabulator->propertiesChanged(); + setDropShortcut(Properties::Instance()->dropShortCut); + + m_menuBar->setVisible(Properties::Instance()->menuVisible); + + m_bookmarksDock->setVisible(Properties::Instance()->useBookmarks + && Properties::Instance()->bookmarksVisible); + m_bookmarksDock->toggleViewAction()->setVisible(Properties::Instance()->useBookmarks); + + if (Properties::Instance()->useBookmarks) + { + qobject_cast(m_bookmarksDock->widget())->setup(); + } + + Properties::Instance()->saveSettings(); + realign(); +} + +void MainWindow::realign() +{ + if (m_dropMode) + { + QRect desktop = QApplication::desktop()->availableGeometry(this); + QRect geometry = QRect(0, 0, + desktop.width() * Properties::Instance()->dropWidht / 100, + desktop.height() * Properties::Instance()->dropHeight / 100 + ); + geometry.moveCenter(desktop.center()); + // do not use 0 here - we need to calculate with potential panel on top + geometry.setTop(desktop.top()); + + setGeometry(geometry); + } +} + +void MainWindow::updateActionGroup(QAction *a) +{ + if (a->parent()->objectName() == tabPosMenu->objectName()) { + tabPosition->actions().at(Properties::Instance()->tabsPos)->setChecked(true); + } +} + +void MainWindow::showHide() +{ + if (isVisible()) + hide(); + else + { + realign(); + show(); + activateWindow(); + } +} + +void MainWindow::setKeepOpen(bool value) +{ + Properties::Instance()->dropKeepOpen = value; + if (!m_dropLockButton) + return; + + if (value) + m_dropLockButton->setIcon(QIcon::fromTheme("object-locked")); + else + m_dropLockButton->setIcon(QIcon::fromTheme("object-unlocked")); + + m_dropLockButton->setChecked(value); +} + +void MainWindow::find() +{ + // A bit ugly perhaps with 4 levels of indirection... + consoleTabulator->terminalHolder()->currentTerminal()->impl()->toggleShowSearchBar(); +} + + +bool MainWindow::event(QEvent *event) +{ + if (event->type() == QEvent::WindowDeactivate) + { + if (m_dropMode && + !Properties::Instance()->dropKeepOpen && + qApp->activeWindow() == 0 + ) + hide(); + } + return QMainWindow::event(event); +} + +void MainWindow::newTerminalWindow() +{ + MainWindow *w = new MainWindow(m_initWorkDir, m_initShell, false); + w->show(); +} + +void MainWindow::bookmarksWidget_callCommand(const QString& cmd) +{ + consoleTabulator->terminalHolder()->currentTerminal()->impl()->sendText(cmd); + consoleTabulator->terminalHolder()->currentTerminal()->setFocus(); +} + +void MainWindow::bookmarksDock_visibilityChanged(bool visible) +{ + Properties::Instance()->bookmarksVisible = visible; +} diff --git a/src/mainwindow.h b/src/mainwindow.h new file mode 100644 index 0000000..070158a --- /dev/null +++ b/src/mainwindow.h @@ -0,0 +1,91 @@ +/*************************************************************************** + * Copyright (C) 2006 by Vladimir Kuznetsov * + * vovanec@gmail.com * + * * + * 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 MAINWINDOW_H +#define MAINWINDOW_H + +#include "ui_qterminal.h" + +#include +#include "qxtglobalshortcut.h" + +class QToolButton; + +class MainWindow : public QMainWindow , private Ui::mainWindow +{ + Q_OBJECT + +public: + MainWindow(const QString& work_dir, const QString& command, + bool dropMode, + QWidget * parent = 0, Qt::WindowFlags f = 0); + ~MainWindow(); + + bool dropMode() { return m_dropMode; } + +protected slots: + void on_consoleTabulator_currentChanged(int); + void propertiesChanged(); + void actAbout_triggered(); + void actProperties_triggered(); + void updateActionGroup(QAction *); + + void toggleBorderless(); + void toggleTabBar(); + void toggleMenu(); + + void showHide(); + void setKeepOpen(bool value); + void find(); + + void newTerminalWindow(); + void bookmarksWidget_callCommand(const QString&); + void bookmarksDock_visibilityChanged(bool visible); + +protected: + bool event(QEvent* event); + +private: + QActionGroup *tabPosition, *scrollBarPosition; + QMenu *tabPosMenu, *scrollPosMenu; + + QAction *toggleBorder, *toggleTabbar, *renameSession; + + QString m_initWorkDir; + QString m_initShell; + + QDockWidget *m_bookmarksDock; + + void migrate_settings(); + + void setup_FileMenu_Actions(); + void setup_ActionsMenu_Actions(); + void setup_ViewMenu_Actions(); + + void closeEvent(QCloseEvent*); + + void enableDropMode(); + QToolButton *m_dropLockButton; + bool m_dropMode; + QxtGlobalShortcut m_dropShortcut; + void realign(); + void setDropShortcut(QKeySequence dropShortCut); +}; +#endif //MAINWINDOW_H diff --git a/src/properties.cpp b/src/properties.cpp new file mode 100644 index 0000000..cbf7964 --- /dev/null +++ b/src/properties.cpp @@ -0,0 +1,186 @@ +#include + +#include "properties.h" +#include "config.h" + + +Properties * Properties::m_instance = 0; + + +Properties * Properties::Instance(const QString& filename) +{ + if (!m_instance) + m_instance = new Properties(filename); + return m_instance; +} + +Properties::Properties(const QString& filename) : filename(filename) +{ + if (filename.isEmpty()) { + QSettings settings; + this->filename = settings.fileName(); + } + qDebug("Properties constructor called"); +} + +Properties::~Properties() +{ + qDebug("Properties destructor called"); + saveSettings(); + delete m_instance; + m_instance = 0; +} + +QFont Properties::defaultFont() +{ + QFont default_font = QApplication::font(); + default_font.setFamily(DEFAULT_FONT); + default_font.setPointSize(12); + default_font.setStyleHint(QFont::TypeWriter); + return default_font; +} + +void Properties::loadSettings() +{ + QSettings settings(filename, QSettings::IniFormat); + + guiStyle = settings.value("guiStyle", QString()).toString(); + if (!guiStyle.isNull()) + QApplication::setStyle(guiStyle); + + colorScheme = settings.value("colorScheme", "Linux").toString(); + + highlightCurrentTerminal = settings.value("highlightCurrentTerminal", true).toBool(); + + font = qvariant_cast(settings.value("font", defaultFont())); + + settings.beginGroup("Shortcuts"); + QStringList keys = settings.childKeys(); + foreach( QString key, keys ) + { + QKeySequence sequence = QKeySequence( settings.value( key ).toString() ); + if( Properties::Instance()->actions.contains( key ) ) + Properties::Instance()->actions[ key ]->setShortcut( sequence ); + } + settings.endGroup(); + + mainWindowGeometry = settings.value("MainWindow/geometry").toByteArray(); + mainWindowState = settings.value("MainWindow/state").toByteArray(); + + + historyLimited = settings.value("HistoryLimited", true).toBool(); + historyLimitedTo = settings.value("HistoryLimitedTo", 1000).toUInt(); + + emulation = settings.value("emulation", "default").toString(); + + // sessions + int size = settings.beginReadArray("Sessions"); + for (int i = 0; i < size; ++i) + { + settings.setArrayIndex(i); + QString name(settings.value("name").toString()); + if (name.isEmpty()) + continue; + sessions[name] = settings.value("state").toByteArray(); + } + settings.endArray(); + + appOpacity = settings.value("MainWindow/appOpacity", 100).toInt(); + termOpacity = settings.value("termOpacity", 100).toInt(); + + /* default to Right. see qtermwidget.h */ + scrollBarPos = settings.value("ScrollbarPosition", 2).toInt(); + /* default to North. I'd prefer South but North is standard (they say) */ + tabsPos = settings.value("TabsPosition", 0).toInt(); + alwaysShowTabs = settings.value("AlwaysShowTabs", true).toBool(); + m_motionAfterPaste = settings.value("MotionAfterPaste", 0).toInt(); + + /* toggles */ + borderless = settings.value("Borderless", false).toBool(); + tabBarless = settings.value("TabBarless", false).toBool(); + menuVisible = settings.value("MenuVisible", true).toBool(); + askOnExit = settings.value("AskOnExit", true).toBool(); + useCWD = settings.value("UseCWD", false).toBool(); + + // bookmarks + useBookmarks = settings.value("UseBookmarks", false).toBool(); + bookmarksVisible = settings.value("BookmarksVisible", true).toBool(); + bookmarksFile = settings.value("BookmarksFile", QFileInfo(settings.fileName()).canonicalPath()+"/qterminal_bookmarks.xml").toString(); + + settings.beginGroup("DropMode"); + dropShortCut = QKeySequence(settings.value("ShortCut", "F12").toString()); + dropKeepOpen = settings.value("KeepOpen", false).toBool(); + dropShowOnStart = settings.value("ShowOnStart", true).toBool(); + dropWidht = settings.value("Width", 70).toInt(); + dropHeight = settings.value("Height", 45).toInt(); + settings.endGroup(); +} + +void Properties::saveSettings() +{ + QSettings settings(filename, QSettings::IniFormat); + + settings.setValue("guiStyle", guiStyle); + settings.setValue("colorScheme", colorScheme); + settings.setValue("highlightCurrentTerminal", highlightCurrentTerminal); + settings.setValue("font", font); + + settings.beginGroup("Shortcuts"); + QMapIterator< QString, QAction * > it(actions); + while( it.hasNext() ) + { + it.next(); + QKeySequence shortcut = it.value()->shortcut(); + settings.setValue( it.key(), shortcut.toString() ); + } + settings.endGroup(); + + settings.setValue("MainWindow/geometry", mainWindowGeometry); + settings.setValue("MainWindow/state", mainWindowState); + + settings.setValue("HistoryLimited", historyLimited); + settings.setValue("HistoryLimitedTo", historyLimitedTo); + + settings.setValue("emulation", emulation); + + // sessions + settings.beginWriteArray("Sessions"); + int i = 0; + Sessions::iterator sit = sessions.begin(); + while (sit != sessions.end()) + { + settings.setArrayIndex(i); + settings.setValue("name", sit.key()); + settings.setValue("state", sit.value()); + ++sit; + ++i; + } + settings.endArray(); + + settings.setValue("MainWindow/appOpacity", appOpacity); + settings.setValue("termOpacity", termOpacity); + settings.setValue("ScrollbarPosition", scrollBarPos); + settings.setValue("TabsPosition", tabsPos); + settings.setValue("AlwaysShowTabs", alwaysShowTabs); + settings.setValue("MotionAfterPaste", m_motionAfterPaste); + settings.setValue("Borderless", borderless); + settings.setValue("TabBarless", tabBarless); + settings.setValue("MenuVisible", menuVisible); + settings.setValue("AskOnExit", askOnExit); + settings.setValue("UseCWD", useCWD); + + // bookmarks + settings.setValue("UseBookmarks", useBookmarks); + settings.setValue("BookmarksVisible", bookmarksVisible); + settings.setValue("BookmarksFile", bookmarksFile); + + settings.beginGroup("DropMode"); + settings.setValue("ShortCut", dropShortCut.toString()); + settings.setValue("KeepOpen", dropKeepOpen); + settings.setValue("ShowOnStart", dropShowOnStart); + settings.setValue("Width", dropWidht); + settings.setValue("Height", dropHeight); + settings.endGroup(); + +} + diff --git a/src/properties.h b/src/properties.h new file mode 100644 index 0000000..dcde366 --- /dev/null +++ b/src/properties.h @@ -0,0 +1,84 @@ +#ifndef PROPERTIES_H +#define PROPERTIES_H + +#include +#include +#include +#include + +typedef QString Session; + +typedef QMap Sessions; + +typedef QMap ShortcutMap; + + +class Properties +{ + public: + static Properties *Instance(const QString& filename = QString("")); + + QFont defaultFont(); + void saveSettings(); + + QByteArray mainWindowGeometry; + QByteArray mainWindowState; + //ShortcutMap shortcuts; + QString shell; + QFont font; + QString colorScheme; + QString guiStyle; + bool highlightCurrentTerminal; + + bool historyLimited; + unsigned historyLimitedTo; + + QString emulation; + + Sessions sessions; + + int appOpacity; + int termOpacity; + + int scrollBarPos; + int tabsPos; + bool alwaysShowTabs; + int m_motionAfterPaste; + + bool borderless; + bool tabBarless; + bool menuVisible; + + bool askOnExit; + + bool useCWD; + + bool useBookmarks; + bool bookmarksVisible; + QString bookmarksFile; + + QKeySequence dropShortCut; + bool dropKeepOpen; + bool dropShowOnStart; + int dropWidht; + int dropHeight; + + QMap< QString, QAction * > actions; + + void loadSettings(); + + + private: + + // Singleton handling + static Properties *m_instance; + QString filename; + + explicit Properties(const QString& filename); + Properties(const Properties &) {}; + ~Properties(); + +}; + +#endif + diff --git a/src/propertiesdialog.cpp b/src/propertiesdialog.cpp new file mode 100644 index 0000000..16d66f6 --- /dev/null +++ b/src/propertiesdialog.cpp @@ -0,0 +1,331 @@ +#include + +#include +#include +#include + +#include "propertiesdialog.h" +#include "properties.h" +#include "fontdialog.h" +#include "config.h" + + +PropertiesDialog::PropertiesDialog(QWidget *parent) + : QDialog(parent) +{ + setupUi(this); + + connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), + this, SLOT(apply())); + connect(changeFontButton, SIGNAL(clicked()), + this, SLOT(changeFontButton_clicked())); + + QStringList emulations = QTermWidget::availableKeyBindings(); + QStringList colorSchemes = QTermWidget::availableColorSchemes(); + + listWidget->setCurrentRow(0); + + colorSchemaCombo->addItems(colorSchemes); + int csix = colorSchemaCombo->findText(Properties::Instance()->colorScheme); + if (csix != -1) + colorSchemaCombo->setCurrentIndex(csix); + + emulationComboBox->addItems(emulations); + int eix = emulationComboBox->findText(Properties::Instance()->emulation); + emulationComboBox->setCurrentIndex(eix != -1 ? eix : 0 ); + + /* shortcuts */ + setupShortcuts(); + + /* scrollbar position */ + QStringList scrollBarPosList; + scrollBarPosList << "No scrollbar" << "Left" << "Right"; + scrollBarPos_comboBox->addItems(scrollBarPosList); + scrollBarPos_comboBox->setCurrentIndex(Properties::Instance()->scrollBarPos); + + /* tabs position */ + QStringList tabsPosList; + tabsPosList << "Top" << "Bottom" << "Left" << "Right"; + tabsPos_comboBox->addItems(tabsPosList); + tabsPos_comboBox->setCurrentIndex(Properties::Instance()->tabsPos); + + alwaysShowTabsCheckBox->setChecked(Properties::Instance()->alwaysShowTabs); + + // show main menu bar + showMenuCheckBox->setChecked(Properties::Instance()->menuVisible); + + /* actions by motion after paste */ + + QStringList motionAfter; + motionAfter << "No move" << "Move start" << "Move end"; + motionAfterPasting_comboBox->addItems(motionAfter); + motionAfterPasting_comboBox->setCurrentIndex(Properties::Instance()->m_motionAfterPaste); + + // Setting windows style actions + styleComboBox->addItem(tr("System Default")); + styleComboBox->addItems(QStyleFactory::keys()); + + int ix = styleComboBox->findText(Properties::Instance()->guiStyle); + if (ix != -1) + styleComboBox->setCurrentIndex(ix); + + setFontSample(Properties::Instance()->font); + + appOpacityBox->setValue(Properties::Instance()->appOpacity); + //connect(appOpacityBox, SIGNAL(valueChanged(int)), this, SLOT(apply())); + + termOpacityBox->setValue(Properties::Instance()->termOpacity); + //connect(termOpacityBox, SIGNAL(valueChanged(int)), this, SLOT(apply())); + + highlightCurrentCheckBox->setChecked(Properties::Instance()->highlightCurrentTerminal); + + askOnExitCheckBox->setChecked(Properties::Instance()->askOnExit); + + useCwdCheckBox->setChecked(Properties::Instance()->useCWD); + + historyLimited->setChecked(Properties::Instance()->historyLimited); + historyUnlimited->setChecked(!Properties::Instance()->historyLimited); + historyLimitedTo->setValue(Properties::Instance()->historyLimitedTo); + + dropShowOnStartCheckBox->setChecked(Properties::Instance()->dropShowOnStart); + dropHeightSpinBox->setValue(Properties::Instance()->dropHeight); + dropWidthSpinBox->setValue(Properties::Instance()->dropWidht); + dropShortCutEdit->setText(Properties::Instance()->dropShortCut.toString()); + + useBookmarksCheckBox->setChecked(Properties::Instance()->useBookmarks); + bookmarksLineEdit->setText(Properties::Instance()->bookmarksFile); + openBookmarksFile(Properties::Instance()->bookmarksFile); + connect(bookmarksButton, SIGNAL(clicked()), + this, SLOT(bookmarksButton_clicked())); +} + + +PropertiesDialog::~PropertiesDialog() +{ +} + +void PropertiesDialog::accept() +{ + apply(); + QDialog::accept(); +} + +void PropertiesDialog::apply() +{ + Properties::Instance()->colorScheme = colorSchemaCombo->currentText(); + Properties::Instance()->font = fontSampleLabel->font();//fontComboBox->currentFont(); + Properties::Instance()->guiStyle = (styleComboBox->currentText() == tr("System Default")) ? + QString() : styleComboBox->currentText(); + + Properties::Instance()->emulation = emulationComboBox->currentText(); + + /* do not allow to go above 99 or we lose transparency option */ + (appOpacityBox->value() >= 100) ? + Properties::Instance()->appOpacity = 99 + : + Properties::Instance()->appOpacity = appOpacityBox->value(); + + Properties::Instance()->termOpacity = termOpacityBox->value(); + Properties::Instance()->highlightCurrentTerminal = highlightCurrentCheckBox->isChecked(); + + Properties::Instance()->askOnExit = askOnExitCheckBox->isChecked(); + + Properties::Instance()->useCWD = useCwdCheckBox->isChecked(); + + Properties::Instance()->scrollBarPos = scrollBarPos_comboBox->currentIndex(); + Properties::Instance()->tabsPos = tabsPos_comboBox->currentIndex(); + Properties::Instance()->alwaysShowTabs = alwaysShowTabsCheckBox->isChecked(); + Properties::Instance()->menuVisible = showMenuCheckBox->isChecked(); + Properties::Instance()->m_motionAfterPaste = motionAfterPasting_comboBox->currentIndex(); + + Properties::Instance()->historyLimited = historyLimited->isChecked(); + Properties::Instance()->historyLimitedTo = historyLimitedTo->value(); + + saveShortcuts(); + + Properties::Instance()->saveSettings(); + + Properties::Instance()->dropShowOnStart = dropShowOnStartCheckBox->isChecked(); + Properties::Instance()->dropHeight = dropHeightSpinBox->value(); + Properties::Instance()->dropWidht = dropWidthSpinBox->value(); + Properties::Instance()->dropShortCut = QKeySequence(dropShortCutEdit->text()); + + Properties::Instance()->useBookmarks = useBookmarksCheckBox->isChecked(); + Properties::Instance()->bookmarksFile = bookmarksLineEdit->text(); + saveBookmarksFile(Properties::Instance()->bookmarksFile); + + emit propertiesChanged(); +} + +void PropertiesDialog::setFontSample(const QFont & f) +{ + fontSampleLabel->setFont(f); + QString sample("%1 %2 pt"); + fontSampleLabel->setText(sample.arg(f.family()).arg(f.pointSize())); +} + +void PropertiesDialog::changeFontButton_clicked() +{ + FontDialog dia(fontSampleLabel->font()); + if (!dia.exec()) + return; + QFont f = dia.getFont(); + if (QFontInfo(f).fixedPitch()) + setFontSample(f); +} + +void PropertiesDialog::saveShortcuts() +{ + QList< QString > shortcutKeys = Properties::Instance()->actions.keys(); + int shortcutCount = shortcutKeys.count(); + + shortcutsWidget->setRowCount( shortcutCount ); + + for( int x=0; x < shortcutCount; x++ ) + { + QString keyValue = shortcutKeys.at(x); + QAction *keyAction = Properties::Instance()->actions[keyValue]; + + QTableWidgetItem *item = shortcutsWidget->item(x, 1); + QKeySequence sequence = QKeySequence(item->text()); + QString sequenceString = sequence.toString(); + + keyAction->setShortcut(sequenceString); + } +} + +void PropertiesDialog::setupShortcuts() +{ + QList< QString > shortcutKeys = Properties::Instance()->actions.keys(); + int shortcutCount = shortcutKeys.count(); + + shortcutsWidget->setRowCount( shortcutCount ); + + for( int x=0; x < shortcutCount; x++ ) + { + QString keyValue = shortcutKeys.at(x); + QAction *keyAction = Properties::Instance()->actions[keyValue]; + + QTableWidgetItem *itemName = new QTableWidgetItem( tr(keyValue.toStdString().c_str()) ); + QTableWidgetItem *itemShortcut = new QTableWidgetItem( keyAction->shortcut().toString() ); + + itemName->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled ); + + shortcutsWidget->setItem(x, 0, itemName); + shortcutsWidget->setItem(x, 1, itemShortcut); + } + + shortcutsWidget->resizeColumnsToContents(); +/* + connect(shortcutsWidget, SIGNAL(currentChanged(int, int)), + this, SLOT(recordAction(int, int))); + connect(shortcutsWidget, SIGNAL(valueChanged(int, int)), + this, SLOT(validateAction(int, int))); +*/ +} + +void PropertiesDialog::recordAction(int row, int column) +{ + oldAccelText = shortcutsWidget->item(row, column)->text(); +} + +void PropertiesDialog::validateAction(int row, int column) +{ + QTableWidgetItem *item = shortcutsWidget->item(row, column); + QString accelText = QKeySequence(item->text()).toString(); + + if (accelText.isEmpty() && !item->text().isEmpty()) + item->setText(oldAccelText); + else + item->setText(accelText); +} + +void PropertiesDialog::bookmarksButton_clicked() +{ + QFileDialog dia(this, tr("Open or create bookmarks file")); + dia.setConfirmOverwrite(false); + dia.setFileMode(QFileDialog::AnyFile); + if (!dia.exec()) + return; + + QString fname = dia.selectedFiles().count() ? dia.selectedFiles().at(0) : QString(); + if (fname.isNull()) + return; + + bookmarksLineEdit->setText(fname); + openBookmarksFile(bookmarksLineEdit->text()); +} + +void PropertiesDialog::openBookmarksFile(const QString &fname) +{ + QFile f(fname); + QString content; + if (!f.open(QFile::ReadOnly)) + content = "\n \n \n \n"; + else + content = f.readAll(); + + bookmarkPlainEdit->setPlainText(content); + bookmarkPlainEdit->document()->setModified(false); +} + +void PropertiesDialog::saveBookmarksFile(const QString &fname) +{ + if (!bookmarkPlainEdit->document()->isModified()) + return; + + QFile f(fname); + if (!f.open(QFile::WriteOnly|QFile::Truncate)) + qDebug() << "Cannot write to file" << f.fileName(); + else + f.write(bookmarkPlainEdit->toPlainText().toUtf8()); +} + +/* +void PropertiesDialog::setupShortcuts() +{ + QList< QString > shortcutKeys = Properties::Instance()->shortcuts.keys(); + int shortcutCount = shortcutKeys.count(); + + shortcutsWidget->setRowCount( shortcutCount ); + + for( int x=0; x < shortcutCount; x++ ) + { + QString keyValue = shortcutKeys.at(x); + + QLabel *lblShortcut = new QLabel( keyValue, this ); + QPushButton *btnLaunch = new QPushButton( Properties::Instance()->shortcuts.value( keyValue ), this ); + + btnLaunch->setObjectName(keyValue); + connect( btnLaunch, SIGNAL(clicked()), this, SLOT(shortcutPrompt()) ); + + shortcutsWidget->setCellWidget( x, 0, lblShortcut ); + shortcutsWidget->setCellWidget( x, 1, btnLaunch ); + } +} + +void PropertiesDialog::shortcutPrompt() +{ + QObject *objectSender = sender(); + + if( !objectSender ) + return; + + QString name = objectSender->objectName(); + qDebug() << "shortcutPrompt(" << name << ")"; + + DialogShortcut *dlgShortcut = new DialogShortcut(this); + dlgShortcut->setTitle( tr("Select a key sequence for %1").arg(name) ); + + QString sequenceString = Properties::Instance()->shortcuts[name]; + dlgShortcut->setKey(sequenceString); + + int result = dlgShortcut->exec(); + if( result == QDialog::Accepted ) + { + sequenceString = dlgShortcut->getKey(); + Properties::Instance()->shortcuts[name] = sequenceString; + Properties::Instance()->saveSettings(); + } +} +*/ diff --git a/src/propertiesdialog.h b/src/propertiesdialog.h new file mode 100644 index 0000000..2ea43c0 --- /dev/null +++ b/src/propertiesdialog.h @@ -0,0 +1,40 @@ +#ifndef PROPERTIESDIALOG_H +#define PROPERTIESDIALOG_H + +#include "ui_propertiesdialog.h" + +class PropertiesDialog : public QDialog, Ui::PropertiesDialog +{ + Q_OBJECT + + QString oldAccelText; // Placeholder when editing shortcut + + public: + PropertiesDialog(QWidget *parent=NULL); + ~PropertiesDialog(); + + signals: + void propertiesChanged(); + + private: + void setFontSample(const QFont & f); + void openBookmarksFile(const QString &fname); + void saveBookmarksFile(const QString &fname); + + private slots: + void apply(); + void accept(); + + void changeFontButton_clicked(); + void bookmarksButton_clicked(); + + protected: + void setupShortcuts(); + void saveShortcuts(); + void recordAction(int row, int column); + void validateAction(int row, int column); +}; + + +#endif + diff --git a/src/tabwidget.cpp b/src/tabwidget.cpp new file mode 100644 index 0000000..1a3197c --- /dev/null +++ b/src/tabwidget.cpp @@ -0,0 +1,386 @@ +/*************************************************************************** + * Copyright (C) 2006 by Vladimir Kuznetsov * + * vovanec@gmail.com * + * * + * 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 +#include +#include +#include + +#include "termwidgetholder.h" +#include "tabwidget.h" +#include "config.h" +#include "properties.h" + + +#define TAB_INDEX_PROPERTY "tab_index" + + +TabWidget::TabWidget(QWidget* parent) : QTabWidget(parent), tabNumerator(0) +{ + setFocusPolicy(Qt::NoFocus); + + /* On Mac OS X this will look similar to + * the tabs in Safari or Leopard's Terminal.app . + * I love this! + */ + setDocumentMode(true); + + tabBar()->setUsesScrollButtons(true); + + setTabsClosable(true); + setMovable(true); + setUsesScrollButtons(true); + + tabBar()->installEventFilter(this); + + connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(removeTab(int))); +} + +TermWidgetHolder * TabWidget::terminalHolder() +{ + return reinterpret_cast(widget(currentIndex())); +} + +void TabWidget::setWorkDirectory(const QString& dir) +{ + this->work_dir = dir; +} + +int TabWidget::addNewTab(const QString & shell_program) +{ + tabNumerator++; + QString label = QString(tr("Shell No. %1")).arg(tabNumerator); + + TermWidgetHolder *ch = terminalHolder(); + QString cwd(work_dir); + if (Properties::Instance()->useCWD && ch) + { + cwd = ch->currentTerminal()->impl()->workingDirectory(); + if (cwd.isEmpty()) + cwd = work_dir; + } + + TermWidgetHolder *console = new TermWidgetHolder(cwd, shell_program, this); + connect(console, SIGNAL(finished()), SLOT(removeFinished())); + //connect(console, SIGNAL(lastTerminalClosed()), this, SLOT(removeCurrentTab())); + connect(console, SIGNAL(lastTerminalClosed()), this, SLOT(removeFinished())); + connect(console, SIGNAL(renameSession()), this, SLOT(renameSession())); + + int index = addTab(console, label); + recountIndexes(); + setCurrentIndex(index); + console->setInitialFocus(); + + showHideTabBar(); + + return index; +} + +void TabWidget::switchNextSubterminal() +{ + terminalHolder()->switchNextSubterminal(); +} + +void TabWidget::switchPrevSubterminal() +{ + terminalHolder()->switchPrevSubterminal(); +} + +void TabWidget::splitHorizontally() +{ + terminalHolder()->splitHorizontal(terminalHolder()->currentTerminal()); +} + +void TabWidget::splitVertically() +{ + terminalHolder()->splitVertical(terminalHolder()->currentTerminal()); +} + +void TabWidget::splitCollapse() +{ + terminalHolder()->splitCollapse(terminalHolder()->currentTerminal()); +} + +void TabWidget::copySelection() +{ + terminalHolder()->currentTerminal()->impl()->copyClipboard(); +} + +void TabWidget::pasteClipboard() +{ + terminalHolder()->currentTerminal()->impl()->pasteClipboard(); +} + +void TabWidget::pasteSelection() +{ + terminalHolder()->currentTerminal()->impl()->pasteSelection(); +} + +void TabWidget::zoomIn() +{ + terminalHolder()->currentTerminal()->impl()->zoomIn(); +} + +void TabWidget::zoomOut() +{ + terminalHolder()->currentTerminal()->impl()->zoomOut(); +} + +void TabWidget::zoomReset() +{ + terminalHolder()->currentTerminal()->impl()->zoomReset(); +} + +void TabWidget::recountIndexes() +{ + for(int i = 0; i < count(); i++) + widget(i)->setProperty(TAB_INDEX_PROPERTY, i); +} + +void TabWidget::renameSession() +{ + bool ok = false; + QString text = QInputDialog::getText(this, tr("Tab name"), + tr("New tab name:"), QLineEdit::Normal, + QString(), &ok); + if(ok && !text.isEmpty()) + { + setTabText(currentIndex(), text); + } +} + +void TabWidget::renameTabsAfterRemove() +{ +// it breaks custom names - it replaces original/custom title with shell no # +#if 0 + for(int i = 0; i < count(); i++) { + setTabText(i, QString(tr("Shell No. %1")).arg(i+1)); + } +#endif +} + +void TabWidget::contextMenuEvent ( QContextMenuEvent * event ) +{ + QMenu menu(this); + + menu.addAction(QIcon::fromTheme("document-close"), tr("Close session"), + this, SLOT(removeCurrentTab())); + menu.addAction(tr("Rename session"), this, SLOT(renameSession()), tr(RENAME_SESSION_SHORTCUT)); + + menu.exec(event->globalPos()); +} + +bool TabWidget::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::MouseButtonDblClick) + { + QMouseEvent *e = reinterpret_cast(event); + // if user doubleclicks on tab button - rename it. If user + // clicks on free space - open new tab + if (tabBar()->tabAt(e->pos()) == -1) + addNewTab(); + else + renameSession(); + return true; + } + return QTabWidget::eventFilter(obj, event); +} + +void TabWidget::removeFinished() +{ + QObject* term = sender(); + QVariant prop = term->property(TAB_INDEX_PROPERTY); + if(prop.isValid() && prop.canConvert(QVariant::Int)) + { + int index = prop.toInt(); + removeTab(index); +// if (count() == 0) +// emit closeTabNotification(); + } +} + +void TabWidget::removeTab(int index) +{ + setUpdatesEnabled(false); + + QWidget * w = widget(index); + QTabWidget::removeTab(index); + w->deleteLater(); + + recountIndexes(); + int current = currentIndex(); + if (current >= 0 ) + { + qobject_cast(widget(current))->setInitialFocus(); + } +// do not decrease it as renaming is disabled in renameTabsAfterRemove +// tabNumerator--; + setUpdatesEnabled(true); + + if (count() == 0) + emit closeTabNotification(); + + renameTabsAfterRemove(); + showHideTabBar(); +} + +void TabWidget::removeCurrentTab() +{ + // question disabled due user requests. Yes I agree it was anoying. +// if (QMessageBox::question(this, +// tr("Close current session"), +// tr("Are you sure you want to close current sesstion?"), +// QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) +// { + if (count() > 1) { + removeTab(currentIndex()); + } else { + emit closeTabNotification(); + } +} + +int TabWidget::switchToRight() +{ + int next_pos = currentIndex() + 1; + if (next_pos < count()) + setCurrentIndex(next_pos); + else + setCurrentIndex(0); + return currentIndex(); +} + +int TabWidget::switchToLeft() +{ + int previous_pos = currentIndex() - 1; + if (previous_pos < 0) + setCurrentIndex(count() - 1); + else + setCurrentIndex(previous_pos); + return currentIndex(); +} + + +void TabWidget::move(Direction dir) +{ + if(count() > 1) + { + int index = currentIndex(); + QWidget* child = widget(index); + QString label = tabText(index); + QString toolTip = tabToolTip(index); + QIcon icon = tabIcon(index); + + int newIndex = 0; + if(dir == Left) + if(index == 0) + newIndex = count() -1; + else + newIndex = index - 1; + else + if(index == count() - 1) + newIndex = 0; + else + newIndex = index + 1; + + setUpdatesEnabled(false); + QTabWidget::removeTab(index); + newIndex = insertTab(newIndex, child, label); + setTabToolTip(newIndex, toolTip); + setTabIcon(newIndex, icon); + setUpdatesEnabled(true); + setCurrentIndex(newIndex); + child->setFocus(); + recountIndexes(); + } +} + +void TabWidget::moveLeft() +{ + move(Left); +} + +void TabWidget::moveRight() +{ + move(Right); +} + +void TabWidget::changeScrollPosition(QAction *triggered) +{ + QActionGroup *scrollPosition = static_cast(sender()); + if(!scrollPosition) + qFatal("scrollPosition is NULL"); + + + Properties::Instance()->scrollBarPos = + scrollPosition->actions().indexOf(triggered); + + Properties::Instance()->saveSettings(); + propertiesChanged(); + +} + +void TabWidget::changeTabPosition(QAction *triggered) +{ + QActionGroup *tabPosition = static_cast(sender()); + if(!tabPosition) + qFatal("tabPosition is NULL"); + + Properties *prop = Properties::Instance(); + /* order is dictated from mainwindow.cpp */ + QTabWidget::TabPosition position = (QTabWidget::TabPosition)tabPosition->actions().indexOf(triggered); + setTabPosition(position); + prop->tabsPos = position; + prop->saveSettings(); + return; +} + +void TabWidget::propertiesChanged() +{ + for (int i = 0; i < count(); ++i) + { + TermWidgetHolder *console = static_cast(widget(i)); + console->propertiesChanged(); + } + showHideTabBar(); +} + +void TabWidget::clearActiveTerminal() +{ + reinterpret_cast(widget(currentIndex()))->clearActiveTerminal(); +} + +void TabWidget::saveSession() +{ + int ix = currentIndex(); + reinterpret_cast(widget(ix))->saveSession(tabText(ix)); +} + +void TabWidget::loadSession() +{ + reinterpret_cast(widget(currentIndex()))->loadSession(); +} + +void TabWidget::showHideTabBar() +{ + if (Properties::Instance()->tabBarless) + tabBar()->setVisible(false); + else + tabBar()->setVisible(Properties::Instance()->alwaysShowTabs || count() > 1); +} diff --git a/src/tabwidget.h b/src/tabwidget.h new file mode 100644 index 0000000..868fc35 --- /dev/null +++ b/src/tabwidget.h @@ -0,0 +1,100 @@ +/*************************************************************************** + * Copyright (C) 2006 by Vladimir Kuznetsov * + * vovanec@gmail.com * + * * + * 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 TAB_WIDGET +#define TAB_WIDGET + +#include +#include + +#include "properties.h" + +class TermWidgetHolder; +class QAction; +class QActionGroup; + + +class TabWidget : public QTabWidget +{ +Q_OBJECT +public: + TabWidget(QWidget* parent = 0); + + TermWidgetHolder * terminalHolder(); + + void showHideTabBar(); + +public slots: + int addNewTab(const QString& shell_program = QString()); + void removeTab(int); + void removeCurrentTab(); + int switchToRight(); + int switchToLeft(); + void removeFinished(); + void moveLeft(); + void moveRight(); + void renameSession(); + void setWorkDirectory(const QString&); + + void switchNextSubterminal(); + void switchPrevSubterminal(); + void splitHorizontally(); + void splitVertically(); + void splitCollapse(); + + void copySelection(); + void pasteClipboard(); + void pasteSelection(); + void zoomIn(); + void zoomOut(); + void zoomReset(); + + void changeTabPosition(QAction *); + void changeScrollPosition(QAction *); + void propertiesChanged(); + + void clearActiveTerminal(); + + void saveSession(); + void loadSession(); + +signals: + void closeTabNotification(); + +protected: + enum Direction{Left = 1, Right}; + void contextMenuEvent(QContextMenuEvent * event); + void recountIndexes(); + void move(Direction); + /*! Event filter for TabWidget's QTabBar. It's installed on tabBar() + in the constructor. + It's purpose is to handle doubleclicks on QTabBar for session + renaming or new tab opening + */ + bool eventFilter(QObject *obj, QEvent *event); + +private: + int tabNumerator; + QString work_dir; + /* re-order naming of the tabs then removeCurrentTab() */ + void renameTabsAfterRemove(); +}; + +#endif diff --git a/src/termwidget.cpp b/src/termwidget.cpp new file mode 100644 index 0000000..82455a7 --- /dev/null +++ b/src/termwidget.cpp @@ -0,0 +1,192 @@ +#include +#include +#include +#include + +#include "termwidget.h" +#include "config.h" +#include "properties.h" + +static int TermWidgetCount = 0; + + +TermWidgetImpl::TermWidgetImpl(const QString & wdir, const QString & shell, QWidget * parent) + : QTermWidget(0, parent) +{ + TermWidgetCount++; + QString name("TermWidget_%1"); + setObjectName(name.arg(TermWidgetCount)); + + setFlowControlEnabled(FLOW_CONTROL_ENABLED); + setFlowControlWarningEnabled(FLOW_CONTROL_WARNING_ENABLED); + + propertiesChanged(); + + setHistorySize(5000); + + if (!wdir.isNull()) + setWorkingDirectory(wdir); + + if (shell.isNull()) + { + if (!Properties::Instance()->shell.isNull()) + setShellProgram(Properties::Instance()->shell); + } + else + { + qDebug() << "Settings custom shell program:" << shell; + QStringList parts = shell.split(QRegExp("\\s+"), QString::SkipEmptyParts); + qDebug() << parts; + setShellProgram(parts.at(0)); + parts.removeAt(0); + if (parts.count()) + setArgs(parts); + } + + setMotionAfterPasting(Properties::Instance()->m_motionAfterPaste); + + setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), + this, SLOT(customContextMenuCall(const QPoint &))); + + connect(this, SIGNAL(urlActivated(QUrl)), this, SLOT(activateUrl(const QUrl&))); + + startShellProgram(); +} + +void TermWidgetImpl::propertiesChanged() +{ + setColorScheme(Properties::Instance()->colorScheme); + setTerminalFont(Properties::Instance()->font); + setMotionAfterPasting(Properties::Instance()->m_motionAfterPaste); + + if (Properties::Instance()->historyLimited) + { + setHistorySize(Properties::Instance()->historyLimitedTo); + } + else + { + // Unlimited history + setHistorySize(-1); + } + + qDebug() << "TermWidgetImpl::propertiesChanged" << this << "emulation:" << Properties::Instance()->emulation; + setKeyBindings(Properties::Instance()->emulation); + setTerminalOpacity(Properties::Instance()->termOpacity/100.0); + + /* be consequent with qtermwidget.h here */ + switch(Properties::Instance()->scrollBarPos) { + case 0: + setScrollBarPosition(QTermWidget::NoScrollBar); + break; + case 1: + setScrollBarPosition(QTermWidget::ScrollBarLeft); + break; + case 2: + default: + setScrollBarPosition(QTermWidget::ScrollBarRight); + break; + } + + update(); +} + +void TermWidgetImpl::customContextMenuCall(const QPoint & pos) +{ + QMenu menu; + menu.addAction(Properties::Instance()->actions[COPY_SELECTION]); + menu.addAction(Properties::Instance()->actions[PASTE_CLIPBOARD]); + menu.addAction(Properties::Instance()->actions[PASTE_SELECTION]); + menu.addAction(Properties::Instance()->actions[ZOOM_IN]); + menu.addAction(Properties::Instance()->actions[ZOOM_OUT]); + menu.addAction(Properties::Instance()->actions[ZOOM_RESET]); + menu.addSeparator(); + menu.addAction(Properties::Instance()->actions[CLEAR_TERMINAL]); + menu.addAction(Properties::Instance()->actions[SPLIT_HORIZONTAL]); + menu.addAction(Properties::Instance()->actions[SPLIT_VERTICAL]); +#warning TODO/FIXME: disable the action when there is only one terminal + menu.addAction(Properties::Instance()->actions[SUB_COLLAPSE]); + menu.exec(mapToGlobal(pos)); +} + +void TermWidgetImpl::zoomIn() +{ + emit QTermWidget::zoomIn(); +// note: do not save zoom here due the #74 Zoom reset option resets font back to Monospace +// Properties::Instance()->font = getTerminalFont(); +// Properties::Instance()->saveSettings(); +} + +void TermWidgetImpl::zoomOut() +{ + emit QTermWidget::zoomOut(); +// note: do not save zoom here due the #74 Zoom reset option resets font back to Monospace +// Properties::Instance()->font = getTerminalFont(); +// Properties::Instance()->saveSettings(); +} + +void TermWidgetImpl::zoomReset() +{ +// note: do not save zoom here due the #74 Zoom reset option resets font back to Monospace +// Properties::Instance()->font = Properties::Instance()->font; + setTerminalFont(Properties::Instance()->font); +// Properties::Instance()->saveSettings(); +} + +void TermWidgetImpl::activateUrl(const QUrl & url) { + if (QApplication::keyboardModifiers() & Qt::ControlModifier) { + QDesktopServices::openUrl(url); + } +} + +TermWidget::TermWidget(const QString & wdir, const QString & shell, QWidget * parent) + : QWidget(parent) +{ + m_border = palette().color(QPalette::Window); + m_term = new TermWidgetImpl(wdir, shell, this); + setFocusProxy(m_term); + + m_layout = new QVBoxLayout; + setLayout(m_layout); + + m_layout->addWidget(m_term); + + propertiesChanged(); + + connect(m_term, SIGNAL(finished()), this, SIGNAL(finished())); + connect(m_term, SIGNAL(termGetFocus()), this, SLOT(term_termGetFocus())); + connect(m_term, SIGNAL(termLostFocus()), this, SLOT(term_termLostFocus())); +} + +void TermWidget::propertiesChanged() +{ + if (Properties::Instance()->highlightCurrentTerminal) + m_layout->setContentsMargins(2, 2, 2, 2); + else + m_layout->setContentsMargins(0, 0, 0, 0); + + m_term->propertiesChanged(); +} + +void TermWidget::term_termGetFocus() +{ + m_border = palette().color(QPalette::Highlight); + emit termGetFocus(this); + update(); +} + +void TermWidget::term_termLostFocus() +{ + m_border = palette().color(QPalette::Window); + update(); +} + +void TermWidget::paintEvent (QPaintEvent *) +{ + QPainter p(this); + QPen pen(m_border); + pen.setWidth(30); + pen.setBrush(m_border); + p.setPen(pen); + p.drawRect(0, 0, width()-1, height()-1); +} diff --git a/src/termwidget.h b/src/termwidget.h new file mode 100644 index 0000000..f2e0178 --- /dev/null +++ b/src/termwidget.h @@ -0,0 +1,71 @@ +#ifndef TERMWIDGET_H +#define TERMWIDGET_H + +#include + +#include + + +class TermWidgetImpl : public QTermWidget +{ + Q_OBJECT + +// QMap< QString, QAction * > actionMap; + + public: + + TermWidgetImpl(const QString & wdir, const QString & shell=QString(), QWidget * parent=0); + void propertiesChanged(); + + signals: + void renameSession(); + void removeCurrentSession(); + + public slots: + void zoomIn(); + void zoomOut(); + void zoomReset(); + + private slots: + void customContextMenuCall(const QPoint & pos); + void activateUrl(const QUrl& url); +}; + + +class TermWidget : public QWidget +{ + Q_OBJECT + + TermWidgetImpl * m_term; + QVBoxLayout * m_layout; + QColor m_border; + + public: + TermWidget(const QString & wdir, const QString & shell=QString(), QWidget * parent=0); + + void propertiesChanged(); + QStringList availableKeyBindings() { return m_term->availableKeyBindings(); } + + TermWidgetImpl * impl() { return m_term; } + + signals: + void finished(); + void renameSession(); + void removeCurrentSession(); + void splitHorizontal(TermWidget * self); + void splitVertical(TermWidget * self); + void splitCollapse(TermWidget * self); + void termGetFocus(TermWidget * self); + + public slots: + + protected: + void paintEvent (QPaintEvent * event); + + private slots: + void term_termGetFocus(); + void term_termLostFocus(); +}; + +#endif + diff --git a/src/termwidgetholder.cpp b/src/termwidgetholder.cpp new file mode 100644 index 0000000..1aeadad --- /dev/null +++ b/src/termwidgetholder.cpp @@ -0,0 +1,290 @@ +#include +#include +#include + +#include "termwidgetholder.h" +#include "termwidget.h" +#include "properties.h" +#include + + +TermWidgetHolder::TermWidgetHolder(const QString & wdir, const QString & shell, QWidget * parent) + : QWidget(parent), + m_wdir(wdir), + m_shell(shell), + m_currentTerm(0) +{ + setFocusPolicy(Qt::NoFocus); + QGridLayout * lay = new QGridLayout(this); + lay->setSpacing(0); + lay->setContentsMargins(0, 0, 0, 0); + + QSplitter *s = new QSplitter(this); + s->setFocusPolicy(Qt::NoFocus); + TermWidget *w = newTerm(); + s->addWidget(w); + lay->addWidget(s); + + setLayout(lay); +} + +TermWidgetHolder::~TermWidgetHolder() +{ +} + +void TermWidgetHolder::setInitialFocus() +{ + QList list = findChildren(); + TermWidget * w = list.count() == 0 ? 0 : list.at(0); + if (w) + w->setFocus(Qt::OtherFocusReason); +} + +void TermWidgetHolder::loadSession() +{ + bool ok; + QString name = QInputDialog::getItem(this, tr("Load Session"), + tr("List of saved sessions:"), + Properties::Instance()->sessions.keys(), + 0, false, &ok); + if (!ok || name.isEmpty()) + return; +#if 0 + foreach (QWidget * w, findChildren()) + { + if (w) + { + delete w; + w = 0; + } + } + + qDebug() << "load" << name << QString(Properties::Instance()->sessions[name]); + QStringList splitters = QString(Properties::Instance()->sessions[name]).split("|", QString::SkipEmptyParts); + foreach (QString splitter, splitters) + { + QStringList components = splitter.split(","); + qDebug() << "comp" << components; + // orientation + Qt::Orientation orientation; + if (components.size() > 0) + orientation = components.takeAt(0).toInt(); + // sizes + QList sizes; + QList widgets; + foreach (QString s, components) + { + sizes << s.toInt(); + widgets << newTerm(); + } + // new terms + } +#endif +} + +void TermWidgetHolder::saveSession(const QString & name) +{ + Session dump; + QString num("%1"); + foreach(QSplitter *w, findChildren()) + { + dump += '|' + num.arg(w->orientation()); + foreach (int i, w->sizes()) + dump += ',' + num.arg(i); + } + Properties::Instance()->sessions[name] = dump; + qDebug() << "dump" << dump; +} + +TermWidget* TermWidgetHolder::currentTerminal() +{ + qDebug() << m_currentTerm << "current terminal"; + return m_currentTerm; +} + +void TermWidgetHolder::setWDir(const QString & wdir) +{ + m_wdir = wdir; +} + +void TermWidgetHolder::switchNextSubterminal() +{ + // TODO/FIXME: merge switchPrevSubterminal with switchNextSubterminal + QList l = findChildren(); + int ix = -1; + foreach (TermWidget * w, l) + { + ++ix; +// qDebug() << ix << w << w->impl() << w->impl()->hasFocus() << QApplication::focusWidget(); +// qDebug() << "parent: " << w->parent(); + if (w->impl()->hasFocus()) + { + break; + } + } + + if (ix < l.count()-1) + { + l.at(ix+1)->impl()->setFocus(Qt::OtherFocusReason); + } + else if (ix == l.count()-1) + { + l.at(0)->impl()->setFocus(Qt::OtherFocusReason); + } +} + +void TermWidgetHolder::switchPrevSubterminal() +{ + // TODO/FIXME: merge switchPrevSubterminal with switchNextSubterminal + QList l = findChildren(); + int ix = -1; + foreach (TermWidget * w, l) + { + ++ix; +// qDebug() << ix << w << w->impl() << w->impl()->hasFocus() << QApplication::focusWidget(); +// qDebug() << "parent: " << w->parent(); + if (w->impl()->hasFocus()) + { + break; + } + } + //qDebug() << ix << l.at(ix)->impl() << QApplication::focusWidget() << l; + + if (ix > 0) + { + l.at(ix-1)->impl()->setFocus(Qt::OtherFocusReason); + } + else if (ix == 0) + { + l.at(l.count()-1)->impl()->setFocus(Qt::OtherFocusReason); + } +} + +void TermWidgetHolder::clearActiveTerminal() +{ + currentTerminal()->impl()->clear(); +} + +void TermWidgetHolder::propertiesChanged() +{ + foreach(TermWidget *w, findChildren()) + w->propertiesChanged(); +} + +void TermWidgetHolder::splitHorizontal(TermWidget * term) +{ + split(term, Qt::Vertical); +} + +void TermWidgetHolder::splitVertical(TermWidget * term) +{ + split(term, Qt::Horizontal); +} + +void TermWidgetHolder::splitCollapse(TermWidget * term) +{ + QSplitter * parent = qobject_cast(term->parent()); + assert(parent); + term->setParent(0); + delete term; + + int cnt = parent->findChildren().count(); + if (cnt == 0) + { + parent->setParent(0); + delete parent; + } + + QList tlist = findChildren(); + int localCnt = tlist.count(); + + if (localCnt > 0) + { + tlist.at(0)->setFocus(Qt::OtherFocusReason); + update(); + if (parent) + parent->update(); + } + else + emit finished(); +} + +void TermWidgetHolder::split(TermWidget *term, Qt::Orientation orientation) +{ + QSplitter *parent = qobject_cast(term->parent()); + assert(parent); + + int ix = parent->indexOf(term); + QList parentSizes = parent->sizes(); + + QList sizes; + sizes << 1 << 1; + + QSplitter *s = new QSplitter(orientation, this); + s->setFocusPolicy(Qt::NoFocus); + s->insertWidget(0, term); + + // wdir settings + QString wd(m_wdir); + if (Properties::Instance()->useCWD) + { + wd = term->impl()->workingDirectory(); + if (wd.isEmpty()) + wd = m_wdir; + } + + TermWidget * w = newTerm(wd); + s->insertWidget(1, w); + s->setSizes(sizes); + + parent->insertWidget(ix, s); + parent->setSizes(parentSizes); + + w->setFocus(Qt::OtherFocusReason); +} + +TermWidget *TermWidgetHolder::newTerm(const QString & wdir, const QString & shell) +{ + QString wd(wdir); + if (wd.isEmpty()) + wd = m_wdir; + + QString sh(shell); + if (shell.isEmpty()) + sh = m_shell; + + TermWidget *w = new TermWidget(wd, sh, this); + // proxy signals + connect(w, SIGNAL(renameSession()), this, SIGNAL(renameSession())); + connect(w, SIGNAL(removeCurrentSession()), this, SIGNAL(lastTerminalClosed())); + connect(w, SIGNAL(finished()), this, SLOT(handle_finished())); + // consume signals + + connect(w, SIGNAL(splitHorizontal(TermWidget *)), + this, SLOT(splitHorizontal(TermWidget *))); + connect(w, SIGNAL(splitVertical(TermWidget *)), + this, SLOT(splitVertical(TermWidget *))); + connect(w, SIGNAL(splitCollapse(TermWidget *)), + this, SLOT(splitCollapse(TermWidget *))); + connect(w, SIGNAL(termGetFocus(TermWidget *)), + this, SLOT(setCurrentTerminal(TermWidget *))); + + return w; +} + +void TermWidgetHolder::setCurrentTerminal(TermWidget* term) +{ + qDebug() << "set current term:" << term; + m_currentTerm = term; +} + +void TermWidgetHolder::handle_finished() +{ + TermWidget * w = qobject_cast(sender()); + if (!w) + { + qDebug() << "TermWidgetHolder::handle_finished: Unknown object to handle" << w; + assert(0); + } + splitCollapse(w); +} diff --git a/src/termwidgetholder.h b/src/termwidgetholder.h new file mode 100644 index 0000000..586eef1 --- /dev/null +++ b/src/termwidgetholder.h @@ -0,0 +1,64 @@ +#ifndef TERMWIDGETHOLDER_H +#define TERMWIDGETHOLDER_H + +#include +#include "termwidget.h" +class QSplitter; + + + +/*! \brief TermWidget group/session manager. + +This widget (one per TabWidget tab) is a "proxy" widget beetween TabWidget and +unspecified count of TermWidgets. Basically it should look like a single TermWidget +for TabWidget - with its signals and slots. + +Splitting and collapsing of TermWidgets is done here. +*/ +class TermWidgetHolder : public QWidget +{ + Q_OBJECT + + public: + TermWidgetHolder(const QString & wdir, const QString & shell=QString(), QWidget * parent=0); + ~TermWidgetHolder(); + + void propertiesChanged(); + void setInitialFocus(); + + void loadSession(); + void saveSession(const QString & name); + void zoomIn(uint step); + void zoomOut(uint step); + + TermWidget* currentTerminal(); + + public slots: + void splitHorizontal(TermWidget * term); + void splitVertical(TermWidget * term); + void splitCollapse(TermWidget * term); + void setWDir(const QString & wdir); + void switchNextSubterminal(); + void switchPrevSubterminal(); + void clearActiveTerminal(); + + signals: + void finished(); + void lastTerminalClosed(); + void renameSession(); + + private: + QString m_wdir; + QString m_shell; + TermWidget * m_currentTerm; + + void split(TermWidget * term, Qt::Orientation orientation); + TermWidget * newTerm(const QString & wdir=QString(), const QString & shell=QString()); + + private slots: + void setCurrentTerminal(TermWidget* term); + void handle_finished(); +}; + +#endif + diff --git a/src/third-party/qxtglobal.h b/src/third-party/qxtglobal.h new file mode 100644 index 0000000..7d5abfb --- /dev/null +++ b/src/third-party/qxtglobal.h @@ -0,0 +1,233 @@ + +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + +#ifndef QXTGLOBAL_H +#define QXTGLOBAL_H + +#include + +#define QXT_VERSION 0x000700 +#define QXT_VERSION_STR "0.7.0" + +//--------------------------global macros------------------------------ + +#ifndef QXT_NO_MACROS + +#ifndef _countof +#define _countof(x) (sizeof(x)/sizeof(*x)) +#endif + +#endif // QXT_NO_MACROS + +//--------------------------export macros------------------------------ + +#define QXT_DLLEXPORT DO_NOT_USE_THIS_ANYMORE + +#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) +# if defined(BUILD_QXT_CORE) +# define QXT_CORE_EXPORT Q_DECL_EXPORT +# else +# define QXT_CORE_EXPORT Q_DECL_IMPORT +# endif +#else +# define QXT_CORE_EXPORT +#endif // BUILD_QXT_CORE + +#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) +# if defined(BUILD_QXT_GUI) +# define QXT_GUI_EXPORT Q_DECL_EXPORT +# else +# define QXT_GUI_EXPORT Q_DECL_IMPORT +# endif +#else +# define QXT_GUI_EXPORT +#endif // BUILD_QXT_GUI + +#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) +# if defined(BUILD_QXT_NETWORK) +# define QXT_NETWORK_EXPORT Q_DECL_EXPORT +# else +# define QXT_NETWORK_EXPORT Q_DECL_IMPORT +# endif +#else +# define QXT_NETWORK_EXPORT +#endif // BUILD_QXT_NETWORK + +#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) +# if defined(BUILD_QXT_SQL) +# define QXT_SQL_EXPORT Q_DECL_EXPORT +# else +# define QXT_SQL_EXPORT Q_DECL_IMPORT +# endif +#else +# define QXT_SQL_EXPORT +#endif // BUILD_QXT_SQL + +#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) +# if defined(BUILD_QXT_WEB) +# define QXT_WEB_EXPORT Q_DECL_EXPORT +# else +# define QXT_WEB_EXPORT Q_DECL_IMPORT +# endif +#else +# define QXT_WEB_EXPORT +#endif // BUILD_QXT_WEB + +#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) +# if defined(BUILD_QXT_BERKELEY) +# define QXT_BERKELEY_EXPORT Q_DECL_EXPORT +# else +# define QXT_BERKELEY_EXPORT Q_DECL_IMPORT +# endif +#else +# define QXT_BERKELEY_EXPORT +#endif // BUILD_QXT_BERKELEY + +#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) +# if defined(BUILD_QXT_ZEROCONF) +# define QXT_ZEROCONF_EXPORT Q_DECL_EXPORT +# else +# define QXT_ZEROCONF_EXPORT Q_DECL_IMPORT +# endif +#else +# define QXT_ZEROCONF_EXPORT +#endif // QXT_ZEROCONF_EXPORT + +#if defined(BUILD_QXT_CORE) || defined(BUILD_QXT_GUI) || defined(BUILD_QXT_SQL) || defined(BUILD_QXT_NETWORK) || defined(BUILD_QXT_WEB) || defined(BUILD_QXT_BERKELEY) || defined(BUILD_QXT_ZEROCONF) +# define BUILD_QXT +#endif + +QXT_CORE_EXPORT const char* qxtVersion(); + +#ifndef QT_BEGIN_NAMESPACE +#define QT_BEGIN_NAMESPACE +#endif + +#ifndef QT_END_NAMESPACE +#define QT_END_NAMESPACE +#endif + +#ifndef QT_FORWARD_DECLARE_CLASS +#define QT_FORWARD_DECLARE_CLASS(Class) class Class; +#endif + +/**************************************************************************** +** This file is derived from code bearing the following notice: +** The sole author of this file, Adam Higerd, has explicitly disclaimed all +** copyright interest and protection for the content within. This file has +** been placed in the public domain according to United States copyright +** statute and case law. In jurisdictions where this public domain dedication +** is not legally recognized, anyone who receives a copy of this file is +** permitted to use, modify, duplicate, and redistribute this file, in whole +** or in part, with no restrictions or conditions. In these jurisdictions, +** this file shall be copyright (C) 2006-2008 by Adam Higerd. +****************************************************************************/ + +#define QXT_DECLARE_PRIVATE(PUB) friend class PUB##Private; QxtPrivateInterface qxt_d; +#define QXT_DECLARE_PUBLIC(PUB) friend class PUB; +#define QXT_INIT_PRIVATE(PUB) qxt_d.setPublic(this); +#define QXT_D(PUB) PUB##Private& d = qxt_d() +#define QXT_P(PUB) PUB& p = qxt_p() + +template +class QxtPrivate +{ +public: + virtual ~QxtPrivate() + {} + inline void QXT_setPublic(PUB* pub) + { + qxt_p_ptr = pub; + } + +protected: + inline PUB& qxt_p() + { + return *qxt_p_ptr; + } + inline const PUB& qxt_p() const + { + return *qxt_p_ptr; + } + inline PUB* qxt_ptr() + { + return qxt_p_ptr; + } + inline const PUB* qxt_ptr() const + { + return qxt_p_ptr; + } + +private: + PUB* qxt_p_ptr; +}; + +template +class QxtPrivateInterface +{ + friend class QxtPrivate; +public: + QxtPrivateInterface() + { + pvt = new PVT; + } + ~QxtPrivateInterface() + { + delete pvt; + } + + inline void setPublic(PUB* pub) + { + pvt->QXT_setPublic(pub); + } + inline PVT& operator()() + { + return *static_cast(pvt); + } + inline const PVT& operator()() const + { + return *static_cast(pvt); + } + inline PVT * operator->() + { + return static_cast(pvt); + } + inline const PVT * operator->() const + { + return static_cast(pvt); + } +private: + QxtPrivateInterface(const QxtPrivateInterface&) { } + QxtPrivateInterface& operator=(const QxtPrivateInterface&) { } + QxtPrivate* pvt; +}; + +#endif // QXT_GLOBAL diff --git a/src/third-party/qxtglobalshortcut.cpp b/src/third-party/qxtglobalshortcut.cpp new file mode 100644 index 0000000..44b9f91 --- /dev/null +++ b/src/third-party/qxtglobalshortcut.cpp @@ -0,0 +1,223 @@ +#include "qxtglobalshortcut.h" +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + +#include "qxtglobalshortcut_p.h" +#include +#include + +#ifndef Q_OS_MAC +int QxtGlobalShortcutPrivate::ref = 0; +# if QT_VERSION < QT_VERSION_CHECK(5,0,0) +QAbstractEventDispatcher::EventFilter QxtGlobalShortcutPrivate::prevEventFilter = 0; +# endif +#endif // Q_OS_MAC +QHash, QxtGlobalShortcut*> QxtGlobalShortcutPrivate::shortcuts; + +QxtGlobalShortcutPrivate::QxtGlobalShortcutPrivate() : enabled(true), key(Qt::Key(0)), mods(Qt::NoModifier) +{ +#ifndef Q_OS_MAC + if (ref == 0) { +# if QT_VERSION < QT_VERSION_CHECK(5,0,0) + prevEventFilter = QAbstractEventDispatcher::instance()->setEventFilter(eventFilter); +# else + QAbstractEventDispatcher::instance()->installNativeEventFilter(this); +#endif + } + ++ref; +#endif // Q_OS_MAC +} + +QxtGlobalShortcutPrivate::~QxtGlobalShortcutPrivate() +{ +#ifndef Q_OS_MAC + --ref; + if (ref == 0) { + QAbstractEventDispatcher *ed = QAbstractEventDispatcher::instance(); + if (ed != 0) { +# if QT_VERSION < QT_VERSION_CHECK(5,0,0) + ed->setEventFilter(prevEventFilter); +# else + ed->removeNativeEventFilter(this); +# endif + } + } +#endif // Q_OS_MAC +} + +bool QxtGlobalShortcutPrivate::setShortcut(const QKeySequence& shortcut) +{ + Qt::KeyboardModifiers allMods = Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier; + key = shortcut.isEmpty() ? Qt::Key(0) : Qt::Key((shortcut[0] ^ allMods) & shortcut[0]); + mods = shortcut.isEmpty() ? Qt::KeyboardModifiers(0) : Qt::KeyboardModifiers(shortcut[0] & allMods); + const quint32 nativeKey = nativeKeycode(key); + const quint32 nativeMods = nativeModifiers(mods); + const bool res = registerShortcut(nativeKey, nativeMods); + if (res) + shortcuts.insert(qMakePair(nativeKey, nativeMods), &qxt_p()); + else + qWarning() << "QxtGlobalShortcut failed to register:" << QKeySequence(key + mods).toString(); + return res; +} + +bool QxtGlobalShortcutPrivate::unsetShortcut() +{ + bool res = false; + const quint32 nativeKey = nativeKeycode(key); + const quint32 nativeMods = nativeModifiers(mods); + if (shortcuts.value(qMakePair(nativeKey, nativeMods)) == &qxt_p()) + res = unregisterShortcut(nativeKey, nativeMods); + if (res) + shortcuts.remove(qMakePair(nativeKey, nativeMods)); + else + qWarning() << "QxtGlobalShortcut failed to unregister:" << QKeySequence(key + mods).toString(); + key = Qt::Key(0); + mods = Qt::KeyboardModifiers(0); + return res; +} + +void QxtGlobalShortcutPrivate::activateShortcut(quint32 nativeKey, quint32 nativeMods) +{ + QxtGlobalShortcut* shortcut = shortcuts.value(qMakePair(nativeKey, nativeMods)); + if (shortcut && shortcut->isEnabled()) + emit shortcut->activated(); +} + +/*! + \class QxtGlobalShortcut + \inmodule QxtWidgets + \brief The QxtGlobalShortcut class provides a global shortcut aka "hotkey". + + A global shortcut triggers even if the application is not active. This + makes it easy to implement applications that react to certain shortcuts + still if some other application is active or if the application is for + example minimized to the system tray. + + Example usage: + \code + QxtGlobalShortcut* shortcut = new QxtGlobalShortcut(window); + connect(shortcut, SIGNAL(activated()), window, SLOT(toggleVisibility())); + shortcut->setShortcut(QKeySequence("Ctrl+Shift+F12")); + \endcode + + \bold {Note:} Since Qxt 0.6 QxtGlobalShortcut no more requires QxtApplication. + */ + +/*! + \fn QxtGlobalShortcut::activated() + + This signal is emitted when the user types the shortcut's key sequence. + + \sa shortcut + */ + +/*! + Constructs a new QxtGlobalShortcut with \a parent. + */ +QxtGlobalShortcut::QxtGlobalShortcut(QObject* parent) + : QObject(parent) +{ + QXT_INIT_PRIVATE(QxtGlobalShortcut); +} + +/*! + Constructs a new QxtGlobalShortcut with \a shortcut and \a parent. + */ +QxtGlobalShortcut::QxtGlobalShortcut(const QKeySequence& shortcut, QObject* parent) + : QObject(parent) +{ + QXT_INIT_PRIVATE(QxtGlobalShortcut); + setShortcut(shortcut); +} + +/*! + Destructs the QxtGlobalShortcut. + */ +QxtGlobalShortcut::~QxtGlobalShortcut() +{ + if (qxt_d().key != 0) + qxt_d().unsetShortcut(); +} + +/*! + \property QxtGlobalShortcut::shortcut + \brief the shortcut key sequence + + \bold {Note:} Notice that corresponding key press and release events are not + delivered for registered global shortcuts even if they are disabled. + Also, comma separated key sequences are not supported. + Only the first part is used: + + \code + qxtShortcut->setShortcut(QKeySequence("Ctrl+Alt+A,Ctrl+Alt+B")); + Q_ASSERT(qxtShortcut->shortcut() == QKeySequence("Ctrl+Alt+A")); + \endcode + */ +QKeySequence QxtGlobalShortcut::shortcut() const +{ + return QKeySequence(qxt_d().key | qxt_d().mods); +} + +bool QxtGlobalShortcut::setShortcut(const QKeySequence& shortcut) +{ + if (qxt_d().key != 0) + qxt_d().unsetShortcut(); + return qxt_d().setShortcut(shortcut); +} + +/*! + \property QxtGlobalShortcut::enabled + \brief whether the shortcut is enabled + + A disabled shortcut does not get activated. + + The default value is \c true. + + \sa setDisabled() + */ +bool QxtGlobalShortcut::isEnabled() const +{ + return qxt_d().enabled; +} + +void QxtGlobalShortcut::setEnabled(bool enabled) +{ + qxt_d().enabled = enabled; +} + +/*! + Sets the shortcut \a disabled. + + \sa enabled + */ +void QxtGlobalShortcut::setDisabled(bool disabled) +{ + qxt_d().enabled = !disabled; +} diff --git a/src/third-party/qxtglobalshortcut.h b/src/third-party/qxtglobalshortcut.h new file mode 100644 index 0000000..a81942d --- /dev/null +++ b/src/third-party/qxtglobalshortcut.h @@ -0,0 +1,64 @@ +#ifndef QXTGLOBALSHORTCUT_H +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + +#define QXTGLOBALSHORTCUT_H + +#include "qxtglobal.h" +#include +#include +class QxtGlobalShortcutPrivate; + +class QXT_GUI_EXPORT QxtGlobalShortcut : public QObject +{ + Q_OBJECT + QXT_DECLARE_PRIVATE(QxtGlobalShortcut) + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) + Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut) + +public: + explicit QxtGlobalShortcut(QObject* parent = 0); + explicit QxtGlobalShortcut(const QKeySequence& shortcut, QObject* parent = 0); + virtual ~QxtGlobalShortcut(); + + QKeySequence shortcut() const; + bool setShortcut(const QKeySequence& shortcut); + + bool isEnabled() const; + +public Q_SLOTS: + void setEnabled(bool enabled = true); + void setDisabled(bool disabled = true); + +Q_SIGNALS: + void activated(); +}; + +#endif // QXTGLOBALSHORTCUT_H diff --git a/src/third-party/qxtglobalshortcut_mac.cpp b/src/third-party/qxtglobalshortcut_mac.cpp new file mode 100644 index 0000000..58b9a90 --- /dev/null +++ b/src/third-party/qxtglobalshortcut_mac.cpp @@ -0,0 +1,258 @@ +#include +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + +#include "qxtglobalshortcut_p.h" +#include +#include +#include +#include + +typedef QPair Identifier; +static QMap keyRefs; +static QHash keyIDs; +static quint32 hotKeySerial = 0; +static bool qxt_mac_handler_installed = false; + +OSStatus qxt_mac_handle_hot_key(EventHandlerCallRef nextHandler, EventRef event, void* data) +{ + Q_UNUSED(nextHandler); + Q_UNUSED(data); + if (GetEventClass(event) == kEventClassKeyboard && GetEventKind(event) == kEventHotKeyPressed) + { + EventHotKeyID keyID; + GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(keyID), NULL, &keyID); + Identifier id = keyIDs.key(keyID.id); + QxtGlobalShortcutPrivate::activateShortcut(id.second, id.first); + } + return noErr; +} + +quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) +{ + quint32 native = 0; + if (modifiers & Qt::ShiftModifier) + native |= shiftKey; + if (modifiers & Qt::ControlModifier) + native |= cmdKey; + if (modifiers & Qt::AltModifier) + native |= optionKey; + if (modifiers & Qt::MetaModifier) + native |= controlKey; + if (modifiers & Qt::KeypadModifier) + native |= kEventKeyModifierNumLockMask; + return native; +} + +quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) +{ + UTF16Char ch; + // Constants found in NSEvent.h from AppKit.framework + switch (key) + { + case Qt::Key_Return: + return kVK_Return; + case Qt::Key_Enter: + return kVK_ANSI_KeypadEnter; + case Qt::Key_Tab: + return kVK_Tab; + case Qt::Key_Space: + return kVK_Space; + case Qt::Key_Backspace: + return kVK_Delete; + case Qt::Key_Control: + return kVK_Command; + case Qt::Key_Shift: + return kVK_Shift; + case Qt::Key_CapsLock: + return kVK_CapsLock; + case Qt::Key_Option: + return kVK_Option; + case Qt::Key_Meta: + return kVK_Control; + case Qt::Key_F17: + return kVK_F17; + case Qt::Key_VolumeUp: + return kVK_VolumeUp; + case Qt::Key_VolumeDown: + return kVK_VolumeDown; + case Qt::Key_F18: + return kVK_F18; + case Qt::Key_F19: + return kVK_F19; + case Qt::Key_F20: + return kVK_F20; + case Qt::Key_F5: + return kVK_F5; + case Qt::Key_F6: + return kVK_F6; + case Qt::Key_F7: + return kVK_F7; + case Qt::Key_F3: + return kVK_F3; + case Qt::Key_F8: + return kVK_F8; + case Qt::Key_F9: + return kVK_F9; + case Qt::Key_F11: + return kVK_F11; + case Qt::Key_F13: + return kVK_F13; + case Qt::Key_F16: + return kVK_F16; + case Qt::Key_F14: + return kVK_F14; + case Qt::Key_F10: + return kVK_F10; + case Qt::Key_F12: + return kVK_F12; + case Qt::Key_F15: + return kVK_F15; + case Qt::Key_Help: + return kVK_Help; + case Qt::Key_Home: + return kVK_Home; + case Qt::Key_PageUp: + return kVK_PageUp; + case Qt::Key_Delete: + return kVK_ForwardDelete; + case Qt::Key_F4: + return kVK_F4; + case Qt::Key_End: + return kVK_End; + case Qt::Key_F2: + return kVK_F2; + case Qt::Key_PageDown: + return kVK_PageDown; + case Qt::Key_F1: + return kVK_F1; + case Qt::Key_Left: + return kVK_LeftArrow; + case Qt::Key_Right: + return kVK_RightArrow; + case Qt::Key_Down: + return kVK_DownArrow; + case Qt::Key_Up: + return kVK_UpArrow; + default: + ; + } + + if (key == Qt::Key_Escape) ch = 27; + else if (key == Qt::Key_Return) ch = 13; + else if (key == Qt::Key_Enter) ch = 3; + else if (key == Qt::Key_Tab) ch = 9; + else ch = key; + + CFDataRef currentLayoutData; + TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource(); + + if (currentKeyboard == NULL) + return 0; + + currentLayoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData); + CFRelease(currentKeyboard); + if (currentLayoutData == NULL) + return 0; + + UCKeyboardLayout* header = (UCKeyboardLayout*)CFDataGetBytePtr(currentLayoutData); + UCKeyboardTypeHeader* table = header->keyboardTypeList; + + uint8_t *data = (uint8_t*)header; + // God, would a little documentation for this shit kill you... + for (quint32 i=0; i < header->keyboardTypeCount; i++) + { + UCKeyStateRecordsIndex* stateRec = 0; + if (table[i].keyStateRecordsIndexOffset != 0) + { + stateRec = reinterpret_cast(data + table[i].keyStateRecordsIndexOffset); + if (stateRec->keyStateRecordsIndexFormat != kUCKeyStateRecordsIndexFormat) stateRec = 0; + } + + UCKeyToCharTableIndex* charTable = reinterpret_cast(data + table[i].keyToCharTableIndexOffset); + if (charTable->keyToCharTableIndexFormat != kUCKeyToCharTableIndexFormat) continue; + + for (quint32 j=0; j < charTable->keyToCharTableCount; j++) + { + UCKeyOutput* keyToChar = reinterpret_cast(data + charTable->keyToCharTableOffsets[j]); + for (quint32 k=0; k < charTable->keyToCharTableSize; k++) + { + if (keyToChar[k] & kUCKeyOutputTestForIndexMask) + { + long idx = keyToChar[k] & kUCKeyOutputGetIndexMask; + if (stateRec && idx < stateRec->keyStateRecordCount) + { + UCKeyStateRecord* rec = reinterpret_cast(data + stateRec->keyStateRecordOffsets[idx]); + if (rec->stateZeroCharData == ch) return k; + } + } + else if (!(keyToChar[k] & kUCKeyOutputSequenceIndexMask) && keyToChar[k] < 0xFFFE) + { + if (keyToChar[k] == ch) return k; + } + } // for k + } // for j + } // for i + return 0; +} + +bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) +{ + if (!qxt_mac_handler_installed) + { + EventTypeSpec t; + t.eventClass = kEventClassKeyboard; + t.eventKind = kEventHotKeyPressed; + InstallApplicationEventHandler(&qxt_mac_handle_hot_key, 1, &t, NULL, NULL); + } + + EventHotKeyID keyID; + keyID.signature = 'cute'; + keyID.id = ++hotKeySerial; + + EventHotKeyRef ref = 0; + bool rv = !RegisterEventHotKey(nativeKey, nativeMods, keyID, GetApplicationEventTarget(), 0, &ref); + if (rv) + { + keyIDs.insert(Identifier(nativeMods, nativeKey), keyID.id); + keyRefs.insert(keyID.id, ref); + } + return rv; +} + +bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) +{ + Identifier id(nativeMods, nativeKey); + if (!keyIDs.contains(id)) return false; + + EventHotKeyRef ref = keyRefs.take(keyIDs[id]); + keyIDs.remove(id); + return !UnregisterEventHotKey(ref); +} diff --git a/src/third-party/qxtglobalshortcut_p.h b/src/third-party/qxtglobalshortcut_p.h new file mode 100644 index 0000000..112988d --- /dev/null +++ b/src/third-party/qxtglobalshortcut_p.h @@ -0,0 +1,84 @@ +#ifndef QXTGLOBALSHORTCUT_P_H +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + +#define QXTGLOBALSHORTCUT_P_H + +#include "qxtglobalshortcut.h" +#include +#include +#include + +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) +#include +#endif + + +class QxtGlobalShortcutPrivate : public QxtPrivate +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) && !defined(Q_OS_MAC) + ,public QAbstractNativeEventFilter +#endif +{ +public: + QXT_DECLARE_PUBLIC(QxtGlobalShortcut) + QxtGlobalShortcutPrivate(); + ~QxtGlobalShortcutPrivate(); + + bool enabled; + Qt::Key key; + Qt::KeyboardModifiers mods; + + bool setShortcut(const QKeySequence& shortcut); + bool unsetShortcut(); + + static bool error; +#ifndef Q_OS_MAC + static int ref; +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) + static QAbstractEventDispatcher::EventFilter prevEventFilter; + static bool eventFilter(void* message); +#else + virtual bool nativeEventFilter(const QByteArray & eventType, void * message, long * result); +#endif // QT_VERSION < QT_VERSION_CHECK(5,0,0) +#endif // Q_OS_MAC + + static void activateShortcut(quint32 nativeKey, quint32 nativeMods); + +private: + static quint32 nativeKeycode(Qt::Key keycode); + static quint32 nativeModifiers(Qt::KeyboardModifiers modifiers); + + static bool registerShortcut(quint32 nativeKey, quint32 nativeMods); + static bool unregisterShortcut(quint32 nativeKey, quint32 nativeMods); + + static QHash, QxtGlobalShortcut*> shortcuts; +}; + +#endif // QXTGLOBALSHORTCUT_P_H diff --git a/src/third-party/qxtglobalshortcut_win.cpp b/src/third-party/qxtglobalshortcut_win.cpp new file mode 100644 index 0000000..aee7934 --- /dev/null +++ b/src/third-party/qxtglobalshortcut_win.cpp @@ -0,0 +1,252 @@ +#include "qxtglobalshortcut_p.h" +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + +#include + + +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) +bool QxtGlobalShortcutPrivate::eventFilter(void* message) +{ +#else +bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, + void * message, long * result) +{ + Q_UNUSED(eventType); + Q_UNUSED(result); +#endif + MSG* msg = static_cast(message); + if (msg->message == WM_HOTKEY) + { + const quint32 keycode = HIWORD(msg->lParam); + const quint32 modifiers = LOWORD(msg->lParam); + activateShortcut(keycode, modifiers); + } + +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) + return prevEventFilter ? prevEventFilter(message) : false; +#else + return false; +#endif +} + + +quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) +{ + // MOD_ALT, MOD_CONTROL, (MOD_KEYUP), MOD_SHIFT, MOD_WIN + quint32 native = 0; + if (modifiers & Qt::ShiftModifier) + native |= MOD_SHIFT; + if (modifiers & Qt::ControlModifier) + native |= MOD_CONTROL; + if (modifiers & Qt::AltModifier) + native |= MOD_ALT; + if (modifiers & Qt::MetaModifier) + native |= MOD_WIN; + // TODO: resolve these? + //if (modifiers & Qt::KeypadModifier) + //if (modifiers & Qt::GroupSwitchModifier) + return native; +} + +quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) +{ + switch (key) + { + case Qt::Key_Escape: + return VK_ESCAPE; + case Qt::Key_Tab: + case Qt::Key_Backtab: + return VK_TAB; + case Qt::Key_Backspace: + return VK_BACK; + case Qt::Key_Return: + case Qt::Key_Enter: + return VK_RETURN; + case Qt::Key_Insert: + return VK_INSERT; + case Qt::Key_Delete: + return VK_DELETE; + case Qt::Key_Pause: + return VK_PAUSE; + case Qt::Key_Print: + return VK_PRINT; + case Qt::Key_Clear: + return VK_CLEAR; + case Qt::Key_Home: + return VK_HOME; + case Qt::Key_End: + return VK_END; + case Qt::Key_Left: + return VK_LEFT; + case Qt::Key_Up: + return VK_UP; + case Qt::Key_Right: + return VK_RIGHT; + case Qt::Key_Down: + return VK_DOWN; + case Qt::Key_PageUp: + return VK_PRIOR; + case Qt::Key_PageDown: + return VK_NEXT; + case Qt::Key_F1: + return VK_F1; + case Qt::Key_F2: + return VK_F2; + case Qt::Key_F3: + return VK_F3; + case Qt::Key_F4: + return VK_F4; + case Qt::Key_F5: + return VK_F5; + case Qt::Key_F6: + return VK_F6; + case Qt::Key_F7: + return VK_F7; + case Qt::Key_F8: + return VK_F8; + case Qt::Key_F9: + return VK_F9; + case Qt::Key_F10: + return VK_F10; + case Qt::Key_F11: + return VK_F11; + case Qt::Key_F12: + return VK_F12; + case Qt::Key_F13: + return VK_F13; + case Qt::Key_F14: + return VK_F14; + case Qt::Key_F15: + return VK_F15; + case Qt::Key_F16: + return VK_F16; + case Qt::Key_F17: + return VK_F17; + case Qt::Key_F18: + return VK_F18; + case Qt::Key_F19: + return VK_F19; + case Qt::Key_F20: + return VK_F20; + case Qt::Key_F21: + return VK_F21; + case Qt::Key_F22: + return VK_F22; + case Qt::Key_F23: + return VK_F23; + case Qt::Key_F24: + return VK_F24; + case Qt::Key_Space: + return VK_SPACE; + case Qt::Key_Asterisk: + return VK_MULTIPLY; + case Qt::Key_Plus: + return VK_ADD; + case Qt::Key_Comma: + return VK_SEPARATOR; + case Qt::Key_Minus: + return VK_SUBTRACT; + case Qt::Key_Slash: + return VK_DIVIDE; + case Qt::Key_MediaNext: + return VK_MEDIA_NEXT_TRACK; + case Qt::Key_MediaPrevious: + return VK_MEDIA_PREV_TRACK; + case Qt::Key_MediaPlay: + return VK_MEDIA_PLAY_PAUSE; + case Qt::Key_MediaStop: + return VK_MEDIA_STOP; + // couldn't find those in VK_* + //case Qt::Key_MediaLast: + //case Qt::Key_MediaRecord: + case Qt::Key_VolumeDown: + return VK_VOLUME_DOWN; + case Qt::Key_VolumeUp: + return VK_VOLUME_UP; + case Qt::Key_VolumeMute: + return VK_VOLUME_MUTE; + + // numbers + case Qt::Key_0: + case Qt::Key_1: + case Qt::Key_2: + case Qt::Key_3: + case Qt::Key_4: + case Qt::Key_5: + case Qt::Key_6: + case Qt::Key_7: + case Qt::Key_8: + case Qt::Key_9: + return key; + + // letters + case Qt::Key_A: + case Qt::Key_B: + case Qt::Key_C: + case Qt::Key_D: + case Qt::Key_E: + case Qt::Key_F: + case Qt::Key_G: + case Qt::Key_H: + case Qt::Key_I: + case Qt::Key_J: + case Qt::Key_K: + case Qt::Key_L: + case Qt::Key_M: + case Qt::Key_N: + case Qt::Key_O: + case Qt::Key_P: + case Qt::Key_Q: + case Qt::Key_R: + case Qt::Key_S: + case Qt::Key_T: + case Qt::Key_U: + case Qt::Key_V: + case Qt::Key_W: + case Qt::Key_X: + case Qt::Key_Y: + case Qt::Key_Z: + return key; + + default: + return 0; + } +} + +bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) +{ + return RegisterHotKey(0, nativeMods ^ nativeKey, nativeMods, nativeKey); +} + +bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) +{ + return UnregisterHotKey(0, nativeMods ^ nativeKey); +} diff --git a/src/third-party/qxtglobalshortcut_x11.cpp b/src/third-party/qxtglobalshortcut_x11.cpp new file mode 100644 index 0000000..87b1198 --- /dev/null +++ b/src/third-party/qxtglobalshortcut_x11.cpp @@ -0,0 +1,243 @@ +#include "qxtglobalshortcut_p.h" +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + +#include +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) +# include +#else +# include +# include +# include +#endif +#include + + +namespace { + +const QVector maskModifiers = QVector() + << 0 << Mod2Mask << LockMask << (Mod2Mask | LockMask); + +typedef int (*X11ErrorHandler)(Display *display, XErrorEvent *event); + +class QxtX11ErrorHandler { +public: + static bool error; + + static int qxtX11ErrorHandler(Display *display, XErrorEvent *event) + { + Q_UNUSED(display); + switch (event->error_code) + { + case BadAccess: + case BadValue: + case BadWindow: + if (event->request_code == 33 /* X_GrabKey */ || + event->request_code == 34 /* X_UngrabKey */) + { + error = true; + //TODO: + //char errstr[256]; + //XGetErrorText(dpy, err->error_code, errstr, 256); + } + } + return 0; + } + + QxtX11ErrorHandler() + { + error = false; + m_previousErrorHandler = XSetErrorHandler(qxtX11ErrorHandler); + } + + ~QxtX11ErrorHandler() + { + XSetErrorHandler(m_previousErrorHandler); + } + +private: + X11ErrorHandler m_previousErrorHandler; +}; + +bool QxtX11ErrorHandler::error = false; + +class QxtX11Data { +public: + QxtX11Data() + { +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) + m_display = QX11Info::display(); +#else + QPlatformNativeInterface *native = qApp->platformNativeInterface(); + void *display = native->nativeResourceForScreen(QByteArray("display"), + QGuiApplication::primaryScreen()); + m_display = reinterpret_cast(display); +#endif + } + + bool isValid() + { + return m_display != 0; + } + + Display *display() + { + Q_ASSERT(isValid()); + return m_display; + } + + Window rootWindow() + { + return DefaultRootWindow(display()); + } + + bool grabKey(quint32 keycode, quint32 modifiers, Window window) + { + QxtX11ErrorHandler errorHandler; + + for (int i = 0; !errorHandler.error && i < maskModifiers.size(); ++i) { + XGrabKey(display(), keycode, modifiers | maskModifiers[i], window, True, + GrabModeAsync, GrabModeAsync); + } + + if (errorHandler.error) { + ungrabKey(keycode, modifiers, window); + return false; + } + + return true; + } + + bool ungrabKey(quint32 keycode, quint32 modifiers, Window window) + { + QxtX11ErrorHandler errorHandler; + + foreach (quint32 maskMods, maskModifiers) { + XUngrabKey(display(), keycode, modifiers | maskMods, window); + } + + return !errorHandler.error; + } + +private: + Display *m_display; +}; + +} // namespace + +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) +bool QxtGlobalShortcutPrivate::eventFilter(void *message) +{ + XEvent *event = static_cast(message); + if (event->type == KeyPress) + { + XKeyEvent *key = reinterpret_cast(event); + unsigned int keycode = key->keycode; + unsigned int keystate = key->state; +#else +bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, + void *message, long *result) +{ + Q_UNUSED(result); + + xcb_key_press_event_t *kev = 0; + if (eventType == "xcb_generic_event_t") { + xcb_generic_event_t *ev = static_cast(message); + if ((ev->response_type & 127) == XCB_KEY_PRESS) + kev = static_cast(message); + } + + if (kev != 0) { + unsigned int keycode = kev->detail; + unsigned int keystate = 0; + if(kev->state & XCB_MOD_MASK_1) + keystate |= Mod1Mask; + if(kev->state & XCB_MOD_MASK_CONTROL) + keystate |= ControlMask; + if(kev->state & XCB_MOD_MASK_4) + keystate |= Mod4Mask; + if(kev->state & XCB_MOD_MASK_SHIFT) + keystate |= ShiftMask; +#endif + activateShortcut(keycode, + // Mod1Mask == Alt, Mod4Mask == Meta + keystate & (ShiftMask | ControlMask | Mod1Mask | Mod4Mask)); + } +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) + return prevEventFilter ? prevEventFilter(message) : false; +#else + return false; +#endif +} + +quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) +{ + // ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask + quint32 native = 0; + if (modifiers & Qt::ShiftModifier) + native |= ShiftMask; + if (modifiers & Qt::ControlModifier) + native |= ControlMask; + if (modifiers & Qt::AltModifier) + native |= Mod1Mask; + if (modifiers & Qt::MetaModifier) + native |= Mod4Mask; + + // TODO: resolve these? + //if (modifiers & Qt::MetaModifier) + //if (modifiers & Qt::KeypadModifier) + //if (modifiers & Qt::GroupSwitchModifier) + return native; +} + +quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) +{ + QxtX11Data x11; + if (!x11.isValid()) + return 0; + + KeySym keysym = XStringToKeysym(QKeySequence(key).toString().toLatin1().data()); + if (keysym == NoSymbol) + keysym = static_cast(key); + + return XKeysymToKeycode(x11.display(), keysym); +} + +bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) +{ + QxtX11Data x11; + return x11.isValid() && x11.grabKey(nativeKey, nativeMods, x11.rootWindow()); +} + +bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) +{ + QxtX11Data x11; + return x11.isValid() && x11.ungrabKey(nativeKey, nativeMods, x11.rootWindow()); +} diff --git a/src/translations/qterminal_cs.ts b/src/translations/qterminal_cs.ts new file mode 100644 index 0000000..5a0ef4e --- /dev/null +++ b/src/translations/qterminal_cs.ts @@ -0,0 +1,567 @@ + + + + + BookmarksWidget + + + Filter: + + + + + FontDialog + + + + Select Terminal Font + + + + + Font: + + + + + Size: + + + + + Preview + + + + + MainWindow + + + Close Tab + + + + + Split Terminal Horizontally + Rozdělit Terminál Horizontálně + + + + Split Terminal Vertically + + + + + Collapse Subterminal + + + + + Next Subterminal + + + + + Previous Subterminal + + + + + Next Tab + + + + + Bookmarks + + + + + Rename Session + + + + + Press "%1" to see the terminal. + + + + + Clear Current Tab + + + + + Previous Tab + + + + + Move Tab Left + + + + + Move Tab Right + + + + + Copy Selection + + + + + Paste Clipboard + + + + + Paste Selection + + + + + Zoom in + + + + + Zoom out + + + + + Zoom reset + + + + + Find... + + + + + Save Session + + + + + Load Session + + + + + Toggle Menu + + + + + New Tab + + + + + New Window + + + + + Hide Window Borders + + + + + Show Tab Bar + + + + + Bottom + + + + + Top + + + + + + Right + + + + + + Left + + + + + Tabs Layout + + + + + None + + + + + Scrollbar Layout + + + + + Exit QTerminal + + + + + Do not ask again + + + + + Are you sure you want to exit? + + + + + A lightweight multiplatform terminal emulator + + + + + PropertiesDialog + + + QTerminal Properties + + + + + Terminal Font + + + + + Look and Feel + + + + + + History + + + + + Emulation + + + + + Shortcuts + + + + + DropDown + + + + + Bookmarks + + + + + Font + + + + + &Set Font... + + + + + Note: only fixed width font are allowed to be used in terminal + + + + + Action after paste clipboard + + + + + Color Scheme: + + + + + GUI Style: + + + + + Scrollbar Position: + + + + + Show on start + + + + + Size + + + + + Height %: + + + + + Width %: + + + + + Shortcut: + + + + + Edit File Content + + + + + Use Bookmarks + + + + + Bookmark FIle: + + + + + Find... + + + + + You can specify your own bookmarks file location. It allows easy bookmark sharing with tools like OwnCloud or Dropbox. + + + + + Tabs Position: + + + + + &Application Transparency: + + + + + + % + + + + + Terminal Transparency: + + + + + &Highlight Current Terminal With Border + + + + + Ask for Window Closing Confirmation + + + + + Open New Sub-Terminals in Current Working Dir + + + + + Show Main Menu + + + + + Always Show Tabs + + + + + Limited to: + + + + + Unlimited + + + + + Emulation Type + + + + + Select emulation behaviour. It does not mean that for example "linux" has to be used only on Linux OS. Feel free to use it on Mac too etc.<p>Default is the failback type with minimal feature set. + + + + + Shortcut + + + + + Key + + + + + + System Default + + + + + Open or create bookmarks file + + + + + QObject + + + Local Bookmarks + + + + + Synchronized Bookmarks + + + + + TabWidget + + + + Shell No. %1 + + + + + Tab name + + + + + New tab name: + + + + + Close session + + + + + Rename session + + + + + TermWidgetHolder + + + Load Session + + + + + List of saved sessions: + + + + + TermWidgetImpl + + Split Terminal Horizontally + Rozdělit Terminál Horizontálně + + + + mainWindow + + + MainWindow + + + + + File + + + + + Actions + + + + + Help + + + + + View + + + + + Edit + + + + + &Quit + + + + + About... + + + + + About Qt... + + + + + &Preferences... + + + + diff --git a/src/translations/qterminal_de.ts b/src/translations/qterminal_de.ts new file mode 100644 index 0000000..5c6adf5 --- /dev/null +++ b/src/translations/qterminal_de.ts @@ -0,0 +1,603 @@ + + + + + BookmarksWidget + + + Filter: + Filter: + + + + FontDialog + + + + Select Terminal Font + Terminal-Schriftart wählen + + + + Font: + Schriftart: + + + + Size: + Größe: + + + + Preview + Vorschau + + + + MainWindow + + + Close Tab + Tab schließen + + + + Split Terminal Horizontally + Terminal horizontal teilen + + + + Split Terminal Vertically + Terminal vertikal teilen + + + + Collapse Subterminal + Unterterminal schließen + + + + Next Subterminal + Nächster Unterterminal + + + + Previous Subterminal + Voriger Unterterminal + + + + Next Tab + Nächster Tab + + + + Previous Tab + Voriger Tab + + + + Move Tab Left + Tab nach links verschieben + + + + Move Tab Right + Tab nach rechts verschieben + + + + Copy Selection + Textauswahl kopieren + + + + Paste Selection + Textauswahl einfügen + + + + Save Session + Sitzung speichern + + + + Load Session + Sitzung laden + + + + Bottom + Unten + + + + Top + Oben + + + + + Right + Rechts + + + + + Left + Links + + + + Tabs Layout + Anzeige Tableiste + + + + None + Keine + + + + Scrollbar Layout + Anzeige Bildlaufleiste + + + + Exit QTerminal + QTerminal beenden + + + + Do not ask again + Nicht erneut nachfragen + + + + Are you sure you want to exit? + Sind Sie sicher, dass Sie QTerminal beenden wollen? + + + + A lightweight multiplatform terminal emulator + Ein schlanker plattformunabhängiger Terminalemulator + + + + Bookmarks + Lesezeichen + + + + Rename Session + Sitzung umbenennen + + + + Press "%1" to see the terminal. + Tippen Sie "%1", um den Terminal zu sehen. + + + + Clear Current Tab + Aktuellen Tab leeren + + + + Paste Clipboard + Zwischenablage einfügen + + + + Zoom in + Vergrößern + + + + Zoom out + Verkleinern + + + + Zoom reset + Zurücksetzen + + + + Find... + Suchen... + + + + Toggle Menu + Menü ein-/ausblenden + + + + New Tab + Neuer Tab + + + + New Window + Neues Fenster + + + + Hide Window Borders + Fensterrahmen ausblenden + + + + Show Tab Bar + Tabzeile anzeigen + + + + PropertiesDialog + + + QTerminal Properties + QTerminal-Einstellungen + + + + Terminal Font + Terminalschrift + + + + Look and Feel + Aussehen + + + + + History + Historie + + + + Emulation + Emulation + + + + Shortcuts + Tastenkürzel + + + + Font + Schriftart + + + + &Set Font... + &Schriftart wählen... + + + + Color Scheme: + Farbschema: + + + + GUI Style: + GUI-Stil: + + + + Scrollbar Position: + Position der Bildlaufleiste: + + + + Tabs Position: + Position der Tabs: + + + + &Application Transparency: + &Transparenz der Anwendung: + + + + + % + % + + + + Terminal Transparency: + Transparenz des Terminals: + + + + Limited to: + Eingeschränkt auf: + + + + Unlimited + keine Einschränkung + + + + Emulation Type + Emulationsart + + + + Select emulation behaviour. It does not mean that for example "linux" has to be used only on Linux OS. Feel free to use it on Mac too etc.<p>Default is the failback type with minimal feature set. + Verhalten des Emulators wählen. Hinweis: Emulationsarten können auch unter anderen Systemen genutzt werden (z.B. "linux" unter OS X).<p>Die Standardemulation ist "default" mit minimalem Funktionsumfang. + + + + Shortcut + Tastenkürzel + + + + Key + Taste + + + + DropDown + Aufklappen + + + + Bookmarks + Lesezeichen + + + + Note: only fixed width font are allowed to be used in terminal + Anmerkung: nur Festbreit-Schriften können im Terminal verwendet werden. + + + + Action after paste clipboard + Aktion nach Einfügen aus der Zwischenablage + + + + &Highlight Current Terminal With Border + Aktuellen Terminal einrahmen + + + + Ask for Window Closing Confirmation + Beim Schließen eines Fensters nachfragen + + + + Open New Sub-Terminals in Current Working Dir + Neuen Unterterminal im aktuellen Verzeichnis öffnen + + + + Show Main Menu + Hauptmenü anzeigen + + + + Always Show Tabs + Tabs immer anzeigen + + + + Show on start + Beim Start anzeigen + + + + Size + Größe + + + + Height %: + Höhe in %: + + + + Width %: + Breite in %: + + + + Shortcut: + Tastenkürzel: + + + + Edit File Content + Datei bearbeiten + + + + Use Bookmarks + Lesezeichen verwenden + + + + Bookmark FIle: + Lesezeichendatei: + + + + Find... + Suchen... + + + + You can specify your own bookmarks file location. It allows easy bookmark sharing with tools like OwnCloud or Dropbox. + Sie können eine Datei für eigene Lesezeichen angeben. Das erlaubt einfachen Austausch mit Werkzeugen wie OwnCloud oder DropBox. + + + + + System Default + Systemstandard + + + + Open or create bookmarks file + Lesezeichendatei öffnen + + + + QObject + + + Local Bookmarks + Lokale Lesezeichen + + + + Synchronized Bookmarks + Synchronisierte Lesezeichen + + + + TabWidget + + + + Shell No. %1 + Shell Nr. %1 + + + + Tab name + Tabbezeichnung + + + + New tab name: + Neue Tabbezeichnung: + + + + Close session + Sitzung schließen + + + + Rename session + Sitzung umbenennen + + + + TermWidgetHolder + + + Load Session + Sitzung laden + + + + List of saved sessions: + Liste der gespeicherten Sitzungen: + + + + TermWidgetImpl + + Copy Selection + Textauswahl kopieren + + + Paste Clipboard + Zwischenablage einfügen + + + Paste Selection + Textauswahl einfügen + + + Zoom in + Vergrößern + + + Zoom out + Verkleinern + + + Zoom reset + Zurücksetzen + + + Clear Active Terminal + Aktiven Terminal leeren + + + Split Terminal Horizontally + Terminal horizontal teilen + + + Split Terminal Vertically + Terminal vertikal teilen + + + Collapse Subterminal + Unterterminal schließen + + + + mainWindow + + + Actions + Aktionen + + + + Help + Hilfe + + + + Edit + + + + + About... + Über... + + + + About Qt... + Über Qt... + + + + &Preferences... + &Einstellungen... + + + + MainWindow + + + + + File + Datei + + + + View + Ansicht + + + + &Quit + Beenden + + + diff --git a/src/translations/qterminal_es.ts b/src/translations/qterminal_es.ts new file mode 100644 index 0000000..4529d01 --- /dev/null +++ b/src/translations/qterminal_es.ts @@ -0,0 +1,627 @@ + + + + + BookmarksWidget + + + Filter: + Filtro: + + + + FontDialog + + + + Select Terminal Font + Selecciona fuente del terminal + + + + Font: + Fuente: + + + + Size: + Tamaño: + + + + Preview + Vista Previa + + + + MainWindow + + Add Tab + Añadir Pestaña + + + + Close Tab + Cerrar Pestaña + + + + Split Terminal Horizontally + Dividir terminal horizontalmente + + + + Split Terminal Vertically + Dividir terminal verticalmente + + + + Collapse Subterminal + Colapsar subterminal + + + + Next Subterminal + Subterminal siguiente + + + + Previous Subterminal + Subterminal previa + + + + Next Tab + Pestaña siguiente + + + + Bookmarks + Marcadores + + + + Rename Session + Renombrar Session + + + + Press "%1" to see the terminal. + Presiona "%1" para ver la terminal. + + + + Clear Current Tab + Limpiar pestaña actual + + + + Previous Tab + Pestaña previa + + + + Move Tab Left + Mover pestaña a izquierda + + + + Move Tab Right + Mover pestaña a derecha + + + + Copy Selection + Copiar selección + + + + Paste Clipboard + Pegar desde portapapeles + + + + Paste Selection + Pegar selección + + + + Zoom in + Acercar + + + + Zoom out + Alejar + + + + Zoom reset + Reestablecer zoom + + + + Find... + Buscar... + + + + Save Session + Guardar session + + + + Load Session + Cargar session + + + + Toggle Menu + + + + + New Tab + Nueva Pestaña + + + + New Window + Nueva Ventana + + + + Hide Window Borders + Ocultar bordes de ventana + + + + Show Tab Bar + Mostrar barra de pestañas + + + + Bottom + Abajo + + + + Top + Arriba + + + + + Right + Derecha + + + + + Left + Izquierda + + + + Tabs Layout + Layout Pestañas + + + + None + Ninguno + + + + Scrollbar Layout + Layout barra de desplazamiento + + + + Exit QTerminal + Salir de QTerminal + + + + Do not ask again + No volver a preguntar + + + + Are you sure you want to exit? + ¿Estás seguro que quieres salir? + + + + A lightweight multiplatform terminal emulator + Un emulador de terminal liviano multiplataforma + + + + PropertiesDialog + + + QTerminal Properties + Propiedades de QTerminal + + + + Terminal Font + Fuente de terminal + + + + Look and Feel + Apariencia + + + + + History + Historia + + + + Emulation + Emulación + + + + Shortcuts + Atajos + + + + DropDown + Desplegar + + + + Bookmarks + Marcadores + + + + Font + Fuente + + + + &Set Font... + &Definir fuente... + + + + Note: only fixed width font are allowed to be used in terminal + Nota: sólo está permitido usar fuentes de tamaño fijo en la terminal + + + + Action after paste clipboard + Acción después de pegar portapapeles + + + + Color Scheme: + Esquema de color: + + + + GUI Style: + Estilo de GUI: + + + + Scrollbar Position: + Posición de barra de dezplazamiento: + + + + Always Show Tabs + + + + + Show on start + Mostrar al inicio + + + + Size + Tamaño + + + + Height %: + Altura %: + + + + Width %: + Ancho %: + + + + Shortcut: + Atajo: + + + + Edit File Content + Editar contenido de archivo + + + + Use Bookmarks + Usar marcadores + + + + Bookmark FIle: + Archivo de marcadores: + + + + Find... + Buscar... + + + + You can specify your own bookmarks file location. It allows easy bookmark sharing with tools like OwnCloud or Dropbox. + Puedes especificar tu propia locación de archivo de marcadores. Permite facilmente compartir marcadores con herramientas como OwnCloud o Dropbox. + + + + Tabs Position: + Posición de pestaña: + + + + &Application Transparency: + &Transparencia de aplicación: + + + + + % + % + + + + Terminal Transparency: + Transparencia de la terminal: + + + + &Highlight Current Terminal With Border + &Resaltar la terminal actual con borde + + + + Ask for Window Closing Confirmation + Preguntar por confirmación de cierre de ventana + + + + Open New Sub-Terminals in Current Working Dir + Abrir nueva subterminal en la actual dirección de trabajo + + + + Show Main Menu + Mostrar menu principal + + + + Limited to: + Limitada: + + + + Unlimited + Ilimitada + + + + Emulation Type + Tipo de emulación + + + + Select emulation behaviour. It does not mean that for example "linux" has to be used only on Linux OS. Feel free to use it on Mac too etc.<p>Default is the failback type with minimal feature set. + Seleccionar comportamiento de emulación. No significa que, por ejemplo, «linux» puede ser usada sólo en Linux SO. Sentite libre de usar esta en Mac, etc. + + + + Shortcut + Acción + + + + Key + Acceso rápido + + + No move + No mover + + + Move start + Mover al inicio + + + Move end + Mover al final + + + + + System Default + Por defecto del sistema + + + + Open or create bookmarks file + Abrir o crear archivo de marcadores + + + Select Terminal Font + Seleccionar fuente de la terminal + + + + QObject + + + Local Bookmarks + Marcadores locales + + + + Synchronized Bookmarks + Marcadores sincronizados + + + + TabWidget + + + + Shell No. %1 + Shell N° %1 + + + + Tab name + Nombre de pestaña + + + + New tab name: + Nuevo nombre de pestaña: + + + + Close session + Cerrar session + + + + Rename session + Renombrar session + + + + TermWidgetHolder + + + Load Session + Cargar session + + + + List of saved sessions: + Lista de sessiones guardadas: + + + + TermWidgetImpl + + Copy Selection + Copiar selección + + + Paste Clipboard + Pegar desde portapapeles + + + Paste Selection + Pegar selección + + + Zoom in + Acercar + + + Zoom out + Alejar + + + Zoom reset + Reestablecer zoom + + + Split Terminal Horizontally + Dividir terminal horizontalmente + + + Split Terminal Vertically + Dividir terminal verticalmente + + + Collapse Subterminal + Colapsar subterminal + + + + mainWindow + + + MainWindow + Ventana principal + + + + File + Archivo + + + + Actions + Acciones + + + + Help + Ayuda + + + + View + Vista + + + + Edit + + + + + &Quit + &Salir + + + &Window + &Ventana + + + + About... + Acerca de... + + + + About Qt... + Acerca de QT... + + + + &Preferences... + &Preferencias... + + + &Quit... + &Salir... + + + diff --git a/src/translations/qterminal_et.ts b/src/translations/qterminal_et.ts new file mode 100644 index 0000000..238b670 --- /dev/null +++ b/src/translations/qterminal_et.ts @@ -0,0 +1,607 @@ + + + + + BookmarksWidget + + + Filter: + + + + + FontDialog + + + + Select Terminal Font + Vali terminali font + + + + Font: + + + + + Size: + + + + + Preview + + + + + MainWindow + + Add Tab + Lisa kaart + + + + Close Tab + Sulge kaart + + + + Split Terminal Horizontally + Poolita terminal horisontaalselt + + + + Split Terminal Vertically + Poolita terminal vertikaalselt + + + + Collapse Subterminal + Ahenda alamterminal + + + + Next Subterminal + Järgmine alamterminal + + + + Previous Subterminal + Eelmine alamterminal + + + + Next Tab + Järgmine kaart + + + + Bookmarks + + + + + Rename Session + + + + + Press "%1" to see the terminal. + + + + + Clear Current Tab + + + + + Previous Tab + Eelmine kaart + + + + Move Tab Left + Liiguta kaart vasakule + + + + Move Tab Right + Liiguta kaart paremale + + + + Copy Selection + Kopeeri valik + + + + Paste Clipboard + + + + + Paste Selection + Aseta valik + + + + Zoom in + + + + + Zoom out + + + + + Zoom reset + + + + + Find... + + + + + Save Session + Salvesta seanss + + + + Load Session + Lae seanss + + + + Toggle Menu + + + + + New Tab + + + + + New Window + + + + + Hide Window Borders + + + + + Show Tab Bar + + + + Toggle Borderless + Lülita ääristeta režiimile + + + Toggle TabBar + Lülita kaardiriba + + + + Bottom + All + + + + Top + Ülal + + + + + Right + Paremal + + + + + Left + Vasakul + + + + Tabs Layout + Kaartide paigutus + + + + None + Puudub + + + + Scrollbar Layout + Kerimisriba paigutus + + + + Exit QTerminal + Lõpeta Qterminali töö + + + + Do not ask again + Ära küsi uuesti + + + + Are you sure you want to exit? + Soovid sa tõesti väljuda? + + + + A lightweight multiplatform terminal emulator + Ressursisäästlik multiplatvormne terminaliemulaator + + + + PropertiesDialog + + + QTerminal Properties + QTerminali omadused + + + + Terminal Font + Terminali font + + + + Look and Feel + Tööilme + + + + + History + Ajalugu + + + + Emulation + Emuleering + + + + Shortcuts + Otseteed + + + + DropDown + + + + + Bookmarks + + + + + Font + Font + + + + &Set Font... + &Määra font... + + + + Note: only fixed width font are allowed to be used in terminal + + + + + Action after paste clipboard + + + + + Color Scheme: + Värviskeem: + + + + GUI Style: + GUI stiil: + + + + Scrollbar Position: + Kerimisriba asukoht: + + + + Show on start + + + + + Size + + + + + Height %: + + + + + Width %: + + + + + Shortcut: + + + + + Edit File Content + + + + + Use Bookmarks + + + + + Bookmark FIle: + + + + + Find... + + + + + You can specify your own bookmarks file location. It allows easy bookmark sharing with tools like OwnCloud or Dropbox. + + + + + Tabs Position: + Kaartide asukoht: + + + + &Application Transparency: + &Rakenduse läbipaistvus: + + + + + % + % + + + + Terminal Transparency: + Terminali läbipaistvus: + + + + &Highlight Current Terminal With Border + + + + + Ask for Window Closing Confirmation + + + + + Open New Sub-Terminals in Current Working Dir + + + + + Show Main Menu + + + + + Always Show Tabs + + + + + Limited to: + Piiratud kuni: + + + + Unlimited + Piiramatu + + + + Emulation Type + Emuleeringu tüüp + + + + Select emulation behaviour. It does not mean that for example "linux" has to be used only on Linux OS. Feel free to use it on Mac too etc.<p>Default is the failback type with minimal feature set. + Vali emuleeringu käitumine. See ei tähenda, et näiteks "linux" tohib olla kasutusel vaid Linux OS puhul. Kasuta seda vabalt ka Mac'l jne.<p>Vaikimisi varuvariant on minimaalsete võimalustega. + + + + Shortcut + Otsetee + + + + Key + Klahv + + + + + System Default + Süsteemne vaikeväärtus + + + + Open or create bookmarks file + + + + Select Terminal Font + Vali terminali font + + + + QObject + + + Local Bookmarks + + + + + Synchronized Bookmarks + + + + + TabWidget + + + + Shell No. %1 + Shell No. %1 + + + + Tab name + Kaardi nimi + + + + New tab name: + Kaardi uus nimi: + + + + Close session + Sulge seanss + + + + Rename session + Nimeta seanss ümber + + + + TermWidgetHolder + + + Load Session + Lae seanss + + + + List of saved sessions: + Salvestatud seansside nimekiri: + + + + TermWidgetImpl + + Copy Selection + Kopeeri valik + + + Paste Selection + Aseta valik + + + Split Terminal Horizontally + Poolita terminal horisontaalselt + + + Split Terminal Vertically + Poolita terminal vertikaalselt + + + Collapse Subterminal + Ahenda alamterminal + + + + mainWindow + + + MainWindow + PeaAken + + + + File + + + + + Actions + Tegevused + + + + Help + Abi + + + + View + + + + + Edit + + + + + &Quit + + + + &Window + &Aken + + + + About... + QTerminali info... + + + + About Qt... + Qt info... + + + + &Preferences... + &Seadistused... + + + &Quit... + &Välju... + + + diff --git a/src/translations/qterminal_it.ts b/src/translations/qterminal_it.ts new file mode 100644 index 0000000..633105a --- /dev/null +++ b/src/translations/qterminal_it.ts @@ -0,0 +1,603 @@ + + + + + BookmarksWidget + + + Filter: + + + + + FontDialog + + + + Select Terminal Font + Seleziona Carattere Terminale + + + + Font: + + + + + Size: + + + + + Preview + + + + + MainWindow + + Add Tab + Aggiungi Tab + + + + Close Tab + Chiudi Tab + + + + Split Terminal Horizontally + Dividi Terminale Orizzontalmente + + + + Split Terminal Vertically + Dividi Terminale Verticalmente + + + + Collapse Subterminal + Collassa Sottoterminale + + + + Next Subterminal + Sottoterminale Successivo + + + + Previous Subterminal + Sottoterminale Precedente + + + + Next Tab + Tab Successivo + + + + Bookmarks + + + + + Rename Session + + + + + Press "%1" to see the terminal. + + + + + Clear Current Tab + + + + + Previous Tab + Tab Precedente + + + + Move Tab Left + Sposta Tab a Sinistra + + + + Move Tab Right + Sposta Tab a Destra + + + + Copy Selection + Copia Selezione + + + + Paste Clipboard + + + + + Paste Selection + Incolla Selezione + + + + Zoom in + + + + + Zoom out + + + + + Zoom reset + + + + + Find... + + + + + Save Session + Salva Sessione + + + + Load Session + Carica Sessione + + + + Toggle Menu + + + + + New Tab + + + + + New Window + + + + + Hide Window Borders + + + + + Show Tab Bar + + + + Toggle Borderless + Toggle Senzabordi + + + + Bottom + Basso + + + + Top + Alto + + + + + Right + Destra + + + + + Left + Sinistra + + + + Tabs Layout + Layout Tabs + + + + None + Nessuno + + + + Scrollbar Layout + Layout Barra di scorrimento + + + + Exit QTerminal + Esci da QTerminal + + + + Do not ask again + Non chiedermelo più + + + + Are you sure you want to exit? + Sei sicuro di voler uscire? + + + + A lightweight multiplatform terminal emulator + Un emulatore di terminale multipiattaforma e leggero + + + + PropertiesDialog + + + QTerminal Properties + Proprietà QTerminal + + + + Terminal Font + Caratteri Terminale + + + + Look and Feel + Aspetto + + + + + History + Storia + + + + Emulation + Emulazione + + + + Shortcuts + Scorciatoie + + + + DropDown + + + + + Bookmarks + + + + + Font + Caratteri + + + + &Set Font... + &Imposta carattere... + + + + Note: only fixed width font are allowed to be used in terminal + + + + + Action after paste clipboard + + + + + Color Scheme: + Schema Colore: + + + + GUI Style: + Stile GUI: + + + + Scrollbar Position: + Posizione Barra di Scorrimento: + + + + Show on start + + + + + Size + + + + + Height %: + + + + + Width %: + + + + + Shortcut: + + + + + Edit File Content + + + + + Use Bookmarks + + + + + Bookmark FIle: + + + + + Find... + + + + + You can specify your own bookmarks file location. It allows easy bookmark sharing with tools like OwnCloud or Dropbox. + + + + + Tabs Position: + Posizione Tabs: + + + + &Application Transparency: + &Trasparenza Applicazione: + + + + + % + % + + + + Terminal Transparency: + Trasparenza Terminale: + + + + &Highlight Current Terminal With Border + + + + + Ask for Window Closing Confirmation + + + + + Open New Sub-Terminals in Current Working Dir + + + + + Show Main Menu + + + + + Always Show Tabs + + + + + Limited to: + Limitato a: + + + + Unlimited + Illimitato + + + + Emulation Type + Tipo Emulazione + + + + Select emulation behaviour. It does not mean that for example "linux" has to be used only on Linux OS. Feel free to use it on Mac too etc.<p>Default is the failback type with minimal feature set. + Seleziona comportamento emulazione. Non significa che per esempio "linux" deve essere utilizzato solo su SO Linux. Sentiti libero di usarlo anche su Mac ecc.<p>L'impostazione di base è quella più sicura con un set minimo di proprietà. + + + + Shortcut + Scorciatoia + + + + Key + Chiave + + + + + System Default + + + + + Open or create bookmarks file + + + + Select Terminal Font + Seleziona Carattere Terminale + + + + QObject + + + Local Bookmarks + + + + + Synchronized Bookmarks + + + + + TabWidget + + + + Shell No. %1 + Shell N° %1 + + + + Tab name + Nome tab + + + + New tab name: + Nuovo nome tab: + + + + Close session + Chiudi sessione + + + + Rename session + Rinomina sessione + + + + TermWidgetHolder + + + Load Session + Carica Sessione + + + + List of saved sessions: + Lista delle sessioni salvate: + + + + TermWidgetImpl + + Copy Selection + Copia Selezione + + + Paste Selection + Incolla Selezione + + + Split Terminal Horizontally + Dividi Terminale Orizzontalmente + + + Split Terminal Vertically + Dividi Terminale Verticalmente + + + Collapse Subterminal + Collassa Sottoterminale + + + + mainWindow + + + MainWindow + + + + + File + + + + + Actions + Azioni + + + + Help + Aiuto + + + + View + + + + + Edit + + + + + &Quit + + + + &Window + &Finestra + + + + About... + + + + + About Qt... + + + + + &Preferences... + &Preferenze... + + + &Quit... + &Chiudi... + + + diff --git a/src/translations/qterminal_ru.ts b/src/translations/qterminal_ru.ts new file mode 100644 index 0000000..0fad9cd --- /dev/null +++ b/src/translations/qterminal_ru.ts @@ -0,0 +1,623 @@ + + + + + BookmarksWidget + + + Filter: + Фильтр: + + + + FontDialog + + + + Select Terminal Font + Выбрать шрифт терминала + + + + Font: + Шрифт: + + + + Size: + Кегль: + + + + Preview + Предпросмотр + + + + MainWindow + + Add Tab + Новая вкладка + + + + Close Tab + Закрыть вкладку + + + + Split Terminal Horizontally + Разделить терминал по горизонтали + + + + Split Terminal Vertically + Разделить терминал по вертикали + + + + Collapse Subterminal + Закрыть подтерминал + + + + Next Subterminal + Следующий подтерминал + + + + Previous Subterminal + Предыдущий подтерминал + + + + Next Tab + Следующая вкладка + + + + Bookmarks + Закладки + + + + Rename Session + Переименовать сессию + + + + Press "%1" to see the terminal. + Нажмите "%1" чтобы увидеть терминал. + + + + Clear Current Tab + Очистить текущую вкладку + + + + Previous Tab + Предыдущая вкладка + + + + Move Tab Left + Сдвинуть вкладку влево + + + + Move Tab Right + Сдвинуть вкладку вправо + + + + Copy Selection + Скопировать выделенное + + + + Paste Clipboard + Вставить из буфера + + + + Paste Selection + Вставить выделенное + + + + Zoom in + Увеличить + + + + Zoom out + Уменьшить + + + + Zoom reset + Сбросить увеличение + + + + Find... + Найти... + + + + Save Session + Сохранить сессию + + + + Load Session + Загрузить сессию + + + + Toggle Menu + Показать строку меню + + + + New Tab + Новая вкладка + + + + New Window + Новое окно + + + + Hide Window Borders + Спрятать рамку окна + + + + Show Tab Bar + Показать панель вкладок + + + Toggle Borderless + Без рамки + + + Toggle TabBar + Без панели вкладок + + + + Bottom + Снизу + + + + Top + Сверху + + + + + Right + Справа + + + + + Left + Слева + + + + Tabs Layout + Расположение вкладок + + + + None + Убрать + + + + Scrollbar Layout + Расположение полосы прокрутки + + + + Exit QTerminal + Выйти из QTerminal + + + + Do not ask again + Не справшивать снова + + + + Are you sure you want to exit? + Вы уверены, что хотите выйти? + + + + A lightweight multiplatform terminal emulator + Лёгкий мультиплатформенный эмулятор терминала + + + + PropertiesDialog + + + QTerminal Properties + Настройки QTerminal + + + + Terminal Font + Шрифт терминала + + + + Look and Feel + Внешний вид + + + + + History + История + + + + Emulation + Эмуляция + + + + Shortcuts + Сочетания клавиш + + + + DropDown + Выпадающий + + + + Bookmarks + Закладки + + + + Font + Шрифт + + + + &Set Font... + &Выбрать шрифт... + + + + Note: only fixed width font are allowed to be used in terminal + Заметка: для использования в терминале разрешены только шрифты фиксированной ширины + + + + Action after paste clipboard + Действие после вставки из буфера + + + + Color Scheme: + Цветовая схема: + + + + GUI Style: + Стиль GUI: + + + + Scrollbar Position: + Расположение полосы прокрутки: + + + + Always Show Tabs + Всегда показывать вкладки + + + + Show on start + Показать при запуске + + + + Size + Размер + + + + Height %: + Высота %: + + + + Width %: + Ширина %: + + + + Shortcut: + Сочетание клавиш: + + + + Edit File Content + Изменить содержимое файла + + + + Use Bookmarks + Использовать закладки + + + + Bookmark FIle: + Файл закладок: + + + + Find... + Найти... + + + + You can specify your own bookmarks file location. It allows easy bookmark sharing with tools like OwnCloud or Dropbox. + Вы можете выбрать ваше собственное место для хранения закладок. Это позволит легко делиться закладками с помощью таких инструментов как OwnCloud или Dropbox. + + + + Tabs Position: + Расположение вкладок: + + + + &Application Transparency: + &Прозрачность приложения: + + + + + % + % + + + + Terminal Transparency: + Прозрачность терминала: + + + + &Highlight Current Terminal With Border + &Выделять текущий терминал границами + + + + Ask for Window Closing Confirmation + Подтверждать закрыте окна + + + + Open New Sub-Terminals in Current Working Dir + Открыть новый подтерминал в текущей папке + + + + Show Main Menu + Показать главное меню + + + + Limited to: + Ограничение: + + + + Unlimited + Без ограничения + + + + Emulation Type + Тип эмуляции + + + + Select emulation behaviour. It does not mean that for example "linux" has to be used only on Linux OS. Feel free to use it on Mac too etc.<p>Default is the failback type with minimal feature set. + Выбрать вид эмуляции. Это не означает, что, например, «linux» должно быть использовано только в ОС Linux. Вы можете использовать его на Mac и др.<p>По умолчанию — это запасной режим с минимальным набором функций. + + + + Shortcut + Сочетание клавиш + + + + Key + Клавиши + + + + + System Default + Системный + + + + Open or create bookmarks file + Открыть или создать файл закладок + + + Select Terminal Font + Выбрать шрифт терминала + + + + QObject + + + Local Bookmarks + Локальные закладки + + + + Synchronized Bookmarks + Синхронизированные закладки + + + + TabWidget + + + + Shell No. %1 + Оболочка № %1 + + + + Tab name + Имя вкладки + + + + New tab name: + Имя новой вкладки: + + + + Close session + Закрыть сессию + + + + Rename session + Переименовать сессию + + + + TermWidgetHolder + + + Load Session + Загрузить сессию + + + + List of saved sessions: + Список сохранённых сессий: + + + + TermWidgetImpl + + Copy Selection + Копировать выделение + + + Paste Clipboard + Вставить из буфера + + + Paste Selection + Вставить выделение + + + Zoom in + Увеличить + + + Zoom out + Уменьшить + + + Zoom reset + Сбросить увеличение + + + Split Terminal Horizontally + Разделить терминал по горизонтали + + + Split Terminal Vertically + Разделить терминал по вертикали + + + Collapse Subterminal + Закрыть подтерминал + + + + mainWindow + + + MainWindow + Главное окно + + + + File + Файл + + + + Actions + Действия + + + + Help + Помощь + + + + View + Вид + + + + Edit + Правка + + + + &Quit + &Выход + + + &Window + &Окно + + + + About... + О программе... + + + + About Qt... + О QT... + + + + &Preferences... + &Настройки... + + + &Quit... + &Выйти... + + +