commit b23ed87b872c6c773210b7e8ff6456d9ce2f407c Author: nowrep Date: Wed Mar 2 16:57:41 2011 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..a370d3289 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +build +DEBIAN +tools +src0.9.4 +src0.9.5 +src0.9.6 +*.deb +*.pro.user diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 000000000..27d51ef84 --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +nowrep diff --git a/BUILDING b/BUILDING new file mode 100644 index 000000000..0a328d196 --- /dev/null +++ b/BUILDING @@ -0,0 +1,16 @@ +####################### +## Building QupZilla ## +####################### + +in src/ folder: + qmake QupZilla.pro + make (unix) or nmake (Windows) +compiled binary is moved to bin folder + +Windows: + execute binary from bin folder + +Unix + move all folders (data, locale, plugins) to /usr/share/qupzilla + move binary to /usr/bin + execute binary here diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 000000000..d7e8ee6db --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,159 @@ +********************************************************************* +********************************************************************* +The QupZilla application itself is licensed under following licension +if it is not explicitly defined in source file or in exceptions bellow +********************************************************************* +********************************************************************* + +QupZilla - very fast web browser based on WebKit +Copyright (C) 2010-2011 nowrep + +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 3 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, see . + +****************************************************************** +****************************************************************** +Some files in 3rdparty/ folder are under different licenses + +----------------------------------------------------------- + lineedit.h, lineedit.cpp, squeezelabel.h, squeezelabel.cpp: +----------------------------------------------------------- +* Copyright (c) 2008 - 2009, Benjamin C. Meyer +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. 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. +* 3. Neither the name of the Benjamin Meyer 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 REGENTS 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 THE REGENTS OR CONTRIBUTORS 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. + +----------------------------------------------------------------------------- + qtlocalpeer.h, qtlocalpeer.cpp, qtsingleapplication.h, qtsingleapplication.cpp, + qtlockedfile.h, qtlockedfile_unix.cpp, qtlockedfile_win.cpp: +----------------------------------------------------------------------------- +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact Nokia at qt-info@nokia.com. +** +--------------------------------------------------------------------------- + Files clicktoflash.cpp and clicktoflash.h: +--------------------------------------------------------------------------- +/* ============================================================ +* +* Copyright (C) 2009 by Benjamin C. Meyer +* Copyright (C) 2010 by Matthieu Gicquel +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* 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, see . +* +* ============================================================ */ + +----------------------------------------------------------------------------- + Files ecwin7.cpp and ecwin7.h: +--------------------------------------------------------------------------- +/* EcWin7 - Support library for integrating Windows 7 taskbar features + * into any Qt application + * Copyright (C) 2010 Emanuele Colombo + * + * 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. + */ + +----------------------------------------------------------------------------- + Files qtwin.cpp and qtwin.h are used from + http://labs.qt.nokia.com/2009/09/15/using-blur-behind-on-windows/ +----------------------------------------------------------------------------- + In application are used also some icons from Faenza icon set, which are + licensed under the GNU/GPL license. + More info at http://tiheum.deviantart.com/art/Faenza-Icons-173323228 +----------------------------------------------------------------------------- diff --git a/GPLv3 b/GPLv3 new file mode 100644 index 000000000..10926e87f --- /dev/null +++ b/GPLv3 @@ -0,0 +1,675 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. 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 +them 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 prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. 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. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey 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; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + 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. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +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. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + 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 +state 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 3 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, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program 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, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU 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. But first, please read +. + diff --git a/README b/README new file mode 100644 index 000000000..b032ef0f3 --- /dev/null +++ b/README @@ -0,0 +1,9 @@ +################################# +## QUPZILLA - WEB BROWSER ## +################################# +Version: 0.9.7 + +QupZilla is new and very fast browser based on WebKit core http://www.webkit.org +Written in Qt Framework http://qt.nokia.com + +More informations at http://www.qupzilla.ic.cz (Czech only) diff --git a/bin/data/default/profiles/default/background.png b/bin/data/default/profiles/default/background.png new file mode 100644 index 000000000..5678d984a Binary files /dev/null and b/bin/data/default/profiles/default/background.png differ diff --git a/bin/data/default/profiles/default/browsedata.db b/bin/data/default/profiles/default/browsedata.db new file mode 100644 index 000000000..80497c3c7 Binary files /dev/null and b/bin/data/default/profiles/default/browsedata.db differ diff --git a/bin/data/default/profiles/profiles.ini b/bin/data/default/profiles/profiles.ini new file mode 100644 index 000000000..2baff5758 --- /dev/null +++ b/bin/data/default/profiles/profiles.ini @@ -0,0 +1,2 @@ +[Profiles] +startProfile="default" diff --git a/bin/locale/cs_CZ.qm b/bin/locale/cs_CZ.qm new file mode 100644 index 000000000..f494f1ca0 Binary files /dev/null and b/bin/locale/cs_CZ.qm differ diff --git a/bin/locale/qt_cs.qm b/bin/locale/qt_cs.qm new file mode 100644 index 000000000..58ebb543d Binary files /dev/null and b/bin/locale/qt_cs.qm differ diff --git a/bin/locale/qt_sk.qm b/bin/locale/qt_sk.qm new file mode 100644 index 000000000..2664279cf Binary files /dev/null and b/bin/locale/qt_sk.qm differ diff --git a/bin/locale/sk_SK.qm b/bin/locale/sk_SK.qm new file mode 100644 index 000000000..8a8b29026 Binary files /dev/null and b/bin/locale/sk_SK.qm differ diff --git a/plugins/TestPlugin/.gitignore b/plugins/TestPlugin/.gitignore new file mode 100644 index 000000000..378eac25d --- /dev/null +++ b/plugins/TestPlugin/.gitignore @@ -0,0 +1 @@ +build diff --git a/plugins/TestPlugin/cs_CZ.ts b/plugins/TestPlugin/cs_CZ.ts new file mode 100644 index 000000000..878a4f95e --- /dev/null +++ b/plugins/TestPlugin/cs_CZ.ts @@ -0,0 +1,37 @@ + + + + + TestPlugin + + + Example Plugin + Příkladový doplněk + + + + Example minimal plugin + Ukázkový minimální doplněk + + + + Very simple minimal plugin example + Velice jednoduchý minimální doplněk + + + + My first plugin action + Moje první akce z doplňku + + + + Hello + Ahoj + + + + First plugin action works :-) + První akce funguje :-) + + + diff --git a/plugins/TestPlugin/sk_SK.ts b/plugins/TestPlugin/sk_SK.ts new file mode 100644 index 000000000..5fdca9835 --- /dev/null +++ b/plugins/TestPlugin/sk_SK.ts @@ -0,0 +1,37 @@ + + + + + TestPlugin + + + Example Plugin + Ukázkovy doplnek + + + + Example minimal plugin + Ukázkovy minimálny doplnek + + + + Very simple minimal plugin example + Vel'mi jednoduchy minimálny doplnek + + + + My first plugin action + Moje první akce z doplnku + + + + Hello + Ahoj + + + + First plugin action works :-) + První doplnek funguje :-) + + + diff --git a/plugins/TestPlugin/src/TestPlugin.pro b/plugins/TestPlugin/src/TestPlugin.pro new file mode 100644 index 000000000..34533be62 --- /dev/null +++ b/plugins/TestPlugin/src/TestPlugin.pro @@ -0,0 +1,21 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2011-02-13T10:23:13 +# +#------------------------------------------------- +QT += network webkit + +TEMPLATE = lib + +CONFIG += plugin + +TARGET = ExamplePlugin + +DESTDIR = ../../../bin/plugins + +SOURCES += testplugin.cpp + +HEADERS += testplugin.h + +RESOURCES += \ + data.qrc diff --git a/plugins/TestPlugin/src/cs_CZ.qm b/plugins/TestPlugin/src/cs_CZ.qm new file mode 100644 index 000000000..4bb57ebfd Binary files /dev/null and b/plugins/TestPlugin/src/cs_CZ.qm differ diff --git a/plugins/TestPlugin/src/data.qrc b/plugins/TestPlugin/src/data.qrc new file mode 100644 index 000000000..55e60431e --- /dev/null +++ b/plugins/TestPlugin/src/data.qrc @@ -0,0 +1,7 @@ + + + cs_CZ.qm + qupzilla.png + sk_SK.qm + + diff --git a/plugins/TestPlugin/src/sk_SK.qm b/plugins/TestPlugin/src/sk_SK.qm new file mode 100644 index 000000000..f50f1a816 Binary files /dev/null and b/plugins/TestPlugin/src/sk_SK.qm differ diff --git a/plugins/TestPlugin/src/testplugin.cpp b/plugins/TestPlugin/src/testplugin.cpp new file mode 100644 index 000000000..440cdf895 --- /dev/null +++ b/plugins/TestPlugin/src/testplugin.cpp @@ -0,0 +1,68 @@ +#include "testplugin.h" + +void TestPlugin::init(QString sPath) +{ + settingsPath = sPath; + //This function is called right after plugin is loaded + qDebug() << __FUNCTION__ << "called"; +} + +bool TestPlugin::testPlugin() +{ + //This function is loaded right after init() + //There should be some testing if plugin is loaded correctly + //If this function returns false, plugin is automatically unloaded + + return true; +} + +QTranslator* TestPlugin::getTranslator(QString locale) +{ + QTranslator* translator = new QTranslator(); + translator->load(":/"+locale); + return translator; +} + +void TestPlugin::showSettings() +{ + QWidget* widget = new QWidget(); + new QLabel("Example Plugin v0.0.1", widget); + widget->resize(200,200); + widget->setAttribute(Qt::WA_DeleteOnClose); + widget->setWindowModality(Qt::WindowModal); //As the preferences window is modal too + widget->setWindowTitle("Example Plugin Settings"); + widget->setWindowIcon(pluginIcon()); + widget->show(); +} + +void TestPlugin::populateWebViewMenu(QMenu *menu, QWebView *view, QWebHitTestResult r) +{ + Q_UNUSED(view) + QString title; + if (!r.imageUrl().isEmpty()) + title += " on image"; + if (!r.linkUrl().isEmpty()) + title += " on link"; + QWebElement element = r.element(); + if (!element.isNull() && (element.tagName().toLower() == "input" || element.tagName().toLower() == "textarea")) + title += " on input"; + menu->addAction(tr("My first plugin action") + title, this, SLOT(actionSlot())); +} + +void TestPlugin::populateHelpMenu(QMenu *menu) +{ + menu->addAction(tr("My first plugin action"), this, SLOT(actionSlot())); +} + +void TestPlugin::populateToolsMenu(QMenu *menu) +{ + menu->addAction(tr("My first plugin action"), this, SLOT(actionSlot())); +} + +void TestPlugin::actionSlot() +{ + QMessageBox::information(0, tr("Hello"), tr("First plugin action works :-)")); +} + +//Export plugin macro +Q_EXPORT_PLUGIN2(ExamplePlugin, TestPlugin) diff --git a/plugins/TestPlugin/src/testplugin.h b/plugins/TestPlugin/src/testplugin.h new file mode 100644 index 000000000..c6fa093bb --- /dev/null +++ b/plugins/TestPlugin/src/testplugin.h @@ -0,0 +1,47 @@ +#ifndef TESTPLUGIN_H +#define TESTPLUGIN_H + +//Include actual plugininterface.h for your version of QupZilla +//This file is available to download at QupZilla website + +#include "../../../src/plugins/plugininterface.h" + + +//For clean plugin directory, please build necessary files into +//plugin in .qrc data files + +#include +#include +#include +#include + +class TestPlugin : public QObject, public PluginInterface +{ + Q_OBJECT + Q_INTERFACES(PluginInterface) + +public: + QString pluginName() { return tr("Example Plugin"); } + QString pluginInfo() { return tr("Example minimal plugin"); } + QString pluginDescription() { return tr("Very simple minimal plugin example"); } + QString pluginVersion() { return "0.0.1"; } + QString pluginAuthor() { return "nowrep "; } + void init(QString sPath); + bool testPlugin(); + + QTranslator* getTranslator(QString locale); + QIcon pluginIcon() { return QIcon(":/qupzilla.png"); } + bool hasSettings() { return true; } + void showSettings(); + + void populateWebViewMenu(QMenu *menu, QWebView *view, QWebHitTestResult r); + void populateHelpMenu(QMenu *menu); + void populateToolsMenu(QMenu *menu); + +private slots: + void actionSlot(); +private: + QString settingsPath; +}; + +#endif // TESTPLUGIN_H diff --git a/src/3rdparty/ecwin7.cpp b/src/3rdparty/ecwin7.cpp new file mode 100644 index 000000000..76755444b --- /dev/null +++ b/src/3rdparty/ecwin7.cpp @@ -0,0 +1,96 @@ +/* EcWin7 - Support library for integrating Windows 7 taskbar features + * into any Qt application + * Copyright (C) 2010 Emanuele Colombo + * + * 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 "ecwin7.h" + +// Windows only definitions +#ifdef Q_WS_WIN +DEFINE_GUID(CLSID_TaskbarList,0x56fdf344,0xfd6d,0x11d0,0x95,0x8a,0x0,0x60,0x97,0xc9,0xa0,0x90); +DEFINE_GUID(IID_ITaskbarList3,0xea1afb91,0x9e28,0x4b86,0x90,0xE9,0x9e,0x9f,0x8a,0x5e,0xef,0xaf); + +// Constructor: variabiles initialization +EcWin7::EcWin7() +{ + mOverlayIcon = NULL; +} + +// Init taskbar communication +void EcWin7::init(WId wid) +{ + mWindowId = wid; + mTaskbarMessageId = RegisterWindowMessage(L"TaskbarButtonCreated"); +} + +// Windows event handler callback function +// (handles taskbar communication initial message) +bool EcWin7::winEvent(MSG * message, long * result) +{ + if (message->message == mTaskbarMessageId) + { + HRESULT hr = CoCreateInstance(CLSID_TaskbarList, + 0, + CLSCTX_INPROC_SERVER, + IID_ITaskbarList3, + reinterpret_cast (&(mTaskbar))); + *result = hr; + return true; + } + return false; +} + +// Set progress bar current value +void EcWin7::setProgressValue(int value, int max) +{ + mTaskbar->SetProgressValue(mWindowId, value, max); + +} + +// Set progress bar current state (active, error, pause, ecc...) +void EcWin7::setProgressState(ToolBarProgressState state) +{ + mTaskbar->SetProgressState(mWindowId, (TBPFLAG)state); +} + +// Set new overlay icon and corresponding description (for accessibility) +// (call with iconName == "" and description == "" to remove any previous overlay icon) +void EcWin7::setOverlayIcon(QString iconName, QString description) +{ + HICON oldIcon = NULL; + if (mOverlayIcon != NULL) oldIcon = mOverlayIcon; + if (iconName == "") + { + mTaskbar->SetOverlayIcon(mWindowId, NULL, NULL); + mOverlayIcon = NULL; + } + else + { + mOverlayIcon = (HICON) LoadImage(GetModuleHandle(NULL), + iconName.toStdWString().c_str(), + IMAGE_ICON, + 0, + 0, + NULL); + mTaskbar->SetOverlayIcon(mWindowId, mOverlayIcon, description.toStdWString().c_str()); + } + if ((oldIcon != NULL) && (oldIcon != mOverlayIcon)) + { + DestroyIcon(oldIcon); + } +} +#endif diff --git a/src/3rdparty/ecwin7.h b/src/3rdparty/ecwin7.h new file mode 100644 index 000000000..1359143e9 --- /dev/null +++ b/src/3rdparty/ecwin7.h @@ -0,0 +1,141 @@ +/* EcWin7 - Support library for integrating Windows 7 taskbar features + * into any Qt application + * Copyright (C) 2010 Emanuele Colombo + * + * 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 ECWIN7_H +#define ECWIN7_H + +#include +#include + +// Windows only data definitions +#ifdef Q_WS_WIN + +#include +#include +#define CMIC_MASK_ASYNCOK SEE_MASK_ASYNCOK + +// Structs types and enums definitions for Windows 7 taskbar + +typedef enum THUMBBUTTONMASK +{ + THB_BITMAP = 0x1, + THB_ICON = 0x2, + THB_TOOLTIP = 0x4, + THB_FLAGS = 0x8 +} THUMBBUTTONMASK; + +typedef enum THUMBBUTTONFLAGS +{ + THBF_ENABLED = 0, + THBF_DISABLED = 0x1, + THBF_DISMISSONCLICK = 0x2, + THBF_NOBACKGROUND = 0x4, + THBF_HIDDEN = 0x8, + THBF_NONINTERACTIVE = 0x10 +} THUMBBUTTONFLAGS; + +typedef struct THUMBBUTTON +{ + THUMBBUTTONMASK dwMask; + UINT iId; + UINT iBitmap; + HICON hIcon; + WCHAR szTip[260]; + THUMBBUTTONFLAGS dwFlags; +} THUMBBUTTON; +typedef struct THUMBBUTTON *LPTHUMBBUTTON; + +typedef enum TBPFLAG +{ + TBPF_NOPROGRESS = 0, + TBPF_INDETERMINATE = 0x1, + TBPF_NORMAL = 0x2, + TBPF_ERROR = 0x4, + TBPF_PAUSED = 0x8 +} TBPFLAG; + +typedef IUnknown *HIMAGELIST; + +// Taskbar interface +DECLARE_INTERFACE_(ITaskbarList3,IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface) (THIS_ REFIID riid,void **ppv) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + // ITaskbarList + STDMETHOD(HrInit) (THIS) PURE; + STDMETHOD(AddTab) (THIS_ HWND hwnd) PURE; + STDMETHOD(DeleteTab) (THIS_ HWND hwnd) PURE; + STDMETHOD(ActivateTab) (THIS_ HWND hwnd) PURE; + STDMETHOD(SetActiveAlt) (THIS_ HWND hwnd) PURE; + STDMETHOD (MarkFullscreenWindow) (THIS_ HWND hwnd, int fFullscreen) PURE; + // ITaskbarList3 + STDMETHOD (SetProgressValue) (THIS_ HWND hwnd, ULONGLONG ullCompleted, ULONGLONG ullTotal) PURE; + STDMETHOD (SetProgressState) (THIS_ HWND hwnd, TBPFLAG tbpFlags) PURE; + STDMETHOD (RegisterTab) (THIS_ HWND hwndTab,HWND hwndMDI) PURE; + STDMETHOD (UnregisterTab) (THIS_ HWND hwndTab) PURE; + STDMETHOD (SetTabOrder) (THIS_ HWND hwndTab, HWND hwndInsertBefore) PURE; + STDMETHOD (SetTabActive) (THIS_ HWND hwndTab, HWND hwndMDI, DWORD dwReserved) PURE; + STDMETHOD (ThumbBarAddButtons) (THIS_ HWND hwnd, UINT cButtons, LPTHUMBBUTTON pButton) PURE; + STDMETHOD (ThumbBarUpdateButtons) (THIS_ HWND hwnd, UINT cButtons, LPTHUMBBUTTON pButton) PURE; + STDMETHOD (ThumbBarSetImageList) (THIS_ HWND hwnd, HIMAGELIST himl) PURE; + STDMETHOD (SetOverlayIcon) (THIS_ HWND hwnd, HICON hIcon, LPCWSTR pszDescription) PURE; + STDMETHOD (SetThumbnailTooltip) (THIS_ HWND hwnd, LPCWSTR pszTip) PURE; + STDMETHOD (SetThumbnailClip) (THIS_ HWND hwnd, RECT *prcClip) PURE; +}; +typedef ITaskbarList3 *LPITaskbarList3; + + +// ******************************************************************** +// EcWin7 class - Windows 7 taskbar handling for Qt and MinGW + +class EcWin7 +{ +public: + + // Initialization methods + EcWin7(); + void init(WId wid); + bool winEvent(MSG * message, long * result); + + // Overlay icon handling + void setOverlayIcon(QString iconName, QString description); + + // Progress indicator handling + enum ToolBarProgressState { + NoProgress = 0, + Indeterminate = 1, + Normal = 2, + Error = 4, + Paused = 8 + }; + void setProgressValue(int value, int max); + void setProgressState(ToolBarProgressState state); + +private: + WId mWindowId; + UINT mTaskbarMessageId; + ITaskbarList3 *mTaskbar; + HICON mOverlayIcon; +}; +// Windows only data definitions - END +#endif + +#endif // ECWIN7_H diff --git a/src/3rdparty/lineedit.cpp b/src/3rdparty/lineedit.cpp new file mode 100644 index 000000000..0cd2330bf --- /dev/null +++ b/src/3rdparty/lineedit.cpp @@ -0,0 +1,214 @@ +#include "lineedit.h" + +#include +#include +#include +#include +#include + +#include +SideWidget::SideWidget(QWidget *parent) + : QWidget(parent) +{ +} + +bool SideWidget::event(QEvent *event) +{ + if (event->type() == QEvent::LayoutRequest) + emit sizeHintChanged(); + return QWidget::event(event); +} + +LineEdit::LineEdit(QWidget *parent) + : QLineEdit(parent) + , m_leftLayout(0) + , m_rightLayout(0) + , m_leftMargin(0) +{ + init(); +} + +LineEdit::LineEdit(const QString &contents, QWidget *parent) + : QLineEdit(contents, parent) + , m_leftWidget(0) + , m_rightWidget(0) + , m_leftLayout(0) + , m_rightLayout(0) + , m_leftMargin(0) +{ + init(); +} + +void LineEdit::setLeftMargin(int margin) +{ + m_leftMargin = margin; +} + +void LineEdit::init() +{ + m_leftWidget = new SideWidget(this); + m_leftWidget->resize(0, 0); + m_leftLayout = new QHBoxLayout(m_leftWidget); + m_leftLayout->setContentsMargins(0, 0, 0, 0); + + if (isRightToLeft()) + m_leftLayout->setDirection(QBoxLayout::RightToLeft); + else + m_leftLayout->setDirection(QBoxLayout::LeftToRight); + m_leftLayout->setSizeConstraint(QLayout::SetFixedSize); + + m_rightWidget = new SideWidget(this); + m_rightWidget->resize(0, 0); + m_rightLayout = new QHBoxLayout(m_rightWidget); + if (isRightToLeft()) + m_rightLayout->setDirection(QBoxLayout::RightToLeft); + else + m_rightLayout->setDirection(QBoxLayout::LeftToRight); + m_rightLayout->setContentsMargins(0, 0, 0, 0); + + QSpacerItem *horizontalSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum); + m_rightLayout->addItem(horizontalSpacer); + + setWidgetSpacing(3); + connect(m_leftWidget, SIGNAL(sizeHintChanged()), + this, SLOT(updateTextMargins())); + connect(m_rightWidget, SIGNAL(sizeHintChanged()), + this, SLOT(updateTextMargins())); +} + +bool LineEdit::event(QEvent *event) +{ + if (event->type() == QEvent::LayoutDirectionChange) { + if (isRightToLeft()) { + m_leftLayout->setDirection(QBoxLayout::RightToLeft); + m_rightLayout->setDirection(QBoxLayout::RightToLeft); + } else { + m_leftLayout->setDirection(QBoxLayout::LeftToRight); + m_rightLayout->setDirection(QBoxLayout::LeftToRight); + } + } + return QLineEdit::event(event); +} + +void LineEdit::addWidget(QWidget *widget, WidgetPosition position) +{ + if (!widget) + return; + + bool rtl = isRightToLeft(); + if (rtl) + position = (position == LeftSide) ? RightSide : LeftSide; + if (position == LeftSide) { + m_leftLayout->addWidget(widget); + } else { + m_rightLayout->insertWidget(1, widget); + } +} + +void LineEdit::removeWidget(QWidget *widget) +{ + if (!widget) + return; + + m_leftLayout->removeWidget(widget); + m_rightLayout->removeWidget(widget); + widget->hide(); +} + +void LineEdit::setWidgetSpacing(int spacing) +{ + m_leftLayout->setSpacing(spacing); + m_rightLayout->setSpacing(spacing); + updateTextMargins(); +} + +int LineEdit::widgetSpacing() const +{ + return m_leftLayout->spacing(); +} + +int LineEdit::textMargin(WidgetPosition position) const +{ + int spacing = m_rightLayout->spacing(); + int w = 0; + if (position == LeftSide) + w = m_leftWidget->sizeHint().width(); + else + w = m_rightWidget->sizeHint().width(); + if (w == 0) + return 0; + return w + spacing * 2; +} + +void LineEdit::updateTextMargins() +{ + int left; + if (m_leftMargin == 0) + left = textMargin(LineEdit::LeftSide); + else + left = m_leftMargin; + int right = textMargin(LineEdit::RightSide); + int top = 0; + int bottom = 0; + setTextMargins(left, top, right, bottom); + updateSideWidgetLocations(); +} + +void LineEdit::updateSideWidgetLocations() +{ + QStyleOptionFrameV2 opt; + initStyleOption(&opt); + QRect textRect = style()->subElementRect(QStyle::SE_LineEditContents, &opt, this); + int spacing = m_rightLayout->spacing(); + textRect.adjust(spacing, 0, -spacing, 0); + + int left = textMargin(LineEdit::LeftSide); + + int midHeight = textRect.center().y() + 1; + + if (m_leftLayout->count() > 0) { + int leftHeight = midHeight - m_leftWidget->height() / 2; + int leftWidth = m_leftWidget->width(); + if (leftWidth == 0) + leftHeight = midHeight - m_leftWidget->sizeHint().height() / 2; + m_leftWidget->move(textRect.x(), leftHeight); + } + textRect.setX(left); + textRect.setY(midHeight - m_rightWidget->sizeHint().height() / 2); + textRect.setHeight(m_rightWidget->sizeHint().height()); + m_rightWidget->setGeometry(textRect); +} + +void LineEdit::resizeEvent(QResizeEvent *event) +{ + updateSideWidgetLocations(); + QLineEdit::resizeEvent(event); +} + +QString LineEdit::inactiveText() const +{ + return m_inactiveText; +} + +void LineEdit::setInactiveText(const QString &text) +{ + m_inactiveText = text; +} + +void LineEdit::paintEvent(QPaintEvent *event) +{ + QLineEdit::paintEvent(event); + if (text().isEmpty() && !m_inactiveText.isEmpty() && !hasFocus()) { + QStyleOptionFrameV2 panel; + initStyleOption(&panel); + QRect textRect = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this); + int horizontalMargin = 2; + textRect.adjust(horizontalMargin, 0, 0, 0); + int left = textMargin(LineEdit::LeftSide); + int right = textMargin(LineEdit::RightSide); + textRect.adjust(left, 0, -right, 0); + QPainter painter(this); + painter.setPen(palette().brush(QPalette::Disabled, QPalette::Text).color()); + painter.drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, m_inactiveText); + } +} diff --git a/src/3rdparty/lineedit.h b/src/3rdparty/lineedit.h new file mode 100644 index 000000000..62ac72cef --- /dev/null +++ b/src/3rdparty/lineedit.h @@ -0,0 +1,107 @@ +#ifndef LINEEDIT_H +#define LINEEDIT_H +/** +* Copyright (c) 2008 - 2009, Benjamin C. Meyer +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. 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. +* 3. Neither the name of the Benjamin Meyer 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 REGENTS 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 THE REGENTS OR CONTRIBUTORS 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 + +class QHBoxLayout; + +/* +LineEdit is a subclass of QLineEdit that provides an easy and simple +way to add widgets on the left or right hand side of the text. + +The layout of the widgets on either side are handled by a QHBoxLayout. +You can set the spacing around the widgets with setWidgetSpacing(). + +As widgets are added to the class they are inserted from the outside +into the center of the widget. +*/ +class SideWidget; +class LineEdit : public QLineEdit +{ + Q_OBJECT + Q_PROPERTY(QString inactiveText READ inactiveText WRITE setInactiveText) + +public: + enum WidgetPosition { + LeftSide, + RightSide + }; + + LineEdit(QWidget *parent = 0); + LineEdit(const QString &contents, QWidget *parent = 0); + + void addWidget(QWidget *widget, WidgetPosition position); + void removeWidget(QWidget *widget); + void setWidgetSpacing(int spacing); + int widgetSpacing() const; + int textMargin(WidgetPosition position) const; + QString inactiveText() const; + void setInactiveText(const QString &text); + + void paintEvent(QPaintEvent *event); + + void setLeftMargin(int margin); + +protected: + void resizeEvent(QResizeEvent *event); + bool event(QEvent *event); + +protected slots: + void updateTextMargins(); + +private: + void init(); + void updateSideWidgetLocations(); + + SideWidget *m_leftWidget; + SideWidget *m_rightWidget; + QHBoxLayout *m_leftLayout; + QHBoxLayout *m_rightLayout; + QString m_inactiveText; + int m_leftMargin; +}; + + +class SideWidget : public QWidget +{ + Q_OBJECT + +signals: + void sizeHintChanged(); + +public: + SideWidget(QWidget *parent = 0); + +protected: + bool event(QEvent *event); + +}; + +#endif // LINEEDIT_H diff --git a/src/3rdparty/qtlocalpeer.cpp b/src/3rdparty/qtlocalpeer.cpp new file mode 100644 index 000000000..f531956f3 --- /dev/null +++ b/src/3rdparty/qtlocalpeer.cpp @@ -0,0 +1,203 @@ +/**************************************************************************** +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact Nokia at qt-info@nokia.com. +** +****************************************************************************/ + + +#include "qtlocalpeer.h" +#include +#include + +#if defined(Q_OS_WIN) +#include +#include +typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*); +static PProcessIdToSessionId pProcessIdToSessionId = 0; +#endif +#if defined(Q_OS_UNIX) +#include +#endif + +namespace QtLP_Private { +#include "qtlockedfile.cpp" +#if defined(Q_OS_WIN) +#include "qtlockedfile_win.cpp" +#else +#include "qtlockedfile_unix.cpp" +#endif +} + +const char* QtLocalPeer::ack = "ack"; + +QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId) + : QObject(parent), id(appId) +{ + QString prefix = id; + if (id.isEmpty()) { + id = QCoreApplication::applicationFilePath(); +#if defined(Q_OS_WIN) + id = id.toLower(); +#endif + prefix = id.section(QLatin1Char('/'), -1); + } + prefix.remove(QRegExp("[^a-zA-Z]")); + prefix.truncate(6); + + QByteArray idc = id.toUtf8(); + quint16 idNum = qChecksum(idc.constData(), idc.size()); + socketName = QLatin1String("qtsingleapp-") + prefix + + QLatin1Char('-') + QString::number(idNum, 16); + +#if defined(Q_OS_WIN) + if (!pProcessIdToSessionId) { + QLibrary lib("kernel32"); + pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); + } + if (pProcessIdToSessionId) { + DWORD sessionId = 0; + pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); + socketName += QLatin1Char('-') + QString::number(sessionId, 16); + } +#else + socketName += QLatin1Char('-') + QString::number(::getuid(), 16); +#endif + + server = new QLocalServer(this); + QString lockName = QDir(QDir::tempPath()).absolutePath() + + QLatin1Char('/') + socketName + + QLatin1String("-lockfile"); + lockFile.setFileName(lockName); + lockFile.open(QIODevice::ReadWrite); +} + + + +bool QtLocalPeer::isClient() +{ + if (lockFile.isLocked()) + return false; + + if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false)) + return true; + + bool res = server->listen(socketName); +#if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0)) + // ### Workaround + if (!res && server->serverError() == QAbstractSocket::AddressInUseError) { + QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName); + res = server->listen(socketName); + } +#endif + if (!res) + qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString())); + QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection())); + return false; +} + + +bool QtLocalPeer::sendMessage(const QString &message, int timeout) +{ + if (!isClient()) + return false; + + QLocalSocket socket; + bool connOk = false; + for(int i = 0; i < 2; i++) { + // Try twice, in case the other instance is just starting up + socket.connectToServer(socketName); + connOk = socket.waitForConnected(timeout/2); + if (connOk || i) + break; + int ms = 250; +#if defined(Q_OS_WIN) + Sleep(DWORD(ms)); +#else + struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; + nanosleep(&ts, NULL); +#endif + } + if (!connOk) + return false; + + QByteArray uMsg(message.toUtf8()); + QDataStream ds(&socket); + ds.writeBytes(uMsg.constData(), uMsg.size()); + bool res = socket.waitForBytesWritten(timeout); + res &= socket.waitForReadyRead(timeout); // wait for ack + res &= (socket.read(qstrlen(ack)) == ack); + return res; +} + + +void QtLocalPeer::receiveConnection() +{ + QLocalSocket* socket = server->nextPendingConnection(); + if (!socket) + return; + + while (socket->bytesAvailable() < (int)sizeof(quint32)) + socket->waitForReadyRead(); + QDataStream ds(socket); + QByteArray uMsg; + quint32 remaining; + ds >> remaining; + uMsg.resize(remaining); + int got = 0; + char* uMsgBuf = uMsg.data(); + do { + got = ds.readRawData(uMsgBuf, remaining); + remaining -= got; + uMsgBuf += got; + } while (remaining && got >= 0 && socket->waitForReadyRead(2000)); + if (got < 0) { + qWarning() << "QtLocalPeer: Message reception failed" << socket->errorString(); + delete socket; + return; + } + QString message(QString::fromUtf8(uMsg)); + socket->write(ack, qstrlen(ack)); + socket->waitForBytesWritten(1000); + delete socket; + emit messageReceived(message); //### (might take a long time to return) +} diff --git a/src/3rdparty/qtlocalpeer.h b/src/3rdparty/qtlocalpeer.h new file mode 100644 index 000000000..8a54a9b5e --- /dev/null +++ b/src/3rdparty/qtlocalpeer.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact Nokia at qt-info@nokia.com. +** +****************************************************************************/ + + +#include +#include +#include + +namespace QtLP_Private { +#include "qtlockedfile.h" +} + +class QtLocalPeer : public QObject +{ + Q_OBJECT + +public: + QtLocalPeer(QObject *parent = 0, const QString &appId = QString()); + bool isClient(); + bool sendMessage(const QString &message, int timeout); + QString applicationId() const + { return id; } + +Q_SIGNALS: + void messageReceived(const QString &message); + +protected Q_SLOTS: + void receiveConnection(); + +protected: + QString id; + QString socketName; + QLocalServer* server; + QtLP_Private::QtLockedFile lockFile; + +private: + static const char* ack; +}; diff --git a/src/3rdparty/qtlockedfile.cpp b/src/3rdparty/qtlockedfile.cpp new file mode 100644 index 000000000..2cf080584 --- /dev/null +++ b/src/3rdparty/qtlockedfile.cpp @@ -0,0 +1,199 @@ +/**************************************************************************** +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact Nokia at qt-info@nokia.com. +** +****************************************************************************/ + +#include "qtlockedfile.h" + +/*! + \class QtLockedFile + + \brief The QtLockedFile class extends QFile with advisory locking + functions. + + A file may be locked in read or write mode. Multiple instances of + \e QtLockedFile, created in multiple processes running on the same + machine, may have a file locked in read mode. Exactly one instance + may have it locked in write mode. A read and a write lock cannot + exist simultaneously on the same file. + + The file locks are advisory. This means that nothing prevents + another process from manipulating a locked file using QFile or + file system functions offered by the OS. Serialization is only + guaranteed if all processes that access the file use + QLockedFile. Also, while holding a lock on a file, a process + must not open the same file again (through any API), or locks + can be unexpectedly lost. + + The lock provided by an instance of \e QtLockedFile is released + whenever the program terminates. This is true even when the + program crashes and no destructors are called. +*/ + +/*! \enum QtLockedFile::LockMode + + This enum describes the available lock modes. + + \value ReadLock A read lock. + \value WriteLock A write lock. + \value NoLock Neither a read lock nor a write lock. +*/ + +/*! + Constructs an unlocked \e QtLockedFile object. This constructor + behaves in the same way as \e QFile::QFile(). + + \sa QFile::QFile() +*/ +QtLockedFile::QtLockedFile() + : QFile() +{ +#ifdef Q_OS_WIN + wmutex = 0; + rmutex = 0; +#endif + m_lock_mode = NoLock; +} + +/*! + Constructs an unlocked QtLockedFile object with file \a name. This + constructor behaves in the same way as \e QFile::QFile(const + QString&). + + \sa QFile::QFile() +*/ +QtLockedFile::QtLockedFile(const QString &name) + : QFile(name) +{ +#ifdef Q_OS_WIN + wmutex = 0; + rmutex = 0; +#endif + m_lock_mode = NoLock; +} + +/*! + Opens the file in OpenMode \a mode. + + This is identical to QFile::open(), with the one exception that the + Truncate mode flag is disallowed. Truncation would conflict with the + advisory file locking, since the file would be modified before the + write lock is obtained. If truncation is required, use resize(0) + after obtaining the write lock. + + Returns true if successful; otherwise false. + + \sa QFile::open(), QFile::resize() +*/ +bool QtLockedFile::open(OpenMode mode) +{ + if (mode & QIODevice::Truncate) { + qWarning("QtLockedFile::open(): Truncate mode not allowed."); + return false; + } + return QFile::open(mode); +} + +/*! + Returns \e true if this object has a in read or write lock; + otherwise returns \e false. + + \sa lockMode() +*/ +bool QtLockedFile::isLocked() const +{ + return m_lock_mode != NoLock; +} + +/*! + Returns the type of lock currently held by this object, or \e + QtLockedFile::NoLock. + + \sa isLocked() +*/ +QtLockedFile::LockMode QtLockedFile::lockMode() const +{ + return m_lock_mode; +} + +/*! + \fn bool QtLockedFile::lock(LockMode mode, bool block = true) + + Obtains a lock of type \a mode. The file must be opened before it + can be locked. + + If \a block is true, this function will block until the lock is + aquired. If \a block is false, this function returns \e false + immediately if the lock cannot be aquired. + + If this object already has a lock of type \a mode, this function + returns \e true immediately. If this object has a lock of a + different type than \a mode, the lock is first released and then a + new lock is obtained. + + This function returns \e true if, after it executes, the file is + locked by this object, and \e false otherwise. + + \sa unlock(), isLocked(), lockMode() +*/ + +/*! + \fn bool QtLockedFile::unlock() + + Releases a lock. + + If the object has no lock, this function returns immediately. + + This function returns \e true if, after it executes, the file is + not locked by this object, and \e false otherwise. + + \sa lock(), isLocked(), lockMode() +*/ + +/*! + \fn QtLockedFile::~QtLockedFile() + + Destroys the \e QtLockedFile object. If any locks were held, they + are released. +*/ diff --git a/src/3rdparty/qtlockedfile.h b/src/3rdparty/qtlockedfile.h new file mode 100644 index 000000000..1d3b918ec --- /dev/null +++ b/src/3rdparty/qtlockedfile.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact Nokia at qt-info@nokia.com. +** +****************************************************************************/ + +#ifndef QTLOCKEDFILE_H +#define QTLOCKEDFILE_H + +#include +#ifdef Q_OS_WIN +#include +#endif + +#if defined(Q_WS_WIN) +# if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT) +# define QT_QTLOCKEDFILE_EXPORT +# elif defined(QT_QTLOCKEDFILE_IMPORT) +# if defined(QT_QTLOCKEDFILE_EXPORT) +# undef QT_QTLOCKEDFILE_EXPORT +# endif +# define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport) +# elif defined(QT_QTLOCKEDFILE_EXPORT) +# undef QT_QTLOCKEDFILE_EXPORT +# define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport) +# endif +#else +# define QT_QTLOCKEDFILE_EXPORT +#endif + +class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile +{ +public: + enum LockMode { NoLock = 0, ReadLock, WriteLock }; + + QtLockedFile(); + QtLockedFile(const QString &name); + ~QtLockedFile(); + + bool open(OpenMode mode); + + bool lock(LockMode mode, bool block = true); + bool unlock(); + bool isLocked() const; + LockMode lockMode() const; + +private: +#ifdef Q_OS_WIN + Qt::HANDLE wmutex; + Qt::HANDLE rmutex; + QVector rmutexes; + QString mutexname; + + Qt::HANDLE getMutexHandle(int idx, bool doCreate); + bool waitMutex(Qt::HANDLE mutex, bool doBlock); + +#endif + LockMode m_lock_mode; +}; + +#endif diff --git a/src/3rdparty/qtlockedfile_unix.cpp b/src/3rdparty/qtlockedfile_unix.cpp new file mode 100644 index 000000000..2881bdd2c --- /dev/null +++ b/src/3rdparty/qtlockedfile_unix.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact Nokia at qt-info@nokia.com. +** +****************************************************************************/ + +#include +#include +#include +#include + +#include "qtlockedfile.h" + +bool QtLockedFile::lock(LockMode mode, bool block) +{ + if (!isOpen()) { + qWarning("QtLockedFile::lock(): file is not opened"); + return false; + } + + if (mode == NoLock) + return unlock(); + + if (mode == m_lock_mode) + return true; + + if (m_lock_mode != NoLock) + unlock(); + + struct flock fl; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK; + int cmd = block ? F_SETLKW : F_SETLK; + int ret = fcntl(handle(), cmd, &fl); + + if (ret == -1) { + if (errno != EINTR && errno != EAGAIN) + qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); + return false; + } + + + m_lock_mode = mode; + return true; +} + + +bool QtLockedFile::unlock() +{ + if (!isOpen()) { + qWarning("QtLockedFile::unlock(): file is not opened"); + return false; + } + + if (!isLocked()) + return true; + + struct flock fl; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + fl.l_type = F_UNLCK; + int ret = fcntl(handle(), F_SETLKW, &fl); + + if (ret == -1) { + qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); + return false; + } + + m_lock_mode = NoLock; + return true; +} + +QtLockedFile::~QtLockedFile() +{ + if (isOpen()) + unlock(); +} + diff --git a/src/3rdparty/qtlockedfile_win.cpp b/src/3rdparty/qtlockedfile_win.cpp new file mode 100644 index 000000000..d4bf9e141 --- /dev/null +++ b/src/3rdparty/qtlockedfile_win.cpp @@ -0,0 +1,213 @@ +/**************************************************************************** +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact Nokia at qt-info@nokia.com. +** +****************************************************************************/ + +#include "qtlockedfile.h" +#include +#include + +#define MUTEX_PREFIX "QtLockedFile mutex " +// Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS +#define MAX_READERS MAXIMUM_WAIT_OBJECTS + +Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate) +{ + if (mutexname.isEmpty()) { + QFileInfo fi(*this); + mutexname = QString::fromLatin1(MUTEX_PREFIX) + + fi.absoluteFilePath().toLower(); + } + QString mname(mutexname); + if (idx >= 0) + mname += QString::number(idx); + + Qt::HANDLE mutex; + if (doCreate) { + QT_WA( { mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); }, + { mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } ); + if (!mutex) { + qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); + return 0; + } + } + else { + QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); }, + { mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } ); + if (!mutex) { + if (GetLastError() != ERROR_FILE_NOT_FOUND) + qErrnoWarning("QtLockedFile::lock(): OpenMutex failed"); + return 0; + } + } + return mutex; +} + +bool QtLockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock) +{ + Q_ASSERT(mutex); + DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0); + switch (res) { + case WAIT_OBJECT_0: + case WAIT_ABANDONED: + return true; + break; + case WAIT_TIMEOUT: + break; + default: + qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed"); + } + return false; +} + + + +bool QtLockedFile::lock(LockMode mode, bool block) +{ + if (!isOpen()) { + qWarning("QtLockedFile::lock(): file is not opened"); + return false; + } + + if (mode == NoLock) + return unlock(); + + if (mode == m_lock_mode) + return true; + + if (m_lock_mode != NoLock) + unlock(); + + if (!wmutex && !(wmutex = getMutexHandle(-1, true))) + return false; + + if (!waitMutex(wmutex, block)) + return false; + + if (mode == ReadLock) { + int idx = 0; + for (; idx < MAX_READERS; idx++) { + rmutex = getMutexHandle(idx, false); + if (!rmutex || waitMutex(rmutex, false)) + break; + CloseHandle(rmutex); + } + bool ok = true; + if (idx >= MAX_READERS) { + qWarning("QtLockedFile::lock(): too many readers"); + rmutex = 0; + ok = false; + } + else if (!rmutex) { + rmutex = getMutexHandle(idx, true); + if (!rmutex || !waitMutex(rmutex, false)) + ok = false; + } + if (!ok && rmutex) { + CloseHandle(rmutex); + rmutex = 0; + } + ReleaseMutex(wmutex); + if (!ok) + return false; + } + else { + Q_ASSERT(rmutexes.isEmpty()); + for (int i = 0; i < MAX_READERS; i++) { + Qt::HANDLE mutex = getMutexHandle(i, false); + if (mutex) + rmutexes.append(mutex); + } + if (rmutexes.size()) { + DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(), + TRUE, block ? INFINITE : 0); + if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) { + if (res != WAIT_TIMEOUT) + qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed"); + m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky + unlock(); + return false; + } + } + } + + m_lock_mode = mode; + return true; +} + +bool QtLockedFile::unlock() +{ + if (!isOpen()) { + qWarning("QtLockedFile::unlock(): file is not opened"); + return false; + } + + if (!isLocked()) + return true; + + if (m_lock_mode == ReadLock) { + ReleaseMutex(rmutex); + CloseHandle(rmutex); + rmutex = 0; + } + else { + foreach(Qt::HANDLE mutex, rmutexes) { + ReleaseMutex(mutex); + CloseHandle(mutex); + } + rmutexes.clear(); + ReleaseMutex(wmutex); + } + + m_lock_mode = QtLockedFile::NoLock; + return true; +} + +QtLockedFile::~QtLockedFile() +{ + if (isOpen()) + unlock(); + if (wmutex) + CloseHandle(wmutex); +} diff --git a/src/3rdparty/qtsingleapplication.cpp b/src/3rdparty/qtsingleapplication.cpp new file mode 100644 index 000000000..46204335b --- /dev/null +++ b/src/3rdparty/qtsingleapplication.cpp @@ -0,0 +1,352 @@ +/**************************************************************************** +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact Nokia at qt-info@nokia.com. +** +****************************************************************************/ + + +#include "qtsingleapplication.h" +#include "qtlocalpeer.h" +#include + + +/*! + \class QtSingleApplication qtsingleapplication.h + \brief The QtSingleApplication class provides an API to detect and + communicate with running instances of an application. + + This class allows you to create applications where only one + instance should be running at a time. I.e., if the user tries to + launch another instance, the already running instance will be + activated instead. Another usecase is a client-server system, + where the first started instance will assume the role of server, + and the later instances will act as clients of that server. + + By default, the full path of the executable file is used to + determine whether two processes are instances of the same + application. You can also provide an explicit identifier string + that will be compared instead. + + The application should create the QtSingleApplication object early + in the startup phase, and call isRunning() or sendMessage() to + find out if another instance of this application is already + running. Startup parameters (e.g. the name of the file the user + wanted this new instance to open) can be passed to the running + instance in the sendMessage() function. + + If isRunning() or sendMessage() returns false, it means that no + other instance is running, and this instance has assumed the role + as the running instance. The application should continue with the + initialization of the application user interface before entering + the event loop with exec(), as normal. The messageReceived() + signal will be emitted when the application receives messages from + another instance of the same application. + + If isRunning() or sendMessage() returns true, another instance is + already running, and the application should terminate or enter + client mode. + + If a message is received it might be helpful to the user to raise + the application so that it becomes visible. To facilitate this, + QtSingleApplication provides the setActivationWindow() function + and the activateWindow() slot. + + Here's an example that shows how to convert an existing + application to use QtSingleApplication. It is very simple and does + not make use of all QtSingleApplication's functionality (see the + examples for that). + + \code + // Original + int main(int argc, char **argv) + { + QApplication app(argc, argv); + + MyMainWidget mmw; + + mmw.show(); + return app.exec(); + } + + // Single instance + int main(int argc, char **argv) + { + QtSingleApplication app(argc, argv); + + if (app.isRunning()) + return 0; + + MyMainWidget mmw; + + app.setActivationWindow(&mmw); + + mmw.show(); + return app.exec(); + } + \endcode + + Once this QtSingleApplication instance is destroyed(for example, + when the user quits), when the user next attempts to run the + application this instance will not, of course, be encountered. The + next instance to call isRunning() or sendMessage() will assume the + role as the new running instance. + + For console (non-GUI) applications, QtSingleCoreApplication may be + used instead of this class, to avoid the dependency on the QtGui + library. + + \sa QtSingleCoreApplication +*/ + + +void QtSingleApplication::sysInit(const QString &appId) +{ + actWin = 0; + peer = new QtLocalPeer(this, appId); + connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); +} + + +/*! + Creates a QtSingleApplication object. The application identifier + will be QCoreApplication::applicationFilePath(). \a argc, \a + argv, and \a GUIenabled are passed on to the QAppliation constructor. + + If you are creating a console application (i.e. setting \a + GUIenabled to false), you may consider using + QtSingleCoreApplication instead. +*/ + +QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled) + : QApplication(argc, argv, GUIenabled) +{ + sysInit(); +} + + +/*! + Creates a QtSingleApplication object with the application + identifier \a appId. \a argc and \a argv are passed on to the + QAppliation constructor. +*/ + +QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv) + : QApplication(argc, argv) +{ + sysInit(appId); +} + + +/*! + Creates a QtSingleApplication object. The application identifier + will be QCoreApplication::applicationFilePath(). \a argc, \a + argv, and \a type are passed on to the QAppliation constructor. +*/ +QtSingleApplication::QtSingleApplication(int &argc, char **argv, Type type) + : QApplication(argc, argv, type) +{ + sysInit(); +} + + +#if defined(Q_WS_X11) +/*! + Special constructor for X11, ref. the documentation of + QApplication's corresponding constructor. The application identifier + will be QCoreApplication::applicationFilePath(). \a dpy, \a visual, + and \a cmap are passed on to the QApplication constructor. +*/ +QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap) + : QApplication(dpy, visual, cmap) +{ + sysInit(); +} + +/*! + Special constructor for X11, ref. the documentation of + QApplication's corresponding constructor. The application identifier + will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a + argv, \a visual, and \a cmap are passed on to the QApplication + constructor. +*/ +QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) + : QApplication(dpy, argc, argv, visual, cmap) +{ + sysInit(); +} + +/*! + Special constructor for X11, ref. the documentation of + QApplication's corresponding constructor. The application identifier + will be \a appId. \a dpy, \a argc, \a + argv, \a visual, and \a cmap are passed on to the QApplication + constructor. +*/ +QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) + : QApplication(dpy, argc, argv, visual, cmap) +{ + sysInit(appId); +} +#endif + + +/*! + Returns true if another instance of this application is running; + otherwise false. + + This function does not find instances of this application that are + being run by a different user (on Windows: that are running in + another session). + + \sa sendMessage() +*/ + +bool QtSingleApplication::isRunning() +{ + return peer->isClient(); +} + + +/*! + Tries to send the text \a message to the currently running + instance. The QtSingleApplication object in the running instance + will emit the messageReceived() signal when it receives the + message. + + This function returns true if the message has been sent to, and + processed by, the current instance. If there is no instance + currently running, or if the running instance fails to process the + message within \a timeout milliseconds, this function return false. + + \sa isRunning(), messageReceived() +*/ +bool QtSingleApplication::sendMessage(const QString &message, int timeout) +{ + return peer->sendMessage(message, timeout); +} + + +/*! + Returns the application identifier. Two processes with the same + identifier will be regarded as instances of the same application. +*/ +QString QtSingleApplication::id() const +{ + return peer->applicationId(); +} + + +/*! + Sets the activation window of this application to \a aw. The + activation window is the widget that will be activated by + activateWindow(). This is typically the application's main window. + + If \a activateOnMessage is true (the default), the window will be + activated automatically every time a message is received, just prior + to the messageReceived() signal being emitted. + + \sa activateWindow(), messageReceived() +*/ + +void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage) +{ + actWin = aw; + if (activateOnMessage) + connect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); + else + disconnect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); +} + + +/*! + Returns the applications activation window if one has been set by + calling setActivationWindow(), otherwise returns 0. + + \sa setActivationWindow() +*/ +QWidget* QtSingleApplication::activationWindow() const +{ + return actWin; +} + + +/*! + De-minimizes, raises, and activates this application's activation window. + This function does nothing if no activation window has been set. + + This is a convenience function to show the user that this + application instance has been activated when he has tried to start + another instance. + + This function should typically be called in response to the + messageReceived() signal. By default, that will happen + automatically, if an activation window has been set. + + \sa setActivationWindow(), messageReceived(), initialize() +*/ +void QtSingleApplication::activateWindow() +{ + if (actWin) { + actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized); + actWin->raise(); + actWin->activateWindow(); + actWin->setFocus(); + } +} + + +/*! + \fn void QtSingleApplication::messageReceived(const QString& message) + + This signal is emitted when the current instance receives a \a + message from another instance of this application. + + \sa sendMessage(), setActivationWindow(), activateWindow() +*/ + + +/*! + \fn void QtSingleApplication::initialize(bool dummy = true) + + \obsolete +*/ diff --git a/src/3rdparty/qtsingleapplication.h b/src/3rdparty/qtsingleapplication.h new file mode 100644 index 000000000..5df916561 --- /dev/null +++ b/src/3rdparty/qtsingleapplication.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact Nokia at qt-info@nokia.com. +** +****************************************************************************/ + + +#include + +class QtLocalPeer; + +#if defined(Q_WS_WIN) +# if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT) +# define QT_QTSINGLEAPPLICATION_EXPORT +# elif defined(QT_QTSINGLEAPPLICATION_IMPORT) +# if defined(QT_QTSINGLEAPPLICATION_EXPORT) +# undef QT_QTSINGLEAPPLICATION_EXPORT +# endif +# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllimport) +# elif defined(QT_QTSINGLEAPPLICATION_EXPORT) +# undef QT_QTSINGLEAPPLICATION_EXPORT +# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllexport) +# endif +#else +# define QT_QTSINGLEAPPLICATION_EXPORT +#endif + +class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication +{ + Q_OBJECT + +public: + QtSingleApplication(int &argc, char **argv, bool GUIenabled = true); + QtSingleApplication(const QString &id, int &argc, char **argv); + QtSingleApplication(int &argc, char **argv, Type type); +#if defined(Q_WS_X11) + QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); + QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0); + QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); +#endif + + bool isRunning(); + QString id() const; + + void setActivationWindow(QWidget* aw, bool activateOnMessage = true); + QWidget* activationWindow() const; + + // Obsolete: + void initialize(bool dummy = true) + { isRunning(); Q_UNUSED(dummy) } + +public Q_SLOTS: + bool sendMessage(const QString &message, int timeout = 5000); + void activateWindow(); + + +Q_SIGNALS: + void messageReceived(const QString &message); + + +private: + void sysInit(const QString &appId = QString()); + QtLocalPeer *peer; + QWidget *actWin; +}; diff --git a/src/3rdparty/qtsingleapplication.pri b/src/3rdparty/qtsingleapplication.pri new file mode 100644 index 000000000..02de47e5c --- /dev/null +++ b/src/3rdparty/qtsingleapplication.pri @@ -0,0 +1,15 @@ +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD +QT *= network + +qtsingleapplication-uselib:!qtsingleapplication-buildlib { + LIBS += -L$$QTSINGLEAPPLICATION_LIBDIR -l$$QTSINGLEAPPLICATION_LIBNAME +} else { + SOURCES += $$PWD/qtsingleapplication.cpp $$PWD/qtlocalpeer.cpp + HEADERS += $$PWD/qtsingleapplication.h $$PWD/qtlocalpeer.h +} + +win32 { + contains(TEMPLATE, lib):contains(CONFIG, shared):DEFINES += QT_QTSINGLEAPPLICATION_EXPORT + else:qtsingleapplication-uselib:DEFINES += QT_QTSINGLEAPPLICATION_IMPORT +} diff --git a/src/3rdparty/qtwin.cpp b/src/3rdparty/qtwin.cpp new file mode 100644 index 000000000..827cdc619 --- /dev/null +++ b/src/3rdparty/qtwin.cpp @@ -0,0 +1,225 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Use, modification and distribution is allowed without limitation, +** warranty, liability or support of any kind. +** +****************************************************************************/ + +#include "qtwin.h" +#include +#include +#include +#include +#include + +#ifdef Q_WS_WIN + +#include + +// Blur behind data structures +#define DWM_BB_ENABLE 0x00000001 // fEnable has been specified +#define DWM_BB_BLURREGION 0x00000002 // hRgnBlur has been specified +#define DWM_BB_TRANSITIONONMAXIMIZED 0x00000004 // fTransitionOnMaximized has been specified +#define WM_DWMCOMPOSITIONCHANGED 0x031E // Composition changed window message + +typedef struct _DWM_BLURBEHIND +{ + DWORD dwFlags; + BOOL fEnable; + HRGN hRgnBlur; + BOOL fTransitionOnMaximized; +} DWM_BLURBEHIND, *PDWM_BLURBEHIND; + +typedef struct _MARGINS +{ + int cxLeftWidth; + int cxRightWidth; + int cyTopHeight; + int cyBottomHeight; +} MARGINS, *PMARGINS; + +typedef HRESULT (WINAPI *PtrDwmIsCompositionEnabled)(BOOL* pfEnabled); +typedef HRESULT (WINAPI *PtrDwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS* pMarInset); +typedef HRESULT (WINAPI *PtrDwmEnableBlurBehindWindow)(HWND hWnd, const DWM_BLURBEHIND* pBlurBehind); +typedef HRESULT (WINAPI *PtrDwmGetColorizationColor)(DWORD *pcrColorization, BOOL *pfOpaqueBlend); + +static PtrDwmIsCompositionEnabled pDwmIsCompositionEnabled= 0; +static PtrDwmEnableBlurBehindWindow pDwmEnableBlurBehindWindow = 0; +static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0; +static PtrDwmGetColorizationColor pDwmGetColorizationColor = 0; + + +/* + * Internal helper class that notifies windows if the + * DWM compositing state changes and updates the widget + * flags correspondingly. + */ +class WindowNotifier : public QWidget +{ +public: + WindowNotifier() { winId(); } + void addWidget(QWidget *widget) { widgets.append(widget); } + void removeWidget(QWidget *widget) { widgets.removeAll(widget); } + bool winEvent(MSG *message, long *result); + +private: + QWidgetList widgets; +}; + +static bool resolveLibs() +{ + if (!pDwmIsCompositionEnabled) { + QLibrary dwmLib(QString::fromAscii("dwmapi")); + pDwmIsCompositionEnabled =(PtrDwmIsCompositionEnabled)dwmLib.resolve("DwmIsCompositionEnabled"); + pDwmExtendFrameIntoClientArea = (PtrDwmExtendFrameIntoClientArea)dwmLib.resolve("DwmExtendFrameIntoClientArea"); + pDwmEnableBlurBehindWindow = (PtrDwmEnableBlurBehindWindow)dwmLib.resolve("DwmEnableBlurBehindWindow"); + pDwmGetColorizationColor = (PtrDwmGetColorizationColor)dwmLib.resolve("DwmGetColorizationColor"); + } + return pDwmIsCompositionEnabled != 0; +} + +#endif + +/*! + * Chekcs and returns true if Windows DWM composition + * is currently enabled on the system. + * + * To get live notification on the availability of + * this feature, you will currently have to + * reimplement winEvent() on your widget and listen + * for the WM_DWMCOMPOSITIONCHANGED event to occur. + * + */ +bool QtWin::isCompositionEnabled() +{ +#ifdef Q_WS_WIN + if (resolveLibs()) { + HRESULT hr = S_OK; + BOOL isEnabled = false; + hr = pDwmIsCompositionEnabled(&isEnabled); + if (SUCCEEDED(hr)) + return isEnabled; + } +#endif + return false; +} + +/*! + * Enables Blur behind on a Widget. + * + * \a enable tells if the blur should be enabled or not + */ +bool QtWin::enableBlurBehindWindow(QWidget *widget, bool enable) +{ + Q_UNUSED(enable); + Q_UNUSED(widget); + Q_ASSERT(widget); + bool result = false; +#ifdef Q_WS_WIN + if (resolveLibs()) { + DWM_BLURBEHIND bb = {0}; + HRESULT hr = S_OK; + bb.fEnable = enable; + bb.dwFlags = DWM_BB_ENABLE; + bb.hRgnBlur = NULL; + widget->setAttribute(Qt::WA_TranslucentBackground, enable); + widget->setAttribute(Qt::WA_NoSystemBackground, enable); + hr = pDwmEnableBlurBehindWindow(widget->winId(), &bb); + if (SUCCEEDED(hr)) { + result = true; + windowNotifier()->addWidget(widget); + } + } +#endif + return result; +} + +/*! + * ExtendFrameIntoClientArea. + * + * This controls the rendering of the frame inside the window. + * Note that passing margins of -1 (the default value) will completely + * remove the frame from the window. + * + * \note you should not call enableBlurBehindWindow before calling + * this functions + * + * \a enable tells if the blur should be enabled or not + */ +bool QtWin::extendFrameIntoClientArea(QWidget *widget, int left, int top, int right, int bottom) +{ + + Q_ASSERT(widget); + Q_UNUSED(left); + Q_UNUSED(top); + Q_UNUSED(right); + Q_UNUSED(bottom); + Q_UNUSED(widget); + + bool result = false; +#ifdef Q_WS_WIN + if (resolveLibs()) { + QLibrary dwmLib(QString::fromAscii("dwmapi")); + HRESULT hr = S_OK; + MARGINS m = {left, top, right, bottom}; + hr = pDwmExtendFrameIntoClientArea(widget->winId(), &m); + if (SUCCEEDED(hr)) { + result = true; + windowNotifier()->addWidget(widget); + } + widget->setAttribute(Qt::WA_TranslucentBackground, result); + } +#endif + return result; +} + +/*! + * Returns the current colorizationColor for the window. + * + * \a enable tells if the blur should be enabled or not + */ +QColor QtWin::colorizatinColor() +{ + QColor resultColor = QApplication::palette().window().color(); + +#ifdef Q_WS_WIN + if (resolveLibs()) { + DWORD color = 0; + BOOL opaque = FALSE; + QLibrary dwmLib(QString::fromAscii("dwmapi")); + HRESULT hr = S_OK; + hr = pDwmGetColorizationColor(&color, &opaque); + if (SUCCEEDED(hr)) + resultColor = QColor(color); + } +#endif + return resultColor; +} + +#ifdef Q_WS_WIN +WindowNotifier *QtWin::windowNotifier() +{ + static WindowNotifier *windowNotifierInstance = 0; + if (!windowNotifierInstance) + windowNotifierInstance = new WindowNotifier; + return windowNotifierInstance; +} + + +/* Notify all enabled windows that the DWM state changed */ +bool WindowNotifier::winEvent(MSG *message, long *result) +{ + if (message && message->message == WM_DWMCOMPOSITIONCHANGED) { + bool compositionEnabled = QtWin::isCompositionEnabled(); + foreach(QWidget * widget, widgets) { + if (widget) { + widget->setAttribute(Qt::WA_NoSystemBackground, compositionEnabled); + } + widget->update(); + } + } + return QWidget::winEvent(message, result); +} +#endif diff --git a/src/3rdparty/qtwin.h b/src/3rdparty/qtwin.h new file mode 100644 index 000000000..aa37e458c --- /dev/null +++ b/src/3rdparty/qtwin.h @@ -0,0 +1,37 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Use, modification and distribution is allowed without limitation, +** warranty, liability or support of any kind. +** +****************************************************************************/ + +#ifndef QTWIN_H +#define QTWIN_H + +#include +#include +/** + * This is a helper class for using the Desktop Window Manager + * functionality on Windows 7 and Windows Vista. On other platforms + * these functions will simply not do anything. + */ + +class WindowNotifier; + +class QtWin +{ +public: + static bool enableBlurBehindWindow(QWidget *widget, bool enable = true); + static bool extendFrameIntoClientArea(QWidget *widget, + int left = -1, int top = -1, + int right = -1, int bottom = -1); + static bool isCompositionEnabled(); + static QColor colorizatinColor(); + +private: + static WindowNotifier *windowNotifier(); +}; + +#endif // QTWIN_H diff --git a/src/3rdparty/squeezelabel.cpp b/src/3rdparty/squeezelabel.cpp new file mode 100644 index 000000000..d8a20a10f --- /dev/null +++ b/src/3rdparty/squeezelabel.cpp @@ -0,0 +1,19 @@ +#include "squeezelabel.h" + +SqueezeLabel::SqueezeLabel(QWidget *parent) + : QLabel(parent) +{ +} + +void SqueezeLabel::paintEvent(QPaintEvent *event) +{ + if (m_SqueezedTextCache != text()) { + m_SqueezedTextCache = text(); + QFontMetrics fm = fontMetrics(); + if (fm.width(m_SqueezedTextCache) > contentsRect().width()) { + QString elided = fm.elidedText(text(), Qt::ElideMiddle, width()); + setText(elided); + } + } + QLabel::paintEvent(event); +} diff --git a/src/3rdparty/squeezelabel.h b/src/3rdparty/squeezelabel.h new file mode 100644 index 000000000..1adbb828d --- /dev/null +++ b/src/3rdparty/squeezelabel.h @@ -0,0 +1,52 @@ +#ifndef SQUEEZELABEL_H +#define SQUEEZELABEL_H + +/** +* Copyright (c) 2009, Benjamin C. Meyer +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. 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. +* 3. Neither the name of the Benjamin Meyer 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 REGENTS 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 THE REGENTS OR CONTRIBUTORS 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 + +/* +A label that will squeeze the set text to fit within the size of the +widget. The text will be elided in the middle. +*/ +class SqueezeLabel : public QLabel +{ + Q_OBJECT + +public: + SqueezeLabel(QWidget *parent = 0); + +protected: + void paintEvent(QPaintEvent *event); + +private: + QString m_SqueezedTextCache; +}; + +#endif // SQUEEZELABEL_H diff --git a/src/QupZilla.pro b/src/QupZilla.pro new file mode 100644 index 000000000..82156c403 --- /dev/null +++ b/src/QupZilla.pro @@ -0,0 +1,168 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2010-12-18T14:53:41 +# +#------------------------------------------------- + +DESTDIR = ../bin + +QT += core gui webkit sql network + +TARGET = qupzilla + +TEMPLATE = app + +INCLUDEPATH += 3rdparty\ + app\ + autofill\ + bookmarks\ + cookies\ + downloads\ + history\ + navigation\ + network\ + other\ + preferences\ + rss\ + tools\ + utils\ + webview\ + plugins\ + sidebar\ + data\ + +SOURCES += main.cpp\ + 3rdparty/squeezelabel.cpp \ + 3rdparty/qtwin.cpp \ + 3rdparty/lineedit.cpp \ + app/qupzilla.cpp \ + app/mainapplication.cpp \ + app/autosaver.cpp \ + autofill/autofillmodel.cpp \ + preferences/autofillmanager.cpp \ + bookmarks/bookmarkstoolbar.cpp \ + bookmarks/bookmarksmanager.cpp \ + cookies/cookiemanager.cpp \ + cookies/cookiejar.cpp \ + downloads/downloadmanager.cpp \ + history/historymodel.cpp \ + history/historymanager.cpp \ + navigation/websearchbar.cpp \ + navigation/locationcompleter.cpp \ + navigation/locationbar.cpp \ + network/networkmanagerproxy.cpp \ + network/networkmanager.cpp \ + other/updater.cpp \ + other/sourceviewer.cpp \ + preferences/preferences.cpp \ + rss/rssmanager.cpp \ + other/clearprivatedata.cpp \ + webview/webview.cpp \ + webview/webpage.cpp \ + webview/tabwidget.cpp \ + webview/tabbar.cpp \ + webview/siteinfo.cpp \ + webview/searchtoolbar.cpp \ + app/commandlineoptions.cpp \ + other/aboutdialog.cpp \ + plugins/plugins.cpp \ + preferences/pluginslist.cpp \ + plugins/pluginproxy.cpp \ + app/appui.cpp \ + tools/clickablelabel.cpp \ + downloads/downloadoptionsdialog.cpp \ + tools/treewidget.cpp \ + bookmarks/bookmarkswidget.cpp \ + tools/frame.cpp \ + bookmarks/bookmarksmodel.cpp \ + sidebar/sidebar.cpp \ + webview/siteinfowidget.cpp \ + plugins/clicktoflash.cpp \ + plugins/webpluginfactory.cpp \ + downloads/downloaditem.cpp \ + 3rdparty/ecwin7.cpp \ + autofill/autofillwidget.cpp \ + webview/webtab.cpp + +HEADERS += 3rdparty/squeezelabel.h \ + 3rdparty/qtwin.h \ + 3rdparty/lineedit.h \ + app/qupzilla.h \ + app/mainapplication.h \ + app/autosaver.h \ + autofill/autofillmodel.h \ + preferences/autofillmanager.h \ + bookmarks/bookmarkstoolbar.h \ + bookmarks/bookmarksmanager.h \ + cookies/cookiemanager.h \ + cookies/cookiejar.h \ + downloads/downloadmanager.h \ + history/historymodel.h \ + history/historymanager.h \ + navigation/websearchbar.h \ + navigation/locationcompleter.h \ + navigation/locationbar.h \ + network/networkmanagerproxy.h \ + network/networkmanager.h \ + other/updater.h \ + other/sourceviewer.h \ + preferences/preferences.h \ + rss/rssmanager.h \ + other/clearprivatedata.h \ + webview/webview.h \ + webview/webpage.h \ + webview/tabwidget.h \ + webview/tabbar.h \ + webview/siteinfo.h \ + webview/searchtoolbar.h \ + app/commandlineoptions.h \ + other/aboutdialog.h \ + plugins/plugininterface.h \ + plugins/plugins.h \ + preferences/pluginslist.h \ + plugins/pluginproxy.h \ + tools/clickablelabel.h \ + downloads/downloadoptionsdialog.h \ + tools/treewidget.h \ + bookmarks/bookmarkswidget.h \ + tools/frame.h \ + bookmarks/bookmarksmodel.h \ + sidebar/sidebar.h \ + webview/siteinfowidget.h \ + plugins/clicktoflash.h \ + plugins/webpluginfactory.h \ + downloads/downloaditem.h \ + 3rdparty/ecwin7.h \ + autofill/autofillwidget.h \ + webview/webtab.h + +FORMS += \ + preferences/autofillmanager.ui \ + bookmarks/bookmarksmanager.ui \ + cookies/cookiemanager.ui \ + history/historymanager.ui \ + preferences/preferences.ui \ + rss/rssmanager.ui \ + webview/siteinfo.ui \ + other/aboutdialog.ui \ + preferences/pluginslist.ui \ + downloads/downloadoptionsdialog.ui \ + bookmarks/bookmarkswidget.ui \ + webview/siteinfowidget.ui \ + downloads/downloaditem.ui \ + downloads/downloadmanager.ui \ + autofill/autofillwidget.ui + +RESOURCES += \ + data/icons.qrc \ + data/html.qrc + +OTHER_FILES += \ + appicon.rc \ + +TRANSLATIONS +=cs_CZ.ts + +include(3rdparty/qtsingleapplication.pri) + +win32:RC_FILE = appicon.rc +win32:LIBS += libole32 diff --git a/src/app/appui.cpp b/src/app/appui.cpp new file mode 100644 index 000000000..29d0c20a9 --- /dev/null +++ b/src/app/appui.cpp @@ -0,0 +1,294 @@ +#include "qupzilla.h" +#include "autofillmodel.h" +#include "bookmarkstoolbar.h" +#include "locationbar.h" + +void QupZilla::postLaunch() +{ + loadSettings(); + //Open tab from command line argument + bool addTab = true; + QStringList arguments = qApp->arguments(); + for (int i = 0;iarguments().count();i++) { + QString arg = arguments.at(i); + if (arg.startsWith("-url=")) { + m_tabWidget->addView(QUrl(arg.replace("-url=",""))); + addTab = false; + } + } + + QSettings settings(m_activeProfil+"settings.ini", QSettings::IniFormat); + settings.beginGroup("Web-URL-Settings"); + int afterLaunch = settings.value("afterLaunch",1).toInt(); + settings.endGroup(); + settings.beginGroup("SessionRestore"); + bool startingAfterCrash = settings.value("isCrashed",false).toBool(); + settings.endGroup(); + qDebug() << "startingaftercrash" << startingAfterCrash; + + QUrl startUrl; + if (m_tryRestore) { + if (afterLaunch == 0) + startUrl = QUrl(""); + else if (afterLaunch == 1) + startUrl = m_homepage; + else + startUrl = m_homepage; + + if ( startingAfterCrash || (addTab && afterLaunch == 2) ) { + p_mainApp->restoreStateSlot(this); + addTab = false; + } + } else + startUrl = m_homepage; + + if (!m_startingUrl.isEmpty()) { + startUrl = WebView::guessUrlFromString(m_startingUrl.toString()); + addTab = true; + } + + if (addTab) + m_tabWidget->addView(startUrl); + + aboutToShowHistoryMenu(); + aboutToShowBookmarksMenu(); + + if (m_tabWidget->count() == 0) //Something went really wrong .. add one tab + m_tabWidget->addView(m_homepage); + + QApplication::restoreOverrideCursor(); + setUpdatesEnabled(true); + emit startingCompleted(); +} + +void QupZilla::setupUi() +{ + setContentsMargins(0,0,0,0); + + m_navigation = new QToolBar(this); + m_navigation->setWindowTitle(tr("Navigation")); + m_navigation->setObjectName("Navigation bar"); + addToolBar(m_navigation); + m_navigation->setMovable(false); + m_navigation->setStyleSheet("QToolBar{background-image:url(:icons/transp.png); border:none;}"); + + m_buttonBack = new QAction(QIcon(":/icons/navigation/zpet.png"),tr("Back"),this); + m_buttonBack->setEnabled(false); + m_buttonNext = new QAction(QIcon(":/icons/navigation/vpred.png"),tr("Forward"),this); + m_buttonNext->setEnabled(false); + m_buttonStop = new QAction(QIcon(":/icons/navigation/stop.png"),tr("Stop"),this); + m_buttonReload = new QAction(QIcon(":/icons/navigation/reload.png"),tr("Reload"),this); + m_buttonReload->setShortcut(QKeySequence("F5")); + m_buttonHome = new QAction(QIcon(":/icons/navigation/home.png"),tr("Home"),this); + + m_menuBack = new QMenu(); + m_buttonBack->setMenu(m_menuBack); + connect(m_menuBack, SIGNAL(aboutToShow()),this, SLOT(aboutToShowHistoryBackMenu())); + + m_menuForward = new QMenu(); + m_buttonNext->setMenu(m_menuForward); + connect(m_menuForward, SIGNAL(aboutToShow()),this, SLOT(aboutToShowHistoryNextMenu())); + + m_supMenu = new QToolButton(this); + m_supMenu->setPopupMode(QToolButton::InstantPopup); + m_supMenu->setIcon(QIcon(":/icons/qupzilla.png")); + m_supMenu->setToolTip(tr("Main Menu")); + m_superMenu = new QMenu(this); + m_supMenu->setMenu(m_superMenu); + + m_navigation->addAction(m_buttonBack); + m_navigation->addAction(m_buttonNext); + m_navigation->addAction(m_buttonReload); + m_navigation->addAction(m_buttonStop); + m_navigation->addAction(m_buttonHome); + + m_locationBar = new LocationBar(this); + m_searchLine = new WebSearchBar(this); + + m_navigationSplitter = new QSplitter(m_navigation); + m_navigationSplitter->addWidget(m_locationBar); + m_navigationSplitter->addWidget(m_searchLine); + + m_navigationSplitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); + m_navigationSplitter->setCollapsible(0, false); + + m_navigation->addWidget(m_navigationSplitter); + int splitterWidth = m_navigationSplitter->width(); + QList sizes; + sizes << (int)((double)splitterWidth * .75) << (int)((double)splitterWidth * .25); + m_navigationSplitter->setSizes(sizes); + + m_actionExitFullscreen = new QAction(tr("Exit Fullscreen"),this); + m_actionExitFullscreen->setVisible(false); + m_navigation->addAction(m_actionExitFullscreen); + m_navigation->addWidget(m_supMenu); + m_navigation->addWidget(new QLabel()); //Elegant spacer -,- + m_navigation->setContextMenuPolicy(Qt::CustomContextMenu); + + m_progressBar = new QProgressBar(this); + m_progressBar->setMaximumSize(QSize(150, 16)); + m_privateBrowsing = new QLabel(this); + m_privateBrowsing->setPixmap(QPixmap(":/icons/locationbar/privatebrowsing.png")); + m_privateBrowsing->setVisible(false); + m_privateBrowsing->setToolTip(tr("Private Browsing Enabled")); + m_allowFlashIcon = new QLabel(this); + m_allowFlashIcon->setPixmap(QPixmap(":/icons/menu/flash.png")); + m_allowFlashIcon->setVisible(false); + m_allowFlashIcon->setToolTip(tr("Flash Plugin Enabled")); + m_ipLabel = new QLabel(this); + m_ipLabel->setStyleSheet("padding-right: 5px;"); + m_ipLabel->setToolTip(tr("IP Address of current page")); + + statusBar()->insertPermanentWidget(0, m_progressBar); + statusBar()->insertPermanentWidget(1, m_ipLabel); + statusBar()->insertPermanentWidget(2, m_privateBrowsing); + statusBar()->insertPermanentWidget(3, m_allowFlashIcon); + + m_bookmarksToolbar = new BookmarksToolbar(this); + addToolBar(m_bookmarksToolbar); + insertToolBarBreak(m_bookmarksToolbar); + + m_tabWidget = new TabWidget(this); + setCentralWidget(m_tabWidget); +} + +void QupZilla::setupMenu() +{ + m_menuTools = new QMenu(tr("Tools")); + m_menuHelp = new QMenu(tr("Help")); + m_menuBookmarks = new QMenu(tr("Bookmarks")); + m_menuHistory = new QMenu(tr("History")); + connect(m_menuHistory, SIGNAL(aboutToShow()), this, SLOT(aboutToShowHistoryMenu())); + connect(m_menuBookmarks, SIGNAL(aboutToShow()), this, SLOT(aboutToShowBookmarksMenu())); + connect(m_menuHelp, SIGNAL(aboutToShow()), this, SLOT(aboutToShowHelpMenu())); + connect(m_menuTools, SIGNAL(aboutToShow()), this, SLOT(aboutToShowToolsMenu())); + + m_menuFile = new QMenu(tr("File")); + m_menuFile->addAction(QIcon::fromTheme("window-new"), tr("New Window"), this, SLOT(newWindow()))->setShortcut(QKeySequence("Ctrl+N")); + m_menuFile->addAction(QIcon(":/icons/menu/popup.png"), tr("New Tab"), this, SLOT(addTab()))->setShortcut(QKeySequence("Ctrl+T")); + m_menuFile->addAction(tr("Open Location"), this, SLOT(openLocation()))->setShortcut(QKeySequence("Ctrl+L")); + m_menuFile->addAction(QIcon::fromTheme("document-open"), tr("Open File"), this, SLOT(openFile()))->setShortcut(QKeySequence("Ctrl+O")); + m_menuFile->addAction(tr("Close Tab"), m_tabWidget, SLOT(closeTab()))->setShortcut(QKeySequence("Ctrl+W")); + m_menuFile->addAction(QIcon::fromTheme("window-close"), tr("Close Window"), this, SLOT(close()))->setShortcut(QKeySequence("Ctrl+Shift+W")); + m_menuFile->addSeparator(); + m_menuFile->addAction(QIcon::fromTheme("document-save"), tr("Save Page As..."), this, SLOT(savePage()))->setShortcut(QKeySequence("Ctrl+S")); + m_menuFile->addAction(tr("Send Link..."), this, SLOT(sendLink())); + m_menuFile->addAction(QIcon::fromTheme("document-print"), tr("Print"), this, SLOT(printPage())); + m_menuFile->addSeparator(); + m_menuFile->addAction(QIcon::fromTheme("application-exit"), tr("Quit"), this, SLOT(quitApp()))->setShortcut(QKeySequence("Ctrl+Q")); + menuBar()->addMenu(m_menuFile); + + m_menuEdit = new QMenu(tr("Edit")); + m_menuEdit->addAction(QIcon::fromTheme("edit-undo"), tr("Undo"))->setShortcut(QKeySequence("Ctrl+Z")); + m_menuEdit->addAction(QIcon::fromTheme("edit-redo"), tr("Redo"))->setShortcut(QKeySequence("Ctrl+Shift+Z")); + m_menuEdit->addSeparator(); + m_menuEdit->addAction(QIcon::fromTheme("edit-cut"), tr("Cut"))->setShortcut(QKeySequence("Ctrl+X")); + m_menuEdit->addAction(QIcon::fromTheme("edit-copy"), tr("Copy"), this, SLOT(copy()))->setShortcut(QKeySequence("Ctrl+C")); + m_menuEdit->addAction(QIcon::fromTheme("edit-paste"), tr("Paste"))->setShortcut(QKeySequence("Ctrl+V")); + m_menuEdit->addAction(QIcon::fromTheme("edit-delete"), tr("Delete"))->setShortcut(QKeySequence("Del")); + m_menuEdit->addSeparator(); + m_menuEdit->addAction(QIcon::fromTheme("edit-select-all"), tr("Select All"), this, SLOT(selectAll()))->setShortcut(QKeySequence("Ctrl+A")); + m_menuEdit->addSeparator(); + m_menuEdit->addAction(QIcon::fromTheme("edit-find"), tr("Find"), this, SLOT(searchOnPage()))->setShortcut(QKeySequence("Ctrl+F")); + menuBar()->addMenu(m_menuEdit); + + m_menuView = new QMenu(tr("View")); + m_actionShowToolbar = new QAction(tr("Navigation Toolbar"), this); + m_actionShowToolbar->setCheckable(true); + connect(m_actionShowToolbar, SIGNAL(triggered(bool)), this, SLOT(showNavigationToolbar())); + m_actionShowBookmarksToolbar = new QAction(tr("Bookmarks Toolbar"), this); + m_actionShowBookmarksToolbar->setCheckable(true); + connect(m_actionShowBookmarksToolbar, SIGNAL(triggered(bool)), this, SLOT(showBookmarksToolbar())); + m_actionShowStatusbar = new QAction(tr("Status Bar"), this); + m_actionShowStatusbar->setCheckable(true); + connect(m_actionShowStatusbar, SIGNAL(triggered(bool)), this, SLOT(showStatusbar())); + m_actionShowMenubar = new QAction(tr("Menu Bar"), this); + m_actionShowMenubar->setCheckable(true); + connect(m_actionShowMenubar, SIGNAL(triggered(bool)), this, SLOT(showMenubar())); + m_actionShowFullScreen = new QAction(tr("Fullscreen"), this); + m_actionShowFullScreen->setCheckable(true); + m_actionShowFullScreen->setShortcut(QKeySequence("F11")); + connect(m_actionShowFullScreen, SIGNAL(triggered(bool)), this, SLOT(fullScreen(bool))); + m_actionStop = new QAction( +#ifdef Q_WS_X11 + style()->standardIcon(QStyle::SP_BrowserStop) +#else + QIcon(":/icons/faenza/stop.png") +#endif + , tr("Stop"), this); + connect(m_actionStop, SIGNAL(triggered()), this, SLOT(stop())); + m_actionStop->setShortcut(QKeySequence("Esc")); + m_actionReload = new QAction( +#ifdef Q_WS_X11 + style()->standardIcon(QStyle::SP_BrowserReload) +#else + QIcon(":/icons/faenza/reload.png") +#endif + , tr("Reload"), this); + connect(m_actionReload, SIGNAL(triggered()), this, SLOT(reload())); + m_actionReload->setShortcut(QKeySequence("Ctrl+R")); + + m_menuView->addAction(m_actionShowMenubar); + m_menuView->addAction(m_actionShowToolbar); + m_menuView->addAction(m_actionShowBookmarksToolbar); + m_menuView->addAction(m_actionShowStatusbar); + m_menuView->addSeparator(); + m_menuView->addAction(m_actionStop); + m_menuView->addAction(m_actionReload); + m_menuView->addSeparator(); + m_menuView->addAction(QIcon::fromTheme("zoom-in"), tr("Zoom In"), this, SLOT(zoomIn()))->setShortcut(QKeySequence("Ctrl++")); + m_menuView->addAction(QIcon::fromTheme("zoom-out"), tr("Zoom Out"), this, SLOT(zoomOut()))->setShortcut(QKeySequence("Ctrl+-")); + m_menuView->addAction(QIcon::fromTheme("zoom-original"), tr("Reset"), this, SLOT(zoomReset()))->setShortcut(QKeySequence("Ctrl+0")); + m_menuView->addSeparator(); + m_menuView->addAction(QIcon::fromTheme("text-html"), tr("Page Source"), this, SLOT(showSource()))->setShortcut(QKeySequence("Ctrl+U")); + m_menuView->addAction(m_actionShowFullScreen); + menuBar()->addMenu(m_menuView); + connect(m_menuView, SIGNAL(aboutToShow()), this, SLOT(aboutToShowViewMenu())); + + menuBar()->addMenu(m_menuHistory); + menuBar()->addMenu(m_menuBookmarks); + menuBar()->addMenu(m_menuTools); + menuBar()->addMenu(m_menuHelp); + + menuBar()->setContextMenuPolicy(Qt::CustomContextMenu); + + aboutToShowToolsMenu(); + aboutToShowHelpMenu(); + + connect(m_locationBar, SIGNAL(returnPressed()), this, SLOT(urlEnter())); + connect(m_buttonBack, SIGNAL(triggered()), this, SLOT(goBack())); + connect(m_buttonNext, SIGNAL(triggered()), this, SLOT(goNext())); + connect(m_buttonStop, SIGNAL(triggered()), this, SLOT(stop())); + connect(m_buttonReload, SIGNAL(triggered()), this, SLOT(reload())); + connect(m_buttonHome, SIGNAL(triggered()), this, SLOT(goHome())); + connect(m_actionExitFullscreen, SIGNAL(triggered(bool)), this, SLOT(fullScreen(bool))); + + //Make shortcuts available even in fullscreen (menu hidden) + QList actions = menuBar()->actions(); + foreach (QAction *action, actions) { + if (action->menu()) + actions += action->menu()->actions(); + addAction(action); + } + + m_superMenu->addMenu(m_menuFile); + m_superMenu->addMenu(m_menuEdit); + m_superMenu->addMenu(m_menuView); + m_superMenu->addMenu(m_menuHistory); + m_superMenu->addMenu(m_menuBookmarks); + m_superMenu->addMenu(m_menuTools); + m_superMenu->addMenu(m_menuHelp); +} + +void QupZilla::setBackground(QColor textColor) +{ + QString color = textColor.name(); + setStyleSheet("QMainWindow { background-image: url("+m_activeProfil+"background.png); background-position: top right; } QToolBar{background-image:url(:icons/transp.png); border:none;}" + "QMenuBar{color:"+color+";background-image:url(:icons/transp.png); border:none;} QStatusBar{background-image:url(:icons/transp.png); border:none; color:"+color+";}" + "QMenuBar:item{spacing: 5px; padding: 2px 6px;background: transparent;}" + "QMenuBar::item:pressed { background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); border: 1px solid darkgrey; border-top-left-radius: 4px;border-top-right-radius: 4px; border-bottom: none;}" + "QSplitter::handle{background-color:transparent;}" + ); + +} + diff --git a/src/app/autosaver.cpp b/src/app/autosaver.cpp new file mode 100644 index 000000000..c7edb462c --- /dev/null +++ b/src/app/autosaver.cpp @@ -0,0 +1,17 @@ +#include "autosaver.h" +#include "mainapplication.h" + +AutoSaver::AutoSaver(QObject *parent) : + QObject(parent) + ,p_mainApp(MainApplication::getInstance()) +{ + m_timer.start(1000*5, this); +} + +void AutoSaver::timerEvent(QTimerEvent *event) +{ + if (event->timerId() == m_timer.timerId() && p_mainApp->isChanged()) + emit saveApp(); + else + QObject::timerEvent(event); +} diff --git a/src/app/autosaver.h b/src/app/autosaver.h new file mode 100644 index 000000000..e1379669f --- /dev/null +++ b/src/app/autosaver.h @@ -0,0 +1,37 @@ +#ifndef AUTOSAVER_H +#define AUTOSAVER_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#ifdef QT_NO_DEBUG +#ifdef DEVELOPING +#error "TRYING TO RELEASE WITH DEVELOPING FLAG" +#endif +#endif + +#include +#include +#include + +class MainApplication; +class AutoSaver : public QObject +{ + Q_OBJECT +public: + explicit AutoSaver(QObject *parent = 0); + +signals: + void saveApp(); + +public slots: + +private: + void timerEvent(QTimerEvent *); + MainApplication* p_mainApp; + QBasicTimer m_timer; + +}; + +#endif // AUTOSAVER_H diff --git a/src/app/commandlineoptions.cpp b/src/app/commandlineoptions.cpp new file mode 100644 index 000000000..ce7968bd6 --- /dev/null +++ b/src/app/commandlineoptions.cpp @@ -0,0 +1,100 @@ +#include "commandlineoptions.h" +#include "qupzilla.h" + +CommandLineOptions::CommandLineOptions(int &argc, char **argv) : + QObject(0) + ,m_actionString("") + ,m_argc(argc) + ,m_argv(argv) + ,m_action(NoAction) +{ + parseActions(); +} + +void CommandLineOptions::showHelp() +{ + using namespace std; + + const char* help= " Usage: qupzilla [options] URL \n" + "\n" + " QupZilla options:\n" + " -h or -help print this message \n" + " -a or -authors print QupZilla authors \n" + " -v or -version print QupZilla version \n" + " -p or -profile=PROFILE start with specified profile \n" + " -np or -no-plugins start without plugins \n" + "\n" + " QupZilla is a new, fast and secure web browser\n" + " based on WebKit core (http://webkit.org) and\n" + " written in Qt Framework (http://qt.nokia.com) \n" + ; + cout << help << " " << QupZilla::WWWADDRESS.toAscii().data() << endl; +} + +void CommandLineOptions::parseActions() +{ + using namespace std; + + bool found = false; + // Skip first argument (program itself) + for (int i = 1; i < m_argc; i++) { + QString arg(m_argv[i]); + if (arg == "-h" || arg == "-help") { + showHelp(); + found = true; + break; + } + if (arg == "-a" || arg == "-authors") { + cout << "QupZilla authors: " << endl; + cout << " nowrep " << endl; + found = true; + break; + } + if (arg == "-v" || arg == "-version") { + cout << "QupZilla v" << QupZilla::VERSION.toAscii().data() + << "(build " << QupZilla::BUILDTIME.toAscii().data() << ")" + << endl; + found = true; + break; + } + + if (arg.startsWith("-p=") || arg.startsWith("-profile=")) { + arg.remove("-p="); + arg.remove("-profile="); + found = true; + cout << "starting with profile " << arg.toAscii().data() << endl; + m_actionString = arg; + m_action = StartWithProfile; + } + + if (arg.startsWith("-np") || arg.startsWith("-no-plugins")) { + found = true; + m_action = StartWithoutAddons; + } + } + + QString url(m_argv[m_argc-1]); + if (m_argc > 1 && !url.isEmpty() && !url.startsWith("-")) { + found = true; + cout << "starting with url " << url.toAscii().data() << endl; + m_actionString = url; + m_action = OpenUrl; + } + + if (m_argc > 1 && !found) { + cout << "bad arguments!" << endl; + showHelp(); + } + +} +CommandLineOptions::Action CommandLineOptions::getAction() +{ + return m_action; +} + +QString CommandLineOptions::getActionString() +{ + return m_actionString; +} + + diff --git a/src/app/commandlineoptions.h b/src/app/commandlineoptions.h new file mode 100644 index 000000000..0182cdd9e --- /dev/null +++ b/src/app/commandlineoptions.h @@ -0,0 +1,31 @@ +#ifndef COMMANDLINEOPTIONS_H +#define COMMANDLINEOPTIONS_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include + +#include + +class CommandLineOptions : public QObject +{ + Q_OBJECT +public: + enum Action {NoAction, OpenUrl, StartWithProfile, StartWithoutAddons}; + explicit CommandLineOptions(int &argc, char **argv); + Action getAction(); + QString getActionString(); + +private: + void showHelp(); + void parseActions(); + + QString m_actionString; + int m_argc; + char **m_argv; + Action m_action; +}; + +#endif // COMMANDLINEOPTIONS_H diff --git a/src/app/mainapplication.cpp b/src/app/mainapplication.cpp new file mode 100644 index 000000000..ffcf3dbdc --- /dev/null +++ b/src/app/mainapplication.cpp @@ -0,0 +1,555 @@ +#include "mainapplication.h" +#include "qupzilla.h" +#include "tabwidget.h" +#include "bookmarkstoolbar.h" +#include "bookmarksmanager.h" +#include "cookiemanager.h" +#include "cookiejar.h" +#include "historymanager.h" +#include "historymodel.h" +#include "networkmanager.h" +#include "rssmanager.h" +#include "updater.h" +#include "autosaver.h" +#include "commandlineoptions.h" +#include "pluginproxy.h" +#include "bookmarksmodel.h" +#include "downloadmanager.h" +#include "autofillmodel.h" + +MainApplication::MainApplication(int &argc, char **argv) + : QtSingleApplication("qupzillaMainApp", argc, argv) + ,m_bookmarksmanager(0) + ,m_cookiemanager(0) + ,m_historymanager(0) + ,m_historymodel(0) + ,m_websettings(0) + ,m_networkmanager(0) + ,m_cookiejar(0) + ,m_rssmanager(0) + ,m_plugins(0) + ,m_bookmarksModel(0) + ,m_downloadManager(0) + ,m_autofill(0) + ,m_isClosing(false) + ,m_isChanged(false) + ,m_isExited(false) +{ +#if defined(Q_WS_X11) & !defined(DEVELOPING) + DATADIR = "/usr/share/qupzilla/"; +#else + DATADIR = qApp->applicationDirPath()+"/"; +#endif + setOverrideCursor(Qt::WaitCursor); + setWindowIcon(QIcon(":/icons/qupzilla.png")); + bool noAddons = false; + QUrl startUrl(""); + QString message; + if (argc > 1) { + CommandLineOptions cmd(argc, argv); + switch (cmd.getAction()) { + case CommandLineOptions::StartWithoutAddons: + noAddons = true; + break; + case CommandLineOptions::OpenUrl: + startUrl = QUrl(cmd.getActionString()); + message = "URL:"+startUrl.toString(); + break; + default: + m_isExited = true; + return; + break; + } + } + + if (isRunning()) { + sendMessage(message); + m_isExited = true; + return; + } + + connect(this, SIGNAL(messageReceived(QString)), this, SLOT(receiveAppMessage(QString))); + + setQuitOnLastWindowClosed(true); + setApplicationName("QupZilla"); + setApplicationVersion(QupZilla::VERSION); + setOrganizationDomain("qupzilla"); + + QString homePath = QDir::homePath(); + homePath+="/.qupzilla/"; + + checkProfileDir(); + + QSettings::setDefaultFormat(QSettings::IniFormat); + QSettings settings(homePath+"profiles/profiles.ini", QSettings::IniFormat); + if (settings.value("Profiles/startProfile","default").toString().contains("/")) + m_activeProfil=homePath+"profiles/default/"; + else + m_activeProfil=homePath+"profiles/"+settings.value("Profiles/startProfile","default").toString()+"/"; + if (!QDir(m_activeProfil).exists()) + m_activeProfil=homePath+"profiles/default/"; + + QSettings settings2(m_activeProfil+"settings.ini", QSettings::IniFormat); + settings2.beginGroup("SessionRestore"); + if (settings2.value("isRunning",false).toBool() ) + settings2.setValue("isCrashed", true); + settings2.setValue("isRunning", true); + settings2.endGroup(); + + QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, m_activeProfil); + + translateApp(); + connectDatabase(); + + QupZilla* qupzilla = new QupZilla(true, startUrl); + m_mainWindows.append(qupzilla); + connect(qupzilla, SIGNAL(message(MainApplication::MessageType,bool)), this, SLOT(sendMessages(MainApplication::MessageType,bool))); + qupzilla->show(); + + AutoSaver* saver = new AutoSaver(); + connect(saver, SIGNAL(saveApp()), this, SLOT(saveStateSlot())); + m_updater = new Updater(qupzilla); + + if (noAddons) { + settings2.setValue("Plugin-Settings/AllowedPlugins",QStringList()); + settings2.setValue("Plugin-Settings/EnablePlugins",false); + } + + networkManager()->loadCertExceptions(); + plugins()->loadPlugins(); + loadSettings(); +} + +void MainApplication::loadSettings() +{ + QSettings settings(m_activeProfil+"settings.ini", QSettings::IniFormat); + webSettings(); + //Web browsing settings + settings.beginGroup("Web-Browser-Settings"); + bool allowFlash = settings.value("allowFlash",true).toBool(); + bool allowJavaScript = settings.value("allowJavaScript",true).toBool(); + bool allowJavaScriptOpenWindow = settings.value("allowJavaScriptOpenWindow",false).toBool(); + bool allowJava = settings.value("allowJava",true).toBool(); + bool allowPersistentStorage = settings.value("allowPersistentStorage",true).toBool(); + bool allowImages = settings.value("autoLoadImages",true).toBool(); + bool dnsPrefetch = settings.value("DNS-Prefetch", false).toBool(); + bool jsClipboard = settings.value("JavaScriptCanAccessClipboard", true).toBool(); + bool linkInFocuschain = settings.value("IncludeLinkInFocusChain", false).toBool(); + bool zoomTextOnly = settings.value("zoomTextOnly", false).toBool(); + bool printElBg = settings.value("PrintElementBackground", true).toBool(); + int maxCachedPages = settings.value("maximumCachedPages",3).toInt(); + int scrollingLines = settings.value("wheelScrollLines", wheelScrollLines()).toInt(); + settings.endGroup(); + + m_websettings->setAttribute(QWebSettings::DeveloperExtrasEnabled, true); + m_websettings->setAttribute(QWebSettings::PluginsEnabled, allowFlash); + m_websettings->setAttribute(QWebSettings::JavascriptEnabled, allowJavaScript); + m_websettings->setAttribute(QWebSettings::JavascriptCanOpenWindows, allowJavaScriptOpenWindow); + m_websettings->setAttribute(QWebSettings::JavaEnabled, allowJava); + m_websettings->setAttribute(QWebSettings::AutoLoadImages, allowImages); + m_websettings->setAttribute(QWebSettings::DnsPrefetchEnabled, dnsPrefetch); + m_websettings->setAttribute(QWebSettings::JavascriptCanAccessClipboard, jsClipboard); + m_websettings->setAttribute(QWebSettings::LinksIncludedInFocusChain, linkInFocuschain); + m_websettings->setAttribute(QWebSettings::ZoomTextOnly, zoomTextOnly); + m_websettings->setAttribute(QWebSettings::PrintElementBackgrounds, printElBg); + + if (allowPersistentStorage) m_websettings->enablePersistentStorage(m_activeProfil); + m_websettings->setMaximumPagesInCache(maxCachedPages); + + setWheelScrollLines(scrollingLines); +} + +QupZilla* MainApplication::getWindow() +{ + QupZilla *active = qobject_cast(QApplication::activeWindow()); + if (active) + return active; + + for(int i=0; isetWindowState(actWin->windowState() & ~Qt::WindowMinimized); + actWin->raise(); + actWin->activateWindow(); + actWin->setFocus(); +} + +void MainApplication::addNewTab(QUrl url) +{ + if (!getWindow()) + return; + getWindow()->tabWidget()->addView(url); +} + +void MainApplication::makeNewWindow(bool tryRestore, const QUrl &startUrl) +{ + QupZilla* newWindow = new QupZilla(tryRestore, startUrl); + newWindow->show(); + connect(newWindow, SIGNAL(message(MainApplication::MessageType,bool)), this, SLOT(sendMessages(MainApplication::MessageType,bool))); + m_mainWindows.append(newWindow); +} + +void MainApplication::connectDatabase() +{ + QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); + db.setDatabaseName(m_activeProfil+"browsedata.db"); + if (!QFile::exists(m_activeProfil+"browsedata.db")) { + QFile(DATADIR+"data/default/profiles/default/browsedata.db").copy(m_activeProfil+"browsedata.db"); + qWarning("Cannot find SQLite database file! Copying and using the defaults!"); + } + if (!db.open()) + qWarning("Cannot open SQLite database! Continuing without database...."); + +} + +void MainApplication::translateApp() +{ + QLocale locale; + QSettings settings(m_activeProfil+"settings.ini", QSettings::IniFormat); + settings.beginGroup("Browser-Window-Settings"); + QString file = settings.value("language",locale.name()+".qm").toString(); + QString shortLoc = file.left(2); + + if (file == "" || !QFile::exists(DATADIR+"locale/"+file) ) + return; + + QTranslator* app = new QTranslator(); + app->load(DATADIR+"locale/"+file); + QTranslator* sys = new QTranslator(); + + if (QFile::exists(DATADIR+"locale/qt_"+shortLoc+".qm")) + sys->load(DATADIR+"locale/qt_"+shortLoc+".qm"); + + m_activeLanguage = file; + + installTranslator(app); + installTranslator(sys); +} + +void MainApplication::quitApplication() +{ + if (m_downloadManager && !m_downloadManager->canClose()) { + m_downloadManager->show(); + return; + } + + delete m_updater; + m_isClosing = true; + + if (m_mainWindows.count() > 0) + saveStateSlot(); + + qDebug() << __FUNCTION__ << "called"; + QSettings settings(m_activeProfil+"settings.ini", QSettings::IniFormat); + settings.beginGroup("SessionRestore"); + settings.setValue("isRunning",false); + settings.setValue("isCrashed", false); + settings.endGroup(); + + bool deleteCookies = settings.value("Web-Browser-Settings/deleteCookiesOnClose",false).toBool(); + bool deleteHistory = settings.value("Web-Browser-Settings/deleteHistoryOnClose",false).toBool(); + + if (deleteCookies) + QFile::remove(m_activeProfil+"cookies.dat"); + if (deleteHistory) { + QSqlQuery query; + query.exec("DELETE FROM history"); + query.exec("VACUUM"); + } + + cookieJar()->saveCookies(); + m_networkmanager->saveCertExceptions(); + m_plugins->c2f_saveSettings(); + + quit(); +} + +BookmarksManager* MainApplication::bookmarksManager() +{ + if (!m_bookmarksmanager) + m_bookmarksmanager = new BookmarksManager(getWindow()); + return m_bookmarksmanager; +} + +PluginProxy* MainApplication::plugins() +{ + if (!m_plugins) + m_plugins = new PluginProxy(); + return m_plugins; +} + +CookieManager* MainApplication::cookieManager() +{ + if (!m_cookiemanager) + m_cookiemanager = new CookieManager(); + return m_cookiemanager; +} + +HistoryManager* MainApplication::historyManager() +{ + if (!m_historymanager) + m_historymanager = new HistoryManager(getWindow()); + return m_historymanager; +} + +HistoryModel* MainApplication::history() +{ + if (!m_historymodel) + m_historymodel = new HistoryModel(getWindow()); + return m_historymodel; +} + +QWebSettings* MainApplication::webSettings() +{ + if (!m_websettings) + m_websettings = QWebSettings::globalSettings(); + return m_websettings; +} + +NetworkManager* MainApplication::networkManager() +{ + if (!m_networkmanager) + m_networkmanager = new NetworkManager(getWindow()); + return m_networkmanager; +} + +CookieJar* MainApplication::cookieJar() +{ + if (!m_cookiejar) { + m_cookiejar = new CookieJar(getWindow()); + m_cookiejar->restoreCookies(); + } + return m_cookiejar; +} + +RSSManager* MainApplication::rssManager() +{ + if (!m_rssmanager) + m_rssmanager = new RSSManager(getWindow()); + return m_rssmanager; +} + +BookmarksModel* MainApplication::bookmarks() +{ + if (!m_bookmarksModel) + m_bookmarksModel = new BookmarksModel(); + return m_bookmarksModel; +} + +DownloadManager* MainApplication::downManager() +{ + if (!m_downloadManager) + m_downloadManager = new DownloadManager(); + return m_downloadManager; +} + +AutoFillModel* MainApplication::autoFill() +{ + if (!m_autofill) + m_autofill = new AutoFillModel(getWindow()); + return m_autofill; +} + +void MainApplication::aboutToCloseWindow(QupZilla *window) +{ + if (!window) + return; + + m_mainWindows.removeOne(window); + if (m_mainWindows.count() == 0 ) + quitApplication(); +} + +//Version of sessin.dat file +static const int sessionVersion = 0x0002; + +bool MainApplication::saveStateSlot() +{ + if (m_websettings->testAttribute(QWebSettings::PrivateBrowsingEnabled)) + return false; + + qDebug() << "Saving state"; + + QSettings settings(m_activeProfil+"settings.ini", QSettings::IniFormat); + settings.beginGroup("SessionRestore"); + settings.setValue("restoreSession",false); + + QFile file(m_activeProfil+"session.dat"); + file.open(QIODevice::WriteOnly); + QDataStream stream(&file); + + stream << sessionVersion; + stream << m_mainWindows.count(); + for (int i = 0; i < m_mainWindows.count(); i++) { + stream << m_mainWindows.at(i)->tabWidget()->saveState(); + stream << m_mainWindows.at(i)->saveState(); + } + file.close(); + + settings.setValue("restoreSession",true); + settings.endGroup(); + + QupZilla* qupzilla_ = getWindow(); + if (qupzilla_) { + settings.setValue("Browser-View-Settings/showBookmarksToolbar",qupzilla_->bookmarksToolbar()->isVisible()); + settings.setValue("Browser-View-Settings/showNavigationToolbar",qupzilla_->navigationToolbar()->isVisible()); + settings.setValue("Browser-View-Settings/showStatusbar",qupzilla_->statusBar()->isVisible()); + settings.setValue("Browser-View-Settings/showMenubar",qupzilla_->menuBar()->isVisible()); + } + return true; +} + +bool MainApplication::restoreStateSlot(QupZilla *window) +{ + QSettings settings(m_activeProfil+"settings.ini", QSettings::IniFormat); + settings.beginGroup("SessionRestore"); + if (!settings.value("restoreSession",false).toBool()) + return false; + if (settings.value("isCrashed",false).toBool()) { + QMessageBox::StandardButton button = QMessageBox::warning(window, tr("Last session crashed"), + tr("QupZilla crashed :-(
Oops, last session of QupZilla ends with its crash. We are very sorry. Would you try to restore saved state?"), + QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); + if (button != QMessageBox::Yes) + return false; + } + if (!QFile::exists(m_activeProfil+"session.dat")) + return false; + + settings.setValue("isCrashed",false); + QFile file(m_activeProfil+"session.dat"); + file.open(QIODevice::ReadOnly); + QDataStream stream(&file); + + QByteArray tabState; + QByteArray qMainWindowState; + int version; + int windowCount; + + stream >> version; + if (version != sessionVersion) + return false; + stream >> windowCount; + stream >> tabState; + stream >> qMainWindowState; + + file.close(); + + window->tabWidget()->restoreState(tabState); + window->restoreState(qMainWindowState); + + settings.endGroup(); + + if (windowCount > 1) { + for (int i = 0; i<(windowCount-1); i++) { + stream >> tabState; + stream >> qMainWindowState; + + QupZilla* window = new QupZilla(false); + m_mainWindows.append(window); + connect(window, SIGNAL(message(MainApplication::MessageType,bool)), this, SLOT(sendMessages(MainApplication::MessageType,bool))); + QEventLoop eLoop; + connect(window, SIGNAL(startingCompleted()), &eLoop, SLOT(quit())); + eLoop.exec(); + + window->tabWidget()->restoreState(tabState); + window->restoreState(qMainWindowState); + window->tabWidget()->closeTab(0); + window->show(); + } + } + + return true; +} + +bool MainApplication::checkProfileDir() +{ + /* + $HOMEDIR + | + .qupzilla/ + | + profiles/----------- + | | + default/ profiles.ini + | + browsedata.db + */ + QString homePath = QDir::homePath(); + homePath+="/.qupzilla/"; + + if (QDir(homePath).exists()) { + QFile versionFile(homePath+"version"); + versionFile.open(QFile::ReadOnly); + if (versionFile.readAll().contains(QupZilla::VERSION.toAscii())) { + versionFile.close(); + return true; + } + versionFile.close(); +#ifdef DEVELOPING + return true; +#endif + } + + std::cout << "Creating new profile directory" << std::endl; + + QDir dir = QDir::home(); + dir.mkdir(".qupzilla"); + dir.cd(".qupzilla"); + + //.qupzilla + QFile(homePath+"version").remove(); + QFile versionFile(homePath+"version"); + versionFile.open(QFile::WriteOnly); + versionFile.write(QupZilla::VERSION.toAscii()); + versionFile.close(); + + dir.mkdir("profiles"); + dir.cd("profiles"); + + //.qupzilla/profiles + QFile(homePath+"profiles/profiles.ini").remove(); + QFile(DATADIR+"data/default/profiles/profiles.ini").copy(homePath+"profiles/profiles.ini"); + + dir.mkdir("default"); + dir.cd("default"); + + //.qupzilla/profiles/default + QFile(homePath+"profiles/default/browsedata.db").remove(); + QFile(DATADIR+"data/default/profiles/default/browsedata.db").copy(homePath+"profiles/default/browsedata.db"); + QFile(homePath+"profiles/default/background.png").remove(); + QFile(DATADIR+"data/default/profiles/default/background.png").copy(homePath+"profiles/default/background.png"); + + return dir.isReadable(); +} diff --git a/src/app/mainapplication.h b/src/app/mainapplication.h new file mode 100644 index 000000000..51fdcb330 --- /dev/null +++ b/src/app/mainapplication.h @@ -0,0 +1,108 @@ +#ifndef MAINAPPLICATION_H +#define MAINAPPLICATION_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include +#include + +#include "qtsingleapplication.h" + +class QupZilla; +class BookmarksManager; +class CookieManager; +class HistoryManager; +class HistoryModel; +class NetworkManager; +class CookieJar; +class RSSManager; +class Updater; +class PluginProxy; +class BookmarksModel; +class DownloadManager; +class AutoFillModel; + +class MainApplication : public QtSingleApplication +{ + Q_OBJECT + +public: + QString DATADIR; + explicit MainApplication(int &argc, char **argv); + + enum MessageType{ ShowFlashIcon, CheckPrivateBrowsing }; + + void loadSettings(); + bool restoreStateSlot(QupZilla* window); + void makeNewWindow(bool tryRestore, const QUrl &startUrl=QUrl()); + void addNewTab(QUrl url); + void aboutToCloseWindow(QupZilla* window); + bool isChanged(); + + inline static MainApplication* getInstance() { return static_cast(QCoreApplication::instance()); } + inline QString getActiveProfil() { return m_activeProfil; } + inline QString getActiveLanguage() { return m_activeLanguage; } + inline bool isClosing() { return m_isClosing; } + inline bool isExited() { return m_isExited; } + + bool checkProfileDir(); + + QupZilla* getWindow(); + BookmarksManager* bookmarksManager(); + CookieManager* cookieManager(); + HistoryManager* historyManager(); + HistoryModel* history(); + QWebSettings* webSettings(); + NetworkManager* networkManager(); + CookieJar* cookieJar(); + RSSManager* rssManager(); + PluginProxy* plugins(); + BookmarksModel* bookmarks(); + DownloadManager* downManager(); + AutoFillModel* autoFill(); + +public slots: + bool saveStateSlot(); + void quitApplication(); + void sendMessages(MainApplication::MessageType mes, bool state); + void receiveAppMessage(QString message); + inline void setChanged() { m_isChanged = true; } + +signals: + void message(MainApplication::MessageType mes, bool state); + +private: + void connectDatabase(); + void translateApp(); + void restoreOtherWindows(); + + BookmarksManager* m_bookmarksmanager; + CookieManager* m_cookiemanager; + HistoryManager* m_historymanager; + HistoryModel* m_historymodel; + QWebSettings* m_websettings; + NetworkManager* m_networkmanager; + CookieJar* m_cookiejar; + RSSManager* m_rssmanager; + Updater* m_updater; + PluginProxy* m_plugins; + BookmarksModel* m_bookmarksModel; + DownloadManager* m_downloadManager; + AutoFillModel* m_autofill; + + QList > m_mainWindows; + + QString m_activeProfil; + QString m_activeLanguage; + + bool m_isClosing; + bool m_isChanged; + bool m_isExited; +}; + +#endif // MAINAPPLICATION_H diff --git a/src/app/qupzilla.cpp b/src/app/qupzilla.cpp new file mode 100644 index 000000000..e9770e699 --- /dev/null +++ b/src/app/qupzilla.cpp @@ -0,0 +1,703 @@ +#include "qupzilla.h" +#include "tabwidget.h" +#include "tabbar.h" +#include "webpage.h" +#include "webview.h" +#include "lineedit.h" +#include "historymodel.h" +#include "locationbar.h" +#include "searchtoolbar.h" +#include "websearchbar.h" +#include "downloadmanager.h" +#include "cookiejar.h" +#include "cookiemanager.h" +#include "historymanager.h" +#include "bookmarksmanager.h" +#include "bookmarkstoolbar.h" +#include "clearprivatedata.h" +#include "sourceviewer.h" +#include "siteinfo.h" +#include "preferences.h" +#include "networkmanager.h" +#include "autofillmodel.h" +#include "networkmanagerproxy.h" +#include "rssmanager.h" +#include "mainapplication.h" +#include "aboutdialog.h" +#include "pluginproxy.h" +#include "qtwin.h" + +const QString QupZilla::VERSION="0.9.7"; +const QString QupZilla::BUILDTIME="03/05/2011 14:48"; +const QString QupZilla::AUTHOR="nowrep"; +const QString QupZilla::COPYRIGHT="2010-2011"; +const QString QupZilla::WWWADDRESS="http://qupzilla.ic.cz"; +const QString QupZilla::WEBKITVERSION=qWebKitVersion(); + +QupZilla::QupZilla(bool tryRestore, QUrl startUrl) : + QMainWindow() + ,p_mainApp(MainApplication::getInstance()) + ,m_tryRestore(tryRestore) + ,m_startingUrl(startUrl) + ,m_actionPrivateBrowsing(0) + ,m_webInspectorDock(0) + ,m_webSearchToolbar(0) +{ + this->resize(640,480); + this->setWindowState(Qt::WindowMaximized); + this->setWindowTitle("QupZilla"); + setUpdatesEnabled(false); + + m_activeProfil = p_mainApp->getActiveProfil(); + m_activeLanguage = p_mainApp->getActiveLanguage(); + + QDesktopServices::setUrlHandler("http", this, "loadAddress"); + + setupUi(); + setupMenu(); + QTimer::singleShot(0, this, SLOT(postLaunch())); + connect(p_mainApp, SIGNAL(message(MainApplication::MessageType,bool)), this, SLOT(receiveMessage(MainApplication::MessageType,bool))); +} + +void QupZilla::loadSettings() +{ + QSettings settings(m_activeProfil+"settings.ini", QSettings::IniFormat); + + //Url settings + settings.beginGroup("Web-URL-Settings"); + m_homepage = settings.value("homepage","http://qupzilla.ic.cz/search/").toUrl(); + m_newtab = settings.value("newTabUrl","").toUrl(); + settings.endGroup(); + + QWebSettings* websettings=p_mainApp->webSettings(); + websettings->setAttribute(QWebSettings::JavascriptCanAccessClipboard, true); + //Web browsing settings + settings.beginGroup("Web-Browser-Settings"); + bool allowFlash = settings.value("allowFlash",true).toBool(); + settings.endGroup(); + m_allowFlashIcon->setVisible(allowFlash); + + //Browser Window settings + settings.beginGroup("Browser-View-Settings"); + m_menuTextColor = settings.value("menuTextColor", QColor(Qt::black)).value(); + setBackground(m_menuTextColor); + m_bookmarksToolbar->setColor(m_menuTextColor); + m_ipLabel->setStyleSheet("QLabel {color: "+m_menuTextColor.name()+";}"); + bool showStatusBar = settings.value("showStatusBar",true).toBool(); + bool showHomeIcon = settings.value("showHomeButton",true).toBool(); + bool showBackForwardIcons = settings.value("showBackForwardButtons",true).toBool(); + bool showBookmarksToolbar = settings.value("showBookmarksToolbar",true).toBool(); + bool showNavigationToolbar = settings.value("showNavigationToolbar",true).toBool(); + bool showMenuBar = settings.value("showMenubar",true).toBool(); + bool makeTransparent = settings.value("useTransparentBackground",false).toBool(); + settings.endGroup(); + + statusBar()->setVisible(showStatusBar); + m_actionShowStatusbar->setChecked(showStatusBar); + + m_bookmarksToolbar->setVisible(showBookmarksToolbar); + m_actionShowBookmarksToolbar->setChecked(showBookmarksToolbar); + + m_navigation->setVisible(showNavigationToolbar); + m_actionShowToolbar->setChecked(showNavigationToolbar); + + m_actionShowMenubar->setChecked(showMenuBar); + menuBar()->setVisible(showMenuBar); + m_navigation->actions().at(m_navigation->actions().count()-2)->setVisible(!showMenuBar); + + m_buttonHome->setVisible(showHomeIcon); + m_buttonBack->setVisible(showBackForwardIcons); + m_buttonNext->setVisible(showBackForwardIcons); + + //Private browsing + m_actionPrivateBrowsing->setChecked( p_mainApp->webSettings()->testAttribute(QWebSettings::PrivateBrowsingEnabled) ); + m_privateBrowsing->setVisible( p_mainApp->webSettings()->testAttribute(QWebSettings::PrivateBrowsingEnabled) ); + + if (!makeTransparent) + return; + //Opacity +#ifdef Q_WS_X11 + setAttribute(Qt::WA_TranslucentBackground); + setAttribute(Qt::WA_NoSystemBackground, false); + QPalette pal = palette(); + QColor bg = pal.window().color(); + bg.setAlpha(180); + pal.setColor(QPalette::Window, bg); + setPalette(pal); + ensurePolished(); // workaround Oxygen filling the background + setAttribute(Qt::WA_StyledBackground, false); +#endif + if (QtWin::isCompositionEnabled()) { + QtWin::extendFrameIntoClientArea(this); + setContentsMargins(0, 0, 0, 0); + } + setWindowIcon(QIcon(":/icons/qupzilla.png")); +} + +void QupZilla::receiveMessage(MainApplication::MessageType mes, bool state) +{ + switch (mes) { + case MainApplication::ShowFlashIcon: + m_allowFlashIcon->setVisible(state); + break; + + case MainApplication::CheckPrivateBrowsing: + m_privateBrowsing->setVisible(state); + m_actionPrivateBrowsing->setChecked(state); + break; + + default: + qWarning() << "Unresolved message sent!"; + break; + } +} + +void QupZilla::refreshHistory(int index) +{ + QWebHistory* history; + if (index == -1) + history = weView()->page()->history(); + else + history = weView()->page()->history(); + + if (history->canGoBack()) { + m_buttonBack->setEnabled(true); + }else{ + m_buttonBack->setEnabled(false); + } + + if (history->canGoForward()) { + m_buttonNext->setEnabled(true); + }else{ + m_buttonNext->setEnabled(false); + } +} + +void QupZilla::goAtHistoryIndex() +{ + if (QAction *action = qobject_cast(sender())) { + weView()->page()->history()->goToItem(weView()->page()->history()->itemAt(action->data().toInt())); + } + refreshHistory(); +} + +void QupZilla::aboutToShowHistoryBackMenu() +{ + if (!m_menuBack || !weView()) + return; + m_menuBack->clear(); + QWebHistory* history = weView()->history(); + int curindex = history->currentItemIndex(); + for (int i = curindex-1;i>=0;i--) { + QWebHistoryItem item = history->itemAt(i); + if (item.isValid()) { + QString title = item.title(); + if (title.length()>40) { + title.truncate(40); + title+=".."; + } + QAction* action = m_menuBack->addAction(m_locationBar->icon(item.url()),title, this, SLOT(goAtHistoryIndex())); + action->setData(i); + } + } +} + +void QupZilla::aboutToShowHistoryNextMenu() +{ + if (!m_menuForward || !weView()) + return; + m_menuForward->clear(); + QWebHistory* history = weView()->history(); + int curindex = history->currentItemIndex(); + for (int i = curindex+1;icount();i++) { + QWebHistoryItem item = history->itemAt(i); + if (item.isValid()) { + QString title = item.title(); + if (title.length()>40) { + title.truncate(40); + title+=".."; + } + QAction* action = m_menuForward->addAction(m_locationBar->icon(item.url()),title, this, SLOT(goAtHistoryIndex())); + action->setData(i); + } + } +} + +void QupZilla::aboutToShowBookmarksMenu() +{ + m_menuBookmarks->clear(); + m_menuBookmarks->addAction(tr("Bookmark This Page"), this, SLOT(bookmarkPage()))->setShortcut(QKeySequence("Ctrl+D")); + m_menuBookmarks->addAction(tr("Bookmark All Tabs"), this, SLOT(bookmarkAllTabs())); + m_menuBookmarks->addAction(QIcon::fromTheme("user-bookmarks"), tr("Organize Bookmarks"), this, SLOT(showBookmarksManager()))->setShortcut(QKeySequence("Ctrl+Shift+O")); + m_menuBookmarks->addSeparator(); + if (m_tabWidget->count() == 1) + m_menuBookmarks->actions().at(1)->setEnabled(false); + QSqlQuery query; + query.exec("SELECT title, url FROM bookmarks WHERE folder='bookmarksMenu'"); + while(query.next()) { + QUrl url = query.value(1).toUrl(); + QString title = query.value(0).toString(); + if (title.length()>40) { + title.truncate(40); + title+=".."; + } + m_menuBookmarks->addAction(LocationBar::icon(url), title, this, SLOT(loadActionUrl()))->setData(url); + } + + QMenu* folderBookmarks = new QMenu(tr("Bookmarks In ToolBar"), m_menuBookmarks); + folderBookmarks->setIcon(QIcon(style()->standardIcon(QStyle::SP_DirOpenIcon))); + + query.exec("SELECT title, url FROM bookmarks WHERE folder='bookmarksToolbar'"); + while(query.next()) { + QUrl url = query.value(1).toUrl(); + QString title = query.value(0).toString(); + if (title.length()>40) { + title.truncate(40); + title+=".."; + } + folderBookmarks->addAction(LocationBar::icon(url), title, this, SLOT(loadActionUrl()))->setData(url); + } + if (folderBookmarks->isEmpty()) + folderBookmarks->addAction(tr("Empty")); + m_menuBookmarks->addMenu(folderBookmarks); + + query.exec("SELECT name FROM folders"); + while(query.next()) { + QMenu* tempFolder = new QMenu(query.value(0).toString(), m_menuBookmarks); + tempFolder->setIcon(QIcon(style()->standardIcon(QStyle::SP_DirOpenIcon))); + + QSqlQuery query2; + query2.exec("SELECT title, url FROM bookmarks WHERE folder='"+query.value(0).toString()+"'"); + while(query2.next()) { + QUrl url = query2.value(1).toUrl(); + QString title = query2.value(0).toString(); + if (title.length()>40) { + title.truncate(40); + title+=".."; + } + tempFolder->addAction(LocationBar::icon(url), title, this, SLOT(loadActionUrl()))->setData(url); + } + if (tempFolder->isEmpty()) + tempFolder->addAction(tr("Empty")); + m_menuBookmarks->addMenu(tempFolder); + } + +} + +void QupZilla::aboutToShowHistoryMenu() +{ + if (!weView()) + return; + m_menuHistory->clear(); + m_menuHistory->addAction( +#ifdef Q_WS_X11 + style()->standardIcon(QStyle::SP_ArrowBack) +#else + QIcon(":/icons/faenza/back.png") +#endif + , tr("Back"), this, SLOT(goBack()))->setShortcut(QKeySequence("Ctrl+Left")); + m_menuHistory->addAction( +#ifdef Q_WS_X11 + style()->standardIcon(QStyle::SP_ArrowForward) +#else + QIcon(":/icons/faenza/forward.png") +#endif + , tr("Forward"), this, SLOT(goNext()))->setShortcut(QKeySequence("Ctrl+Right")); + m_menuHistory->addAction( +#ifdef Q_WS_X11 + QIcon::fromTheme("go-home") +#else + QIcon(":/icons/faenza/home.png") +#endif + , tr("Home"), this, SLOT(goHome()))->setShortcut(QKeySequence("Alt+Home")); + + if (!weView()->history()->canGoBack()) + m_menuHistory->actions().at(0)->setEnabled(false); + if (!weView()->history()->canGoForward()) + m_menuHistory->actions().at(1)->setEnabled(false); + + m_menuHistory->addAction(QIcon(":/icons/menu/history.png"), tr("Show All History"), this, SLOT(showHistoryManager()))->setShortcut(QKeySequence("Ctrl+H")); + m_menuHistory->addSeparator(); + + QSqlQuery query; + query.exec("SELECT title, url FROM history ORDER BY date DESC LIMIT 10"); + while(query.next()) { + QUrl url = query.value(1).toUrl(); + QString title = query.value(0).toString(); + if (title.length()>40) { + title.truncate(40); + title+=".."; + } + m_menuHistory->addAction(LocationBar::icon(url), title, this, SLOT(loadActionUrl()))->setData(url); + } +} + +void QupZilla::aboutToShowHelpMenu() +{ + m_menuHelp->clear(); + m_menuHelp->addAction(tr("Report Bug"), this, SLOT(reportBug())); + m_menuHelp->addSeparator(); + p_mainApp->plugins()->populateHelpMenu(m_menuHelp); + m_menuHelp->addAction(QIcon(":/icons/menu/qt.png"), tr("About Qt"), qApp, SLOT(aboutQt())); + m_menuHelp->addAction(QIcon(":/icons/qupzilla.png"), tr("About QupZilla"), this, SLOT(aboutQupZilla())); +} + +void QupZilla::aboutToShowToolsMenu() +{ + m_menuTools->clear(); + m_menuTools->addAction(tr("Web Search"), this, SLOT(webSearch()))->setShortcut(QKeySequence("Ctrl+K")); + m_menuTools->addAction(QIcon::fromTheme("dialog-information"), tr("Page Info"), this, SLOT(showPageInfo()))->setShortcut(QKeySequence("Ctrl+I")); + m_menuTools->addSeparator(); + m_menuTools->addAction(tr("Download Manager"), this, SLOT(showDownloadManager()))->setShortcut(QKeySequence("Ctrl+Y")); + m_menuTools->addAction(tr("Cookies Manager"), this, SLOT(showCookieManager())); + m_menuTools->addAction(QIcon(":/icons/menu/rss.png"), tr("RSS Reader"), this, SLOT(showRSSManager())); + m_menuTools->addAction(QIcon::fromTheme("edit-clear"), tr("Clear Recent History"), this, SLOT(showClearPrivateData())); + m_actionPrivateBrowsing = new QAction(tr("Private Browsing"), this); + m_actionPrivateBrowsing->setCheckable(true); + m_actionPrivateBrowsing->setChecked(p_mainApp->webSettings()->testAttribute(QWebSettings::PrivateBrowsingEnabled)); + connect(m_actionPrivateBrowsing, SIGNAL(triggered(bool)), this, SLOT(startPrivate(bool))); + m_menuTools->addAction(m_actionPrivateBrowsing); + m_menuTools->addSeparator(); + p_mainApp->plugins()->populateToolsMenu(m_menuTools); + m_menuTools->addAction(QIcon(":/icons/faenza/settings.png"), tr("Preferences"), this, SLOT(showPreferences()))->setShortcut(QKeySequence("Ctrl+P")); +} + +void QupZilla::aboutToShowViewMenu() +{ + if (!weView()) + return; + + if (weView()->isLoading()) + m_actionStop->setEnabled(true); + else + m_actionStop->setEnabled(false); +} + +void QupZilla::bookmarkPage() +{ + p_mainApp->bookmarksManager()->addBookmark(weView()); +} + +void QupZilla::addBookmark(const QUrl &url, const QString &title) +{ + p_mainApp->bookmarksManager()->insertBookmark(url, title); +} + +void QupZilla::bookmarkAllTabs() +{ + p_mainApp->bookmarksManager()->insertAllTabs(); +} + +void QupZilla::loadActionUrl() +{ + if (QAction *action = qobject_cast(sender())) { + loadAddress(action->data().toUrl()); + } +} + +void QupZilla::urlEnter() +{ + if (m_locationBar->text().isEmpty()) + return; + loadAddress(QUrl(WebView::guessUrlFromString(m_locationBar->text()))); + weView()->setFocus(); +} + +void QupZilla::showCookieManager() +{ + CookieManager* m = p_mainApp->cookieManager(); + m->refreshTable(); + m->show(); +} + +void QupZilla::showHistoryManager() +{ + HistoryManager* m = p_mainApp->historyManager(); + m->refreshTable(); + m->setMainWindow(this); + m->show(); +} + +void QupZilla::showRSSManager() +{ + RSSManager* m = p_mainApp->rssManager(); + m->refreshTable(); + m->setMainWindow(this); + m->show(); +} + +void QupZilla::showBookmarksManager() +{ + BookmarksManager* m = p_mainApp->bookmarksManager(); + m->refreshTable(); + m->setMainWindow(this); + m->show(); +} + +void QupZilla::showClearPrivateData() +{ + ClearPrivateData clear(this, this); + clear.exec(); +} + +void QupZilla::showDownloadManager() +{ + MainApplication::getInstance()->downManager()->show(); +} + +void QupZilla::showPreferences() +{ + bool flashIconVisibility = m_allowFlashIcon->isVisible(); + Preferences prefs(this, this); + prefs.exec(); + + if (flashIconVisibility != m_allowFlashIcon->isVisible()) + emit message(MainApplication::ShowFlashIcon, m_allowFlashIcon->isVisible()); +} + +void QupZilla::showSource() +{ + SourceViewer* source = new SourceViewer(this); + source->setAttribute(Qt::WA_DeleteOnClose); + source->show(); +} + +void QupZilla::showPageInfo() +{ + SiteInfo* info = new SiteInfo(this, this); + info->setAttribute(Qt::WA_DeleteOnClose); + info->show(); +} + +void QupZilla::showBookmarksToolbar() +{ + if (m_bookmarksToolbar->isVisible()) { + m_bookmarksToolbar->setVisible(false); + m_actionShowBookmarksToolbar->setChecked(false); + }else{ + m_bookmarksToolbar->setVisible(true); + m_actionShowBookmarksToolbar->setChecked(true); + } +} + +void QupZilla::showNavigationToolbar() +{ + if (!menuBar()->isVisible() && !m_actionShowToolbar->isChecked()) + showMenubar(); + + if (m_navigation->isVisible()) { + m_navigation->setVisible(false); + m_actionShowToolbar->setChecked(false); + }else{ + m_navigation->setVisible(true); + m_actionShowToolbar->setChecked(true); + } +} + +void QupZilla::showMenubar() +{ + if (!m_navigation->isVisible() && !m_actionShowMenubar->isChecked()) + showNavigationToolbar(); + + menuBar()->setVisible(!menuBar()->isVisible()); + m_navigation->actions().at(m_navigation->actions().count()-2)->setVisible(!menuBar()->isVisible()); + m_actionShowMenubar->setChecked(menuBar()->isVisible()); +} + +void QupZilla::showStatusbar() +{ + if (statusBar()->isVisible()) { + statusBar()->setVisible(false); + m_actionShowStatusbar->setChecked(false); + }else{ + statusBar()->setVisible(true); + m_actionShowStatusbar->setChecked(true); + } +} + +void QupZilla::showInspector() +{ + if (!m_webInspectorDock) { + m_webInspectorDock = new QDockWidget(this); + if (m_webInspector) + delete m_webInspector; + m_webInspector = new QWebInspector(this); + m_webInspector->setPage(weView()->page()); + addDockWidget(Qt::BottomDockWidgetArea, m_webInspectorDock); + m_webInspectorDock->setWindowTitle(tr("Web Inspector")); + m_webInspectorDock->setObjectName("WebInspector"); + m_webInspectorDock->setWidget(m_webInspector); + m_webInspectorDock->setFeatures(QDockWidget::DockWidgetClosable); + m_webInspectorDock->setContextMenuPolicy(Qt::CustomContextMenu); + } else if (m_webInspectorDock->isVisible()) { //Next tab + m_webInspectorDock->show(); + m_webInspector->setPage(weView()->page()); + m_webInspectorDock->setWidget(m_webInspector); + } else { //Showing hidden dock + m_webInspectorDock->show(); + if (m_webInspector->page() != weView()->page()) { + m_webInspector->setPage(weView()->page()); + m_webInspectorDock->setWidget(m_webInspector); + } + } +} + +void QupZilla::aboutQupZilla() +{ + AboutDialog about(this); + about.exec(); +} + +void QupZilla::searchOnPage() +{ + if (!m_webSearchToolbar) { + m_webSearchToolbar = new SearchToolBar(this); + addToolBar(Qt::BottomToolBarArea, m_webSearchToolbar); + m_webSearchToolbar->showBar(); + return; + } + if (m_webSearchToolbar->isVisible()) { + m_webSearchToolbar->hideBar(); + weView()->setFocus(); + }else{ + m_webSearchToolbar->showBar(); + } +} + +void QupZilla::openFile() +{ + QString filePath = QFileDialog::getOpenFileName(this, tr("Open file..."), QDir::homePath(), "(*.html *.htm *.jpg *.png)"); + if (!filePath.isEmpty()) + loadAddress(QUrl(filePath)); +} + +void QupZilla::fullScreen(bool make) +{ + if (make) { + m_menuBarVisible = menuBar()->isVisible(); + m_statusBarVisible = statusBar()->isVisible(); + setWindowState(windowState() | Qt::WindowFullScreen); + menuBar()->hide(); + statusBar()->hide(); + }else{ + setWindowState(windowState() & ~Qt::WindowFullScreen); + if (m_menuBarVisible) + showMenubar(); + if (m_statusBarVisible) + showStatusbar(); + } + m_actionShowFullScreen->setChecked(make); + m_actionExitFullscreen->setVisible(make); +} + +void QupZilla::savePage() +{ + QNetworkRequest request(weView()->url()); + + DownloadManager* dManager = MainApplication::getInstance()->downManager(); + dManager->download(request); +} + +void QupZilla::printPage() +{ + QPrintPreviewDialog* dialog = new QPrintPreviewDialog(this); + connect(dialog, SIGNAL(paintRequested(QPrinter*)), weView(), SLOT(print(QPrinter*))); + dialog->exec(); + delete dialog; +} + +void QupZilla::startPrivate(bool state) +{ + if (state) { + QString title = tr("Are you sure you want to turn on private browsing?"); + QString text1 = tr("When private browsing is turned on, some actions concerning your privacy will be disabled:"); + + QStringList actions; + actions.append(tr("Webpages are not added to the history.")); + actions.append(tr("New cookies are not stored, but current cookies can be accessed.")); + actions.append(tr("Your session won't be stored.")); + + QString text2 = tr("Until you close the window, you can still click the Back and Forward " + "buttons to return to the webpages you have opened."); + + QString message = QString(QLatin1String("%1

%2

  • %3

%4

")).arg(title, text1, actions.join(QLatin1String("
  • ")), text2); + + QMessageBox::StandardButton button = QMessageBox::question(this, tr("Start Private Browsing"), + message, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); + if (button != QMessageBox::Yes) + return; + } + p_mainApp->webSettings()->setAttribute(QWebSettings::PrivateBrowsingEnabled, state); + p_mainApp->history()->setSaving(!state); + p_mainApp->cookieJar()->setAllowCookies(!state); + emit message(MainApplication::CheckPrivateBrowsing, state); +} + +void QupZilla::closeEvent(QCloseEvent* event) +{ + if (p_mainApp->isClosing()) + return; + + QSettings settings(m_activeProfil+"settings.ini", QSettings::IniFormat); + settings.beginGroup("Web-URL-Settings"); + + if (settings.value("afterLaunch",0).toInt()!=2 && m_tabWidget->count()>1) { + QMessageBox::StandardButton button = QMessageBox::warning(this, tr("There are still open tabs"), + tr("There are still %1 open tabs and your session won't be stored. Are you sure to quit?").arg(m_tabWidget->count()), QMessageBox::Yes | QMessageBox::No); + if (button != QMessageBox::Yes) { + event->ignore(); + return; + } + } + settings.endGroup(); + + p_mainApp->cookieJar()->saveCookies(); + p_mainApp->saveStateSlot(); + p_mainApp->aboutToCloseWindow(this); + + this->~QupZilla(); + event->accept(); +} + +void QupZilla::quitApp() +{ + QSettings settings(m_activeProfil+"settings.ini", QSettings::IniFormat); + settings.beginGroup("Web-URL-Settings"); + + if (settings.value("afterLaunch",0).toInt()!=2 && m_tabWidget->count()>1) { + QMessageBox::StandardButton button = QMessageBox::warning(this, tr("There are still open tabs"), + tr("There are still %1 open tabs and your session won't be stored. Are you sure to quit?").arg(m_tabWidget->count()), QMessageBox::Yes | QMessageBox::No); + if (button != QMessageBox::Yes) + return; + } + settings.endGroup(); + + p_mainApp->quitApplication(); +} + +QupZilla::~QupZilla() +{ + delete m_tabWidget; + delete m_privateBrowsing; + delete m_allowFlashIcon; + delete m_menuBack; + delete m_menuForward; + delete m_locationBar; + delete m_searchLine; + delete m_bookmarksToolbar; + delete m_webSearchToolbar; + delete m_buttonBack; + delete m_buttonNext; + delete m_buttonHome; + delete m_buttonStop; + delete m_buttonReload; + delete m_actionExitFullscreen; + delete m_navigationSplitter; + delete m_navigation; + delete m_progressBar; + + if (m_webInspectorDock) { + delete m_webInspector; + delete m_webInspectorDock; + } +} diff --git a/src/app/qupzilla.h b/src/app/qupzilla.h new file mode 100644 index 000000000..5eb3fc3b4 --- /dev/null +++ b/src/app/qupzilla.h @@ -0,0 +1,234 @@ +#ifndef QUPZILLA_H +#define QUPZILLA_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +//Comment for release building +#define DEVELOPING +//Check if i don't fuck anything + +#ifdef QT_NO_DEBUG +#ifdef DEVELOPING +#error "TRYING TO RELEASE WITH DEVELOPING FLAG" +#endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qwebkitversion.h" + +#include "webtab.h" +#include "webview.h" +#include "tabwidget.h" +#include "locationbar.h" +#include "mainapplication.h" +#include "websearchbar.h" + +class TabWidget; +class WebView; +class LineEdit; +class LocationBar; +class SearchToolBar; +class WebSearchBar; +class BookmarksToolbar; +class AutoFillModel; +class MainApplication; +class WebTab; +class QupZilla : public QMainWindow +{ + Q_OBJECT + +public: + static const QString VERSION; + static const QString BUILDTIME; + static const QString AUTHOR; + static const QString COPYRIGHT; + static const QString WWWADDRESS; + static const QString WEBKITVERSION; + + explicit QupZilla(bool m_tryRestore=true, QUrl startUrl=QUrl()); + ~QupZilla(); + + void refreshAddressBar(); + void addBookmark(const QUrl &url, const QString &title); + void installTranslator(); + void loadSettings(); + void showInspector(); + void setBackground(QColor textColor); + + inline WebView* weView() const { return qobject_cast(m_tabWidget->widget(m_tabWidget->currentIndex()))->view(); } + inline WebView* weView(int index) const { return qobject_cast(m_tabWidget->widget(index))->view(); } + inline LocationBar* locationBar(){ return m_locationBar; } + inline TabWidget* tabWidget(){ return m_tabWidget; } + inline BookmarksToolbar* bookmarksToolbar(){ return m_bookmarksToolbar; } + inline MainApplication* getMainApp() { return p_mainApp; } + + inline QAction* buttonStop(){ return m_buttonStop; } + inline QAction* buttonReload(){ return m_buttonReload; } + inline QProgressBar* progressBar(){ return m_progressBar; } + inline QToolBar* navigationToolbar(){ return m_navigation; } + inline QString activeProfil(){ return m_activeProfil; } + inline QString activeLanguage(){ return m_activeLanguage; } + inline QDockWidget* inspectorDock(){ return m_webInspectorDock; } + inline QLabel* ipLabel(){ return m_ipLabel; } + inline QColor menuTextColor() { return m_menuTextColor; } + inline QAction* acShowBookmarksToolbar() { return m_actionShowBookmarksToolbar; } + +signals: + void loadHistory(); + void startingCompleted(); + void message(MainApplication::MessageType mes, bool state); + +public slots: + void refreshHistory(int index=-1); + void loadActionUrl(); + void bookmarkPage(); + void loadAddress(QUrl url) { weView()->load(url); m_locationBar->setText(url.toEncoded()); } + void showSource(); + void showPageInfo(); + void receiveMessage(MainApplication::MessageType mes, bool state); + +private slots: + void closeEvent(QCloseEvent* event); + void postLaunch(); + void goAtHistoryIndex(); + void goNext() { weView()->forward(); } + void goBack() { weView()->back(); } + void goHome() { loadAddress(m_homepage); } + void stop() { weView()->stop(); } + void reload() { weView()->reload(); } + void urlEnter(); + void aboutQupZilla(); + void addTab() { m_tabWidget->addView(QUrl(), tr("New tab"), TabWidget::NewTab, true); } + void printPage(); + + void aboutToShowHistoryBackMenu(); + void aboutToShowHistoryNextMenu(); + void aboutToShowHistoryMenu(); + void aboutToShowBookmarksMenu(); + void aboutToShowToolsMenu(); + void aboutToShowHelpMenu(); + void aboutToShowViewMenu(); + + void searchOnPage(); + void showCookieManager(); + void showHistoryManager(); + void showBookmarksManager(); + void showRSSManager(); + void showDownloadManager(); + + void showMenubar(); + void showNavigationToolbar(); + void showBookmarksToolbar(); + void showStatusbar(); + void showClearPrivateData(); + void showPreferences(); + + void bookmarkAllTabs(); + void newWindow() { p_mainApp->makeNewWindow(false); } + + void openLocation() { m_locationBar->setFocus(); m_locationBar->selectAll(); } + void openFile(); + void savePage(); + void sendLink() { QDesktopServices::openUrl(QUrl("mailto:?body="+weView()->url().toString())); } + void webSearch() { m_searchLine->setFocus(); } + + void copy() { QApplication::clipboard()->setText(weView()->selectedText()); } + void selectAll() { weView()->selectAll(); } + void reportBug() { m_tabWidget->addView(QUrl("http://qupzilla.ic.cz/bugzilla/?do=newtask&project=2")); } + + void zoomIn() { weView()->zoomIn(); } + void zoomOut() { weView()->zoomOut(); } + void zoomReset() { weView()->zoomReset(); } + void fullScreen(bool make); + void startPrivate(bool state); + + void quitApp(); + +private: + void setupUi(); + void setupMenu(); + + MainApplication* p_mainApp; + + bool m_tryRestore; + QUrl m_startingUrl; + QUrl m_newtab; + QUrl m_homepage; + + QToolButton* m_supMenu; + QMenu* m_superMenu; + QMenu* m_menuFile; + QMenu* m_menuEdit; + QMenu* m_menuTools; + QMenu* m_menuHelp; + QMenu* m_menuView; + QMenu* m_menuBookmarks; + QMenu* m_menuHistory; + QMenu* m_menuBack; + QMenu* m_menuForward; + QAction* m_actionShowToolbar; + QAction* m_actionShowBookmarksToolbar; + QAction* m_actionShowStatusbar; + QAction* m_actionShowMenubar; + QAction* m_actionShowFullScreen; + QAction* m_actionPrivateBrowsing; + QAction* m_actionStop; + QAction* m_actionReload; + + QLabel* m_privateBrowsing; + QLabel* m_allowFlashIcon; + QPointer m_webInspector; + QPointer m_webInspectorDock; + + WebSearchBar* m_searchLine; + SearchToolBar* m_webSearchToolbar; + BookmarksToolbar* m_bookmarksToolbar; + LocationBar* m_locationBar; + TabWidget* m_tabWidget; + + QSplitter* m_navigationSplitter; + QAction* m_buttonBack; + QAction* m_buttonNext; + QAction* m_buttonHome; + QAction* m_buttonStop; + QAction* m_buttonReload; + QAction* m_actionExitFullscreen; + QProgressBar* m_progressBar; + QLabel* m_ipLabel; + QToolBar* m_navigation; + + QString m_activeProfil; + QString m_activeLanguage; + QColor m_menuTextColor; + + //Used for F11 FullScreen remember visibility + //of menubar and statusbar + bool m_menuBarVisible; + bool m_statusBarVisible; +}; + +#endif // QUPZILLA_H diff --git a/src/appicon.rc b/src/appicon.rc new file mode 100644 index 000000000..e490cd766 --- /dev/null +++ b/src/appicon.rc @@ -0,0 +1,32 @@ +#include "winver.h" + +IDI_ICON1 ICON DISCARDABLE "icon.ico" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,9,7,0 + PRODUCTVERSION 0,9,7,0 + FILEFLAGS 0x0L + FILEFLAGSMASK 0x3fL + FILEOS 0x00040004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "CompanyName", "QupZilla Association" + VALUE "FileDescription", "QupZilla Web Browser" + VALUE "FileVersion", "0.9.7.0" + VALUE "LegalCopyright", "Copyright (C) 2010-2011 nowrep" + VALUE "InternalName", "qupzilla" + VALUE "OriginalFilename", "qupzilla.exe" + VALUE "ProductName", "QupZilla" + VALUE "ProductVersion", "0.9.7.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END diff --git a/src/autofill/autofillmodel.cpp b/src/autofill/autofillmodel.cpp new file mode 100644 index 000000000..0129182d9 --- /dev/null +++ b/src/autofill/autofillmodel.cpp @@ -0,0 +1,183 @@ +#include "autofillmodel.h" +#include "qupzilla.h" +#include "webview.h" +#include "mainapplication.h" +#include "autofillwidget.h" + +AutoFillModel::AutoFillModel(QupZilla* mainClass, QObject *parent) : + QObject(parent) + ,p_QupZilla(mainClass) + ,m_isStoring(false) +{ + QTimer::singleShot(0, this, SLOT(loadSettings())); +} + +void AutoFillModel::loadSettings() +{ + QSettings settings(MainApplication::getInstance()->getActiveProfil()+"settings.ini", QSettings::IniFormat); + settings.beginGroup("Web-Browser-Settings"); + m_isStoring = settings.value("AutoFillForms",true).toBool(); + settings.endGroup(); +} + +bool AutoFillModel::isStored(const QUrl &url) +{ + QString server = url.host(); + QSqlQuery query; + query.exec("SELECT count(id) FROM autofill WHERE server='"+server+"'"); + query.next(); + if (query.value(0).toInt()>0) + return true; + return false; +} + +bool AutoFillModel::isStoringEnabled(const QUrl &url) +{ + if (!m_isStoring) + return false; + QString server = url.host(); + QSqlQuery query; + query.exec("SELECT count(id) FROM autofill_exceptions WHERE server='"+server+"'"); + query.next(); + if (query.value(0).toInt()>0) + return false; + return true; +} + +void AutoFillModel::blockStoringfor (const QUrl &url) +{ + QString server = url.host(); + QSqlQuery query; + query.exec("INSERT INTO autofill_exceptions (server) VALUES ('"+server+"')"); +} + +QString AutoFillModel::getUsername(const QUrl &url) +{ + QString server = url.host(); + QSqlQuery query; + query.exec("SELECT username FROM autofill WHERE server='"+server+"'"); + query.next(); + return query.value(0).toString(); +} + +QString AutoFillModel::getPassword(const QUrl &url) +{ + QString server = url.host(); + QSqlQuery query; + query.exec("SELECT password FROM autofill WHERE server='"+server+"'"); + query.next(); + return query.value(0).toString(); +} + +///HTTP Authorization +bool AutoFillModel::addEntry(const QUrl &url, const QString &name, const QString &pass) +{ + QSqlQuery query; + query.exec("SELECT username FROM autofill WHERE server='"+url.host()+"'"); + if (query.next()) + return false; + query.prepare("INSERT INTO autofill (server, username, password) VALUES (?,?,?)"); + query.bindValue(0, url.host()); + query.bindValue(1, name); + query.bindValue(2, pass); + return query.exec(); +} + +///WEB Form +bool AutoFillModel::addEntry(const QUrl &url, const QByteArray &data, const QString &pass) +{ + QSqlQuery query; + query.exec("SELECT data FROM autofill WHERE server='"+url.host()+"'"); + if (query.next()) + return false; + + query.prepare("INSERT INTO autofill (server, data, password) VALUES (?,?,?)"); + query.bindValue(0, url.host()); + query.bindValue(1, data); + query.bindValue(2, pass); + return query.exec(); +} + +void AutoFillModel::completePage(WebView* view) +{ + if (!isStored(view->url())) + return; + + QWebFrame* frame = view->page()->mainFrame(); + QWebElementCollection inputs = frame->findAllElements("input"); + QSqlQuery query; + query.exec("SELECT data FROM autofill WHERE server='"+view->url().host()+"'"); + query.next(); + QByteArray data = query.value(0).toByteArray(); + if (data.isEmpty()) + return; + + QList > arguments = QUrl::fromEncoded(QByteArray("http://bla.com/?"+data)).queryItems(); + for (int i = 0; iwebSettings()->testAttribute(QWebSettings::PrivateBrowsingEnabled)) + return; + m_lastOutgoingData = outgoingData; + + QVariant v = request.attribute((QNetworkRequest::Attribute)(QNetworkRequest::User + 100)); + QWebPage* webPage = (QWebPage*)(v.value()); + v = request.attribute((QNetworkRequest::Attribute)(QNetworkRequest::User + 102)); + WebView* webView = (WebView*)(v.value()); + if (!webPage || !webView) + return; + + v = request.attribute((QNetworkRequest::Attribute)(QNetworkRequest::User + 101)); + QWebPage::NavigationType type = (QWebPage::NavigationType)v.toInt(); + + if (type!=QWebPage::NavigationTypeFormSubmitted) + return; + + QString passwordName=""; + QWebFrame* frame = webPage->mainFrame(); + QWebElementCollection inputs = frame->findAllElements("input"); + for (int i = 0; i > arguments = QUrl::fromEncoded(QByteArray("http://bla.com/?"+outgoingData)).queryItems(); + for (int i = 0; iaddNotification(aWidget); + +} diff --git a/src/autofill/autofillmodel.h b/src/autofill/autofillmodel.h new file mode 100644 index 000000000..58c8f8862 --- /dev/null +++ b/src/autofill/autofillmodel.h @@ -0,0 +1,44 @@ +#ifndef AUTOFILLMODEL_H +#define AUTOFILLMODEL_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include + +class QupZilla; +class WebView; +class AutoFillModel : public QObject +{ + Q_OBJECT +public: + explicit AutoFillModel(QupZilla* mainClass, QObject *parent = 0); + void completePage(WebView* view); + + bool isStored(const QUrl &url); + bool isStoringEnabled(const QUrl &url); + void blockStoringfor (const QUrl &url); + + QString getUsername(const QUrl &url); + QString getPassword(const QUrl &url); + bool addEntry(const QUrl &url, const QString &name, const QString &pass); + bool addEntry(const QUrl &url, const QByteArray &data, const QString &pass); + + void post(const QNetworkRequest &request, const QByteArray &outgoingData); + +signals: + +public slots: + void loadSettings(); + +private: + QupZilla* p_QupZilla; + QByteArray m_lastOutgoingData; + bool m_isStoring; + +}; + +#endif // AUTOFILLMODEL_H diff --git a/src/autofill/autofillwidget.cpp b/src/autofill/autofillwidget.cpp new file mode 100644 index 000000000..81ecd109d --- /dev/null +++ b/src/autofill/autofillwidget.cpp @@ -0,0 +1,46 @@ +#include "autofillwidget.h" +#include "ui_autofillwidget.h" +#include "autofillmodel.h" +#include "mainapplication.h" + +AutoFillWidget::AutoFillWidget(QUrl url, QByteArray data, QString pass, QWidget *parent) + :QWidget(parent) + ,ui(new Ui::AutoFillWidget) + ,m_url(url) + ,m_data(data) + ,m_pass(pass) +{ + setAttribute(Qt::WA_DeleteOnClose); + ui->setupUi(this); + ui->label->setText(tr("Do you want QupZilla to remember password on %1?").arg(url.host())); + ui->closeButton->setIcon( +#ifdef Q_WS_X11 + style()->standardIcon(QStyle::SP_DialogCloseButton) +#else + QIcon(":/icons/faenza/close.png") +#endif + ); + + connect(ui->remember, SIGNAL(clicked()), this, SLOT(remember())); + connect(ui->never, SIGNAL(clicked()), this, SLOT(never())); + connect(ui->notnow, SIGNAL(clicked()), this, SLOT(close())); + connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(close())); +} +// addEntry(request.url(), outgoingData, pass); + +void AutoFillWidget::never() +{ + MainApplication::getInstance()->autoFill()->blockStoringfor(m_url); + close(); +} + +void AutoFillWidget::remember() +{ + MainApplication::getInstance()->autoFill()->addEntry(m_url, m_data, m_pass); + close(); +} + +AutoFillWidget::~AutoFillWidget() +{ + delete ui; +} diff --git a/src/autofill/autofillwidget.h b/src/autofill/autofillwidget.h new file mode 100644 index 000000000..3f03adc8b --- /dev/null +++ b/src/autofill/autofillwidget.h @@ -0,0 +1,30 @@ +#ifndef AUTOFILLWIDGET_H +#define AUTOFILLWIDGET_H + +#include +#include + +namespace Ui { + class AutoFillWidget; +} + +class AutoFillWidget : public QWidget +{ + Q_OBJECT + +public: + explicit AutoFillWidget(QUrl url, QByteArray data, QString pass, QWidget *parent = 0); + ~AutoFillWidget(); + +private slots: + void remember(); + void never(); + +private: + Ui::AutoFillWidget *ui; + QUrl m_url; + QByteArray m_data; + QString m_pass; +}; + +#endif // AUTOFILLWIDGET_H diff --git a/src/autofill/autofillwidget.ui b/src/autofill/autofillwidget.ui new file mode 100644 index 000000000..656691efb --- /dev/null +++ b/src/autofill/autofillwidget.ui @@ -0,0 +1,126 @@ + + + AutoFillWidget + + + + 0 + 0 + 897 + 40 + + + + + 0 + 0 + + + + Form + + + + 3 + + + 5 + + + 4 + + + 5 + + + 4 + + + + + + 0 + 0 + + + + + + + :/icons/other/keys.png + + + + + + + + 0 + 0 + + + + + + + + + + + + + + 0 + 0 + + + + Remember + + + + + + + + 0 + 0 + + + + Never For This Site + + + + + + + + 0 + 0 + + + + Not Now + + + + + + + + + + + + true + + + + + + + + + + diff --git a/src/bookmarks/bookmarksmanager.cpp b/src/bookmarks/bookmarksmanager.cpp new file mode 100644 index 000000000..01f4a85de --- /dev/null +++ b/src/bookmarks/bookmarksmanager.cpp @@ -0,0 +1,343 @@ +#include "mainapplication.h" +#include "bookmarksmanager.h" +#include "ui_bookmarksmanager.h" +#include "qupzilla.h" +#include "locationbar.h" +#include "webview.h" +#include "bookmarkstoolbar.h" +#include "tabwidget.h" +#include "bookmarksmodel.h" + +//Won't be bad idea to rewrite bookmarks access via bookmarksmodel + +BookmarksManager::BookmarksManager(QupZilla* mainClass, QWidget *parent) : + QWidget(parent) + ,m_isRefreshing(false) + ,ui(new Ui::BookmarksManager) + ,p_QupZilla(mainClass) + ,m_bookmarksModel(MainApplication::getInstance()->bookmarks()) +{ + ui->setupUi(this); + //CENTER on scren + const QRect screen = QApplication::desktop()->screenGeometry(); + const QRect &size = QWidget::geometry(); + QWidget::move( (screen.width()-size.width())/2, (screen.height()-size.height())/2 ); + + connect(ui->deleteB, SIGNAL(clicked()), this, SLOT(deleteItem())); + connect(ui->close, SIGNAL(clicked(QAbstractButton*)), this, SLOT(hide())); + connect(ui->bookmarksTree, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(itemChanged(QTreeWidgetItem*))); + connect(ui->addFolder, SIGNAL(clicked()), this, SLOT(addFolder())); + connect(ui->bookmarksTree, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(contextMenuRequested(const QPoint &))); + connect(ui->bookmarksTree, SIGNAL(itemControlClicked(QTreeWidgetItem*)), this, SLOT(itemControlClicked(QTreeWidgetItem*))); + //QTimer::singleShot(0, this, SLOT(refreshTable())); +} + +QupZilla* BookmarksManager::getQupZilla() +{ + if (!p_QupZilla) + p_QupZilla = MainApplication::getInstance()->getWindow(); + return p_QupZilla; +} + +void BookmarksManager::setMainWindow(QupZilla *window) +{ + if (window) + p_QupZilla = window; +} + +void BookmarksManager::addFolder() +{ + QString text = QInputDialog::getText(this, tr("Add new folder"), tr("Choose name for new bookmark folder: ")); + if (text.isEmpty()) + return; + QSqlQuery query; + query.exec("INSERT INTO folders (name) VALUES ('"+text+"')"); + refreshTable(); +} + +void BookmarksManager::itemChanged(QTreeWidgetItem *item) +{ + if (!item || m_isRefreshing) + return; + + QString name = item->text(0); + QUrl url = QUrl(item->text(1)); + int id = item->whatsThis(1).toInt(); + + m_bookmarksModel->editBookmark(id, url, name); +} + +void BookmarksManager::itemControlClicked(QTreeWidgetItem *item) +{ + if (!item || item->text(1).isEmpty()) + return; + getQupZilla()->tabWidget()->addView(QUrl(item->text(1))); +} + +void BookmarksManager::loadInNewTab() +{ + if (QAction *action = qobject_cast(sender())) + getQupZilla()->tabWidget()->addView(action->data().toUrl(), tr("New Tab"), TabWidget::NewNotSelectedTab); +} + +void BookmarksManager::deleteItem() +{ + QTreeWidgetItem* item = ui->bookmarksTree->currentItem(); + if (!item) + return; + QSqlQuery query; + + if (item->text(1).isEmpty()) { // Delete folder + QString folder = item->text(0); + if (folder == tr("Bookmarks In Menu") || folder == tr("Bookmarks In ToolBar")) + return; + + query.exec("DELETE FROM folders WHERE name='"+folder+"'"); + query.exec("DELETE FROM bookmarks WHERE folder='"+folder+"'"); + delete item; + return; + } + + QString id = item->whatsThis(1); + + query.exec("DELETE FROM bookmarks WHERE id="+id); + delete item; + getQupZilla()->bookmarksToolbar()->refreshBookmarks(); +} + +void BookmarksManager::addBookmark(WebView *view) +{ + insertBookmark(view->url(), view->title()); +} + +void BookmarksManager::moveBookmark() +{ + QTreeWidgetItem* item = ui->bookmarksTree->currentItem(); + if (!item) + return; + if (QAction *action = qobject_cast(sender())) { + m_bookmarksModel->editBookmark(item->whatsThis(1).toInt(), item->text(0), action->data().toString()); + } + refreshTable(); +} + +void BookmarksManager::contextMenuRequested(const QPoint &position) +{ + if (!ui->bookmarksTree->itemAt(position)) + return; + QString link = ui->bookmarksTree->itemAt(position)->text(1); + if (link.isEmpty()) + return; + + QMenu menu; + menu.addAction(tr("Open link in actual tab"), getQupZilla(), SLOT(loadActionUrl()))->setData(link); + menu.addAction(tr("Open link in new tab"), this, SLOT(loadInNewTab()))->setData(link); + menu.addSeparator(); + + QMenu moveMenu; + moveMenu.setTitle(tr("Move bookmark to folder")); + moveMenu.addAction(QIcon(":icons/other/unsortedbookmarks.png"), tr("Unsorted Bookmarks"), this, SLOT(moveBookmark()))->setData("unsorted"); + moveMenu.addAction(style()->standardIcon(QStyle::SP_DirOpenIcon), tr("Bookmarks In Menu"), this, SLOT(moveBookmark()))->setData("bookmarksMenu"); + moveMenu.addAction(style()->standardIcon(QStyle::SP_DirOpenIcon), tr("Bookmarks In ToolBar"), this, SLOT(moveBookmark()))->setData("bookmarksToolbar"); + QSqlQuery query; + query.exec("SELECT name FROM folders"); + while(query.next()) + moveMenu.addAction(style()->standardIcon(QStyle::SP_DirIcon), query.value(0).toString(), this, SLOT(moveBookmark()))->setData(query.value(0).toString()); + menu.addMenu(&moveMenu); + + menu.addSeparator(); + menu.addAction(tr("Close"), this, SLOT(close())); + + //Prevent choosing first option with double rightclick + QPoint pos = QCursor::pos(); + QPoint p(pos.x(), pos.y()+1); + menu.exec(p); +} + +void BookmarksManager::refreshTable() +{ + m_isRefreshing = true; + ui->bookmarksTree->setUpdatesEnabled(false); + ui->bookmarksTree->clear(); + + QSqlQuery query; + QTreeWidgetItem* newItem = new QTreeWidgetItem(ui->bookmarksTree); + newItem->setText(0, tr("Bookmarks In Menu")); + newItem->setIcon(0, style()->standardIcon(QStyle::SP_DirIcon)); + ui->bookmarksTree->addTopLevelItem(newItem); + + newItem = new QTreeWidgetItem(ui->bookmarksTree); + newItem->setText(0, tr("Bookmarks In ToolBar")); + newItem->setIcon(0, style()->standardIcon(QStyle::SP_DirIcon)); + ui->bookmarksTree->addTopLevelItem(newItem); + + query.exec("SELECT name FROM folders"); + while(query.next()) { + newItem = new QTreeWidgetItem(ui->bookmarksTree); + newItem->setText(0, query.value(0).toString()); + newItem->setIcon(0, style()->standardIcon(QStyle::SP_DirIcon)); + ui->bookmarksTree->addTopLevelItem(newItem); + } + + query.exec("SELECT title, url, id, folder FROM bookmarks"); + while(query.next()) { + QString title = query.value(0).toString(); + QUrl url = query.value(1).toUrl(); + int id = query.value(2).toInt(); + QString folder = query.value(3).toString(); + QTreeWidgetItem* item; + if (folder == "bookmarksMenu") + folder = tr("Bookmarks In Menu"); + if (folder == "bookmarksToolbar") + folder = tr("Bookmarks In ToolBar"); + + if (folder != "unsorted") { + QList findParent = ui->bookmarksTree->findItems(folder, 0); + if (findParent.count() == 1) { + item = new QTreeWidgetItem(findParent.at(0)); + }else{ + QTreeWidgetItem* newParent = new QTreeWidgetItem(ui->bookmarksTree); + newParent->setText(0, folder); + newParent->setIcon(0, style()->standardIcon(QStyle::SP_DirIcon)); + ui->bookmarksTree->addTopLevelItem(newParent); + item = new QTreeWidgetItem(newParent); + } + } else + item = new QTreeWidgetItem(ui->bookmarksTree); + + item->setText(0, title); + item->setText(1, url.toEncoded()); + item->setToolTip(0, title); + item->setToolTip(1, url.toEncoded()); + + item->setWhatsThis(1, QString::number(id)); + item->setIcon(0, LocationBar::icon(url)); + item->setFlags(item->flags() | Qt::ItemIsEditable); + ui->bookmarksTree->addTopLevelItem(item); + } + ui->bookmarksTree->expandAll(); + + ui->bookmarksTree->setUpdatesEnabled(true); + m_isRefreshing = false; +} + +void BookmarksManager::insertBookmark(const QUrl &url, const QString &title) +{ + if (url.isEmpty() || title.isEmpty()) + return; + QDialog* dialog = new QDialog(getQupZilla()); + QBoxLayout* layout = new QBoxLayout(QBoxLayout::TopToBottom, dialog); + QLabel* label = new QLabel(dialog); + QLineEdit* edit = new QLineEdit(dialog); + QComboBox* combo = new QComboBox(dialog); + QDialogButtonBox* box = new QDialogButtonBox(dialog); + box->addButton(QDialogButtonBox::Ok); + box->addButton(QDialogButtonBox::Cancel); + connect(box, SIGNAL(rejected()), dialog, SLOT(reject())); + connect(box, SIGNAL(accepted()), dialog, SLOT(accept())); + layout->addWidget(label); + layout->addWidget(edit); + layout->addWidget(combo); + if (m_bookmarksModel->isBookmarked(url)) + layout->addWidget(new QLabel(tr("Warning: You already have this page bookmarked!"))); + layout->addWidget(box); + + combo->addItem(QIcon(":icons/other/unsortedbookmarks.png"), tr("Unsorted Bookmarks")); + combo->addItem(style()->standardIcon(QStyle::SP_DirOpenIcon), tr("Bookmarks In Menu")); + combo->addItem(style()->standardIcon(QStyle::SP_DirOpenIcon), tr("Bookmarks In ToolBar")); + QSqlQuery query; + query.exec("SELECT name FROM folders"); + while(query.next()) + combo->addItem(style()->standardIcon(QStyle::SP_DirIcon), query.value(0).toString()); + + label->setText(tr("Choose name and location of bookmark.")); + edit->setText(title); + edit->setCursorPosition(0); + dialog->setWindowIcon(LocationBar::icon(url)); + dialog->setWindowTitle(tr("Add New Bookmark")); + + QSize size = dialog->size(); + size.setWidth(350); + dialog->resize(size); + dialog->exec(); + if (dialog->result() == QDialog::Rejected) + return; + if (edit->text().isEmpty()) + return; + + query.prepare("INSERT INTO bookmarks (title, url, folder) VALUES (?,?,?)"); + query.bindValue(0, edit->text()); + query.bindValue(1, url.toString()); + if (combo->currentText() == tr("Bookmarks In Menu")) + query.bindValue(2,"bookmarksMenu"); + else if (combo->currentText() == tr("Bookmarks In ToolBar")) + query.bindValue(2,"bookmarksToolbar"); + else if (combo->currentText() == tr("Unsorted Bookmarks")) + query.bindValue(2, "unsorted"); + else query.bindValue(2, combo->currentText()); + query.exec(); + + getQupZilla()->bookmarksToolbar()->refreshBookmarks(); + getQupZilla()->locationBar()->checkBookmark(); + delete dialog; +} + +void BookmarksManager::insertAllTabs() +{ + QDialog* dialog = new QDialog(getQupZilla()); + QBoxLayout* layout = new QBoxLayout(QBoxLayout::TopToBottom, dialog); + QLabel* label = new QLabel(dialog); + QComboBox* combo = new QComboBox(dialog); + QDialogButtonBox* box = new QDialogButtonBox(dialog); + box->addButton(QDialogButtonBox::Ok); + box->addButton(QDialogButtonBox::Cancel); + connect(box, SIGNAL(rejected()), dialog, SLOT(reject())); + connect(box, SIGNAL(accepted()), dialog, SLOT(accept())); + layout->addWidget(label); + layout->addWidget(combo); + layout->addWidget(box); + + combo->addItem(QIcon(":icons/other/unsortedbookmarks.png"), tr("Unsorted Bookmarks")); + combo->addItem(style()->standardIcon(QStyle::SP_DirOpenIcon), tr("Bookmarks In Menu")); + combo->addItem(style()->standardIcon(QStyle::SP_DirOpenIcon), tr("Bookmarks In ToolBar")); + QSqlQuery query; + query.exec("SELECT name FROM folders"); + while(query.next()) + combo->addItem(style()->standardIcon(QStyle::SP_DirIcon), query.value(0).toString()); + + label->setText(tr("Choose folder for bookmarks:")); + dialog->setWindowIcon(QIcon(":/icons/qupzilla.png")); + dialog->setWindowTitle(tr("Bookmark All Tabs")); + + QSize size = dialog->size(); + size.setWidth(350); + dialog->resize(size); + dialog->exec(); + if (dialog->result() == QDialog::Rejected) + return; + + for (int i = 0; itabWidget()->count(); i++) { + WebView* view = getQupZilla()->weView(i); + if (!view || view->url().isEmpty()) + continue; + query.prepare("INSERT INTO bookmarks (title, url, folder) VALUES (?,?,?)"); + query.bindValue(0, view->title()); + query.bindValue(1, view->url().toString()); + if (combo->currentText() == tr("Bookmarks In Menu")) + query.bindValue(2,"bookmarksMenu"); + else if (combo->currentText() == tr("Bookmarks In ToolBar")) + query.bindValue(2,"bookmarksToolbar"); + else if (combo->currentText() == tr("Unsorted Bookmarks")) + query.bindValue(2, "unsorted"); + else query.bindValue(2, combo->currentText()); + query.exec(); + } + getQupZilla()->bookmarksToolbar()->refreshBookmarks(); + getQupZilla()->locationBar()->checkBookmark(); + delete dialog; +} + +BookmarksManager::~BookmarksManager() +{ + delete ui; +} diff --git a/src/bookmarks/bookmarksmanager.h b/src/bookmarks/bookmarksmanager.h new file mode 100644 index 000000000..75903addf --- /dev/null +++ b/src/bookmarks/bookmarksmanager.h @@ -0,0 +1,53 @@ +#ifndef BOOKMARKSMANAGER_H +#define BOOKMARKSMANAGER_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include + +namespace Ui { + class BookmarksManager; +} + +class WebView; +class QupZilla; +class BookmarksModel; +class BookmarksManager : public QWidget +{ + Q_OBJECT + +public: + explicit BookmarksManager(QupZilla* mainClass, QWidget *parent = 0); + ~BookmarksManager(); + void addBookmark(WebView* view); + void insertBookmark(const QUrl &url, const QString &title); + void setMainWindow(QupZilla* window); + +public slots: + void refreshTable(); + void insertAllTabs(); + +private slots: + void deleteItem(); + void itemChanged(QTreeWidgetItem* item); + void addFolder(); + void contextMenuRequested(const QPoint &position); + void loadInNewTab(); + void itemControlClicked(QTreeWidgetItem* item); + void moveBookmark(); + +private: + QupZilla* getQupZilla(); + + bool m_isRefreshing; + Ui::BookmarksManager *ui; + QPointer p_QupZilla; + BookmarksModel* m_bookmarksModel; +}; + +#endif // BOOKMARKSMANAGER_H diff --git a/src/bookmarks/bookmarksmanager.ui b/src/bookmarks/bookmarksmanager.ui new file mode 100644 index 000000000..49e60bb19 --- /dev/null +++ b/src/bookmarks/bookmarksmanager.ui @@ -0,0 +1,81 @@ + + + BookmarksManager + + + + 0 + 0 + 735 + 547 + + + + Bookmarks + + + + :/icons/qupzilla.png:/icons/qupzilla.png + + + + + + Qt::CustomContextMenu + + + true + + + 330 + + + + Title + + + + + Url + + + + + + + + QDialogButtonBox::Close + + + + + + + Delete + + + Del + + + + + + + Add Folder + + + + + + + + TreeWidget + QTreeWidget +
    treewidget.h
    +
    +
    + + + + +
    diff --git a/src/bookmarks/bookmarksmodel.cpp b/src/bookmarks/bookmarksmodel.cpp new file mode 100644 index 000000000..1df0c3ce1 --- /dev/null +++ b/src/bookmarks/bookmarksmodel.cpp @@ -0,0 +1,150 @@ +#include "mainapplication.h" +#include "bookmarksmodel.h" +#include "webview.h" + +// SQLite DB -> table bookmarks + folders +// Unique in bookmarks table is id +// However from bookmark icon, it is not possible to add more than one bookmark +// Only from Ctrl+D dialog it is possible + +BookmarksModel::BookmarksModel() +{ + loadSettings(); +} + +void BookmarksModel::loadSettings() +{ + QSettings settings(MainApplication::getInstance()->getActiveProfil()+"settings.ini", QSettings::IniFormat); + settings.beginGroup("Web-Browser-Settings"); + m_showMostVisited = settings.value("showMostVisited",true).toBool(); + settings.endGroup(); +} + +void BookmarksModel::setShowingMostVisited(bool state) +{ + QSettings settings(MainApplication::getInstance()->getActiveProfil()+"settings.ini", QSettings::IniFormat); + settings.beginGroup("Web-Browser-Settings"); + settings.setValue("showMostVisited",state); + settings.endGroup(); + m_showMostVisited = state; +} + +bool BookmarksModel::isBookmarked(QUrl url) +{ + QSqlQuery query; + query.prepare("SELECT count(id) FROM bookmarks WHERE url=?"); + query.bindValue(0, url.toString()); + query.exec(); + query.next(); + return query.value(0).toInt()>0; +} + +// Bookmark search priority: +// Bookmarks in menu > bookmarks in toolbar -> user folders and unsorted +int BookmarksModel::bookmarkId(QUrl url) +{ + QSqlQuery query; + query.prepare("SELECT id FROM bookmarks WHERE url=? AND folder='bookmarksMenu' "); + query.bindValue(0, url.toString()); + query.exec(); + if (query.next()) + return query.value(0).toInt(); + + query.prepare("SELECT id FROM bookmarks WHERE url=? AND folder='bookmarksToolbar' "); + query.bindValue(0, url.toString()); + query.exec(); + if (query.next()) + return query.value(0).toInt(); + + query.prepare("SELECT id FROM bookmarks WHERE url=? "); + query.bindValue(0, url.toString()); + query.exec(); + if (query.next()) + return query.value(0).toInt(); + + return -1; +} + +int BookmarksModel::bookmarkId(QUrl url, QString title, QString folder) +{ + QSqlQuery query; + query.prepare("SELECT id FROM bookmarks WHERE url=? AND title=? AND folder=? "); + query.bindValue(0, url.toString()); + query.bindValue(1, title); + query.bindValue(2, folder); + query.exec(); + if (query.next()) + return query.value(0).toInt(); + return -1; +} + +QStringList BookmarksModel::getBookmark(int id) +{ + QSqlQuery query; + query.prepare("SELECT url, title, folder FROM bookmarks WHERE id=?"); + query.bindValue(0, id); + query.exec(); + if (!query.next()) + return QStringList(); + QStringList list; + list.append(query.value(0).toString()); + list.append(query.value(1).toString()); + list.append(query.value(2).toString()); + return list; +} + +bool BookmarksModel::saveBookmark(QUrl url, QString title, QString folder) +{ + if (url.isEmpty() || title.isEmpty() || folder.isEmpty()) + return false; + + QSqlQuery query; + query.prepare("INSERT INTO bookmarks (url, title, folder) VALUES (?,?,?)"); + query.bindValue(0, url.toString()); + query.bindValue(1, title); + query.bindValue(2, folder); + return query.exec(); +} + +bool BookmarksModel::saveBookmark(WebView *view, QString folder) +{ + return saveBookmark(view->url(), view->title(), folder); +} + +bool BookmarksModel::removeBookmark(int id) +{ + QSqlQuery query; + query.prepare("DELETE FROM bookmarks WHERE id = ?"); + query.bindValue(0, id); + return query.exec(); +} + +bool BookmarksModel::removeBookmark(QUrl url) +{ + return removeBookmark(bookmarkId(url)); +} + +bool BookmarksModel::removeBookmark(WebView *view) +{ + return removeBookmark(bookmarkId(view->url())); +} + +bool BookmarksModel::editBookmark(int id, QString title, QString folder) +{ + QSqlQuery query; + query.prepare("UPDATE bookmarks SET title=?, folder=? WHERE id=?"); + query.bindValue(0, title); + query.bindValue(1, folder); + query.bindValue(2, id); + return query.exec(); +} + +bool BookmarksModel::editBookmark(int id, QUrl url, QString title) +{ + QSqlQuery query; + query.prepare("UPDATE bookmarks SET title=?, url=? WHERE id=?"); + query.bindValue(0, title); + query.bindValue(1, url.toString()); + query.bindValue(2, id); + return query.exec(); +} diff --git a/src/bookmarks/bookmarksmodel.h b/src/bookmarks/bookmarksmodel.h new file mode 100644 index 000000000..1dc93f6c8 --- /dev/null +++ b/src/bookmarks/bookmarksmodel.h @@ -0,0 +1,44 @@ +#ifndef BOOKMARKSMODEL_H +#define BOOKMARKSMODEL_H +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include + +class WebView; +class BookmarksModel +{ +public: + explicit BookmarksModel(); + void loadSettings(); + inline bool isShowingMostVisited() { return m_showMostVisited; } + void setShowingMostVisited(bool state); + + bool isBookmarked(QUrl url); + int bookmarkId(QUrl url); + int bookmarkId(QUrl url, QString title, QString folder); + QStringList getBookmark(int id); + + bool saveBookmark(QUrl url, QString title, QString folder = "unsorted"); + bool saveBookmark(WebView* view, QString folder = "unsorted"); + + bool removeBookmark(int id); + bool removeBookmark(QUrl url); + bool removeBookmark(WebView* view); + + bool editBookmark(int id, QString title, QString folder); + bool editBookmark(int id, QUrl url, QString title); + +signals: + +public slots: + +private: + bool m_showMostVisited; + +}; + +#endif // BOOKMARKSMODEL_H diff --git a/src/bookmarks/bookmarkstoolbar.cpp b/src/bookmarks/bookmarkstoolbar.cpp new file mode 100644 index 000000000..8ddd5f34f --- /dev/null +++ b/src/bookmarks/bookmarkstoolbar.cpp @@ -0,0 +1,125 @@ +#include "bookmarkstoolbar.h" +#include "qupzilla.h" +#include "locationbar.h" +#include "bookmarksmodel.h" + +BookmarksToolbar::BookmarksToolbar(QupZilla* mainClass, QWidget *parent) : + QToolBar(parent) + ,p_QupZilla(mainClass) + ,m_bookmarksModel(0) +{ + setObjectName("bookmarksToolbar"); + setWindowTitle(tr("Bookmarks")); + setStyleSheet("QToolBar{background-image:url(:icons/transp.png); border:none;}"); + setMovable(false); + setContextMenuPolicy(Qt::CustomContextMenu); + + connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(customContextMenuRequested(QPoint))); + QTimer::singleShot(0, this, SLOT(refreshBookmarks())); +} + +void BookmarksToolbar::setColor(QColor color) +{ + setStyleSheet("QToolButton {color: "+color.name()+";}"); +} + +void BookmarksToolbar::customContextMenuRequested(const QPoint &pos) +{ + if (actionAt(pos)) + return; + + QMenu menu; + menu.addAction(tr("Bookmark Current Page"), p_QupZilla, SLOT(bookmarkPage())); + menu.addAction(tr("Bookmark All Tabs"), p_QupZilla, SLOT(bookmarkAllTabs())); + menu.addAction(QIcon::fromTheme("user-bookmarks"), tr("Organize Bookmarks"), p_QupZilla, SLOT(showBookmarksManager())); + menu.addSeparator(); + menu.addAction( +#ifdef Q_WS_X11 + style()->standardIcon(QStyle::SP_BrowserReload) +#else + QIcon(":/icons/faenza/reload.png") +#endif + ,tr("Reload Toolbar"), this, SLOT(refreshBookmarks())); + menu.addSeparator(); + menu.addAction(m_bookmarksModel->isShowingMostVisited() ? tr("Hide Most Visited") : tr("Show Most Visited"), this, SLOT(showMostVisited())); + menu.addAction(tr("Hide Toolbar"), this, SLOT(hidePanel())); + + //Prevent choosing first option with double rightclick + QPoint position = QCursor::pos(); + QPoint p(position.x(), position.y()+1); + menu.exec(p); +} + +void BookmarksToolbar::showMostVisited() +{ + m_bookmarksModel->setShowingMostVisited(!m_bookmarksModel->isShowingMostVisited()); + refreshBookmarks(); +} + +void BookmarksToolbar::hidePanel() +{ + this->hide(); + p_QupZilla->acShowBookmarksToolbar()->setChecked(false); +} + +void BookmarksToolbar::refreshBookmarks() +{ + if (!m_bookmarksModel) + m_bookmarksModel =MainApplication::getInstance()->bookmarks(); + + clear(); + QSqlQuery query; + query.exec("SELECT title, url FROM bookmarks WHERE folder='bookmarksToolbar'"); + while(query.next()) { + QUrl url = query.value(1).toUrl(); + QString title = query.value(0).toString(); + QAction* action = new QAction(this); + if (title.length()>15) { + title.truncate(13); + title+=".."; + } + + action->setText(title); + action->setData(url); + action->setIcon(LocationBar::icon(url)); + QToolButton* button = new QToolButton(this); + button->setDefaultAction(action); + button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + button->setMaximumHeight(25); + connect(action, SIGNAL(triggered()), p_QupZilla, SLOT(loadActionUrl())); + addWidget(button); + } + + if (!m_bookmarksModel->isShowingMostVisited()) + return; + + QToolButton* mostVis = new QToolButton(this); + mostVis->setPopupMode(QToolButton::InstantPopup); + mostVis->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + mostVis->setMaximumHeight(25); + mostVis->setIcon(style()->standardIcon(QStyle::SP_DirIcon)); + mostVis->setText(tr("Most visited")); + mostVis->setToolTip(tr("Sites You visited the most")); + m_menuMostVisited = new QMenu(); + mostVis->setMenu(m_menuMostVisited); + connect(m_menuMostVisited, SIGNAL(aboutToShow()), this, SLOT(refreshMostVisited())); + + addWidget(mostVis); +} + +void BookmarksToolbar::refreshMostVisited() +{ + m_menuMostVisited->clear(); + + QSqlQuery query; + query.exec("SELECT title, url FROM history ORDER BY count DESC LIMIT 10"); + while(query.next()) { + QUrl url = query.value(1).toUrl(); + QString title = query.value(0).toString(); + if (title.length()>40) { + title.truncate(40); + title+=".."; + } + m_menuMostVisited->addAction(LocationBar::icon(url), title, p_QupZilla, SLOT(loadActionUrl()))->setData(url); + } +} diff --git a/src/bookmarks/bookmarkstoolbar.h b/src/bookmarks/bookmarkstoolbar.h new file mode 100644 index 000000000..01fd1bef5 --- /dev/null +++ b/src/bookmarks/bookmarkstoolbar.h @@ -0,0 +1,38 @@ +#ifndef BOOKMARKSTOOLBAR_H +#define BOOKMARKSTOOLBAR_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include + +class QupZilla; +class BookmarksModel; + +class BookmarksToolbar : public QToolBar +{ + Q_OBJECT +public: + explicit BookmarksToolbar(QupZilla* mainClass, QWidget *parent = 0); + void setColor(QColor color); + +signals: + +public slots: + void refreshBookmarks(); + void refreshMostVisited(); + void customContextMenuRequested(const QPoint &pos); + void hidePanel(); + void showMostVisited(); + +private: + QupZilla* p_QupZilla; + BookmarksModel* m_bookmarksModel; + QMenu* m_menuMostVisited; + +}; + +#endif // BOOKMARKSTOOLBAR_H diff --git a/src/bookmarks/bookmarkswidget.cpp b/src/bookmarks/bookmarkswidget.cpp new file mode 100644 index 000000000..2122665c5 --- /dev/null +++ b/src/bookmarks/bookmarkswidget.cpp @@ -0,0 +1,63 @@ +#include "bookmarkswidget.h" +#include "ui_bookmarkswidget.h" +#include "bookmarksmodel.h" +#include "mainapplication.h" + +BookmarksWidget::BookmarksWidget(int bookmarkId, QWidget *parent) : + QMenu(parent) + ,ui(new Ui::BookmarksWidget) + ,m_bookmarkId(bookmarkId) + ,m_bookmarksModel(0) +{ + ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + connect(ui->close, SIGNAL(clicked()), this, SLOT(close())); + connect(ui->removeBookmark, SIGNAL(clicked()), this, SLOT(removeBookmark())); + connect(ui->save, SIGNAL(clicked()), this, SLOT(saveBookmark())); + + m_bookmarksModel = MainApplication::getInstance()->bookmarks(); + loadBookmark(); +} + +void BookmarksWidget::loadBookmark() +{ + QStringList bookmark = m_bookmarksModel->getBookmark(m_bookmarkId); + ui->name->setText( bookmark.at(1) ); + + // Bookmark folders + ui->folder->addItem(QIcon(":icons/other/unsortedbookmarks.png"), tr("Unsorted Bookmarks"), "unsorted"); + ui->folder->addItem(style()->standardIcon(QStyle::SP_DirOpenIcon), tr("Bookmarks In Menu"), "bookmarksMenu"); + ui->folder->addItem(style()->standardIcon(QStyle::SP_DirOpenIcon), tr("Bookmarks In ToolBar"), "bookmarksToolbar"); + QSqlQuery query; + query.exec("SELECT name FROM folders"); + while(query.next()) + ui->folder->addItem(style()->standardIcon(QStyle::SP_DirIcon), query.value(0).toString(), query.value(0).toString()); + + ui->folder->setCurrentIndex( ui->folder->findData(bookmark.at(2)) ); + ui->name->setCursorPosition(0); +} + +void BookmarksWidget::removeBookmark() +{ + m_bookmarksModel->removeBookmark(m_bookmarkId); + emit bookmarkDeleted(); + close(); +} + +void BookmarksWidget::saveBookmark() +{ + m_bookmarksModel->editBookmark(m_bookmarkId, ui->name->text(), ui->folder->itemData(ui->folder->currentIndex()).toString() ); + close(); +} + +void BookmarksWidget::showAt(QWidget* _parent) +{ + QPoint p = _parent->mapToGlobal(QPoint(0, 0)); + move( (p.x()+_parent->width() ) - width(), p.y() + _parent->height()); + show(); +} + +BookmarksWidget::~BookmarksWidget() +{ + delete ui; +} diff --git a/src/bookmarks/bookmarkswidget.h b/src/bookmarks/bookmarkswidget.h new file mode 100644 index 000000000..b344c7d23 --- /dev/null +++ b/src/bookmarks/bookmarkswidget.h @@ -0,0 +1,48 @@ +#ifndef BOOKMARKSWIDGET_H +#define BOOKMARKSWIDGET_H +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Ui { + class BookmarksWidget; +} + +class BookmarksModel; +class BookmarksWidget : public QMenu +{ + Q_OBJECT +public: + explicit BookmarksWidget(int bookmarkId, QWidget *parent = 0); + ~BookmarksWidget(); + void showAt(QWidget* _parent); + +signals: + void bookmarkDeleted(); + +public slots: + +private slots: + void removeBookmark(); + void saveBookmark(); + +private: + void loadBookmark(); + + Ui::BookmarksWidget* ui; + int m_bookmarkId; + BookmarksModel* m_bookmarksModel; +}; + +#endif // BOOKMARKSWIDGET_H diff --git a/src/bookmarks/bookmarkswidget.ui b/src/bookmarks/bookmarkswidget.ui new file mode 100644 index 000000000..04f5c5523 --- /dev/null +++ b/src/bookmarks/bookmarkswidget.ui @@ -0,0 +1,142 @@ + + + BookmarksWidget + + + + 0 + 0 + 282 + 166 + + + + + + + + + + QFrame::NoFrame + + + + 0 + + + 0 + + + + + + + + :/icons/other/bigstar.png + + + + + + + Edit This Bookmark + + + + + + + + 0 + 0 + + + + Remove Bookmark + + + + + + + Name: + + + + + + + + + + Folder: + + + + + + + + + + 5 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Save + + + + + + + + 0 + 0 + + + + Close + + + + + + + + + + + + + Frame + QFrame +
    frame.h
    + 1 +
    +
    + + + + +
    diff --git a/src/cookies/cookiejar.cpp b/src/cookies/cookiejar.cpp new file mode 100644 index 000000000..935fb8750 --- /dev/null +++ b/src/cookies/cookiejar.cpp @@ -0,0 +1,112 @@ +#include "cookiejar.h" +#include "qupzilla.h" +#define COOKIE_DEBUG + +//TODO: black/white listing +CookieJar::CookieJar(QupZilla* mainClass, QObject *parent) : + QNetworkCookieJar(parent) + ,p_QupZilla(mainClass) +{ + loadSettings(); +// activeProfil = MainApplication::getInstance()->getActiveProfil(); + m_activeProfil = MainApplication::getInstance()->getActiveProfil(); +} + +void CookieJar::loadSettings() +{ + QSettings settings(m_activeProfil+"settings.ini", QSettings::IniFormat); + settings.beginGroup("Web-Browser-Settings"); + m_allowCookies = settings.value("allowCookies",true).toBool(); + m_allowCookiesFromDomain = settings.value("allowCookiesFromVisitedDomainOnly",false).toBool(); + m_filterTrackingCookie = settings.value("filterTrackingCookie",false).toBool(); + m_deleteOnClose = settings.value("deleteCookiesOnClose", false).toBool(); +} + +void CookieJar::setAllowCookies(bool allow) +{ + m_allowCookies = allow; +} + +bool CookieJar::setCookiesFromUrl(const QList &cookieList, const QUrl &url) +{ + if (!m_allowCookies) + return QNetworkCookieJar::setCookiesFromUrl(QList(), url); + + QList newList = cookieList; + QDateTime now = QDateTime::currentDateTime(); + + foreach (QNetworkCookie cok, newList) { + if (m_allowCookiesFromDomain && !url.toString().contains(cok.domain())) { +#ifdef COOKIE_DEBUG + qDebug() << "purged for domain mismatch" << cok; +#endif + newList.removeOne(cok); + continue; + } + if (m_filterTrackingCookie && cok.expirationDate() > now.addYears(2)) { +#ifdef COOKIE_DEBUG + qDebug() << "purged as tracking " << cok; +#endif + newList.removeOne(cok); + continue; + } + } + return QNetworkCookieJar::setCookiesFromUrl(newList, url); +} + +void CookieJar::saveCookies() +{ + if (m_deleteOnClose) + return; + + QList allCookies = getAllCookies(); + QFile file(m_activeProfil+"cookies.dat"); + file.open(QIODevice::WriteOnly); + QDataStream stream(&file); + int count = allCookies.count(); + + stream << count; + for (int i = 0; i restoredCookies; + QFile file(m_activeProfil+"cookies.dat"); + file.open(QIODevice::ReadOnly); + QDataStream stream(&file); + int count; + + stream >> count; + for (int i = 0; i> rawForm; + QNetworkCookie cok = QNetworkCookie::parseCookies(rawForm).at(0); + if (cok.expirationDate() < now) + continue; + if (cok.isSessionCookie()) + continue; + restoredCookies.append(cok); + } + + file.close(); + setAllCookies(restoredCookies); +} + +QList CookieJar::getAllCookies() +{ + return QNetworkCookieJar::allCookies(); +} + +void CookieJar::setAllCookies(const QList &cookieList) +{ + QNetworkCookieJar::setAllCookies(cookieList); +} diff --git a/src/cookies/cookiejar.h b/src/cookies/cookiejar.h new file mode 100644 index 000000000..c5d1a5589 --- /dev/null +++ b/src/cookies/cookiejar.h @@ -0,0 +1,43 @@ +#ifndef COOKIEJAR_H +#define COOKIEJAR_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include +#include + +class QupZilla; +class CookieJar : public QNetworkCookieJar +{ + Q_OBJECT +public: + explicit CookieJar(QupZilla* mainClass, QObject *parent = 0); + + void loadSettings(); + bool setCookiesFromUrl(const QList &cookieList, const QUrl &url); + QList getAllCookies(); + void setAllCookies(const QList &cookieList); + void saveCookies(); + void restoreCookies(); + void setAllowCookies(bool allow); + +signals: + +public slots: + +private: + QupZilla* p_QupZilla; + bool m_allowCookies; + bool m_filterTrackingCookie; + bool m_allowCookiesFromDomain; + bool m_deleteOnClose; + + QString m_activeProfil; +}; + +#endif // COOKIEJAR_H diff --git a/src/cookies/cookiemanager.cpp b/src/cookies/cookiemanager.cpp new file mode 100644 index 000000000..54e873fd7 --- /dev/null +++ b/src/cookies/cookiemanager.cpp @@ -0,0 +1,171 @@ +#include "cookiemanager.h" +#include "ui_cookiemanager.h" +#include "qupzilla.h" +#include "cookiejar.h" +#include "mainapplication.h" + +CookieManager::CookieManager(QWidget *parent) : + QWidget(parent) + ,ui(new Ui::CookieManager) +{ + ui->setupUi(this); + //CENTER on scren + const QRect screen = QApplication::desktop()->screenGeometry(); + const QRect &size = QWidget::geometry(); + QWidget::move( (screen.width()-size.width())/2, (screen.height()-size.height())/2 ); + + //QTimer::singleShot(0, this, SLOT(refreshTable())); + + connect(ui->cookieTree, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),this, SLOT(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*))); + connect(ui->removeAll, SIGNAL(clicked()), this, SLOT(removeAll())); + connect(ui->removeCookie, SIGNAL(clicked()), this, SLOT(removeCookie())); + connect(ui->close, SIGNAL(clicked(QAbstractButton*)), this, SLOT(hide())); + connect(ui->search, SIGNAL(returnPressed()), this, SLOT(search())); + connect(ui->search, SIGNAL(cursorPositionChanged(int, int)), this, SLOT(search())); + + ui->search->setInactiveText(tr("Search")); +} + +void CookieManager::removeAll() +{ + QMessageBox::StandardButton button = QMessageBox::warning(this, tr("Confirmation"), + tr("Are you sure to delete all cookies on your computer?"), QMessageBox::Yes | QMessageBox::No); + if (button != QMessageBox::Yes) + return; + + m_cookies.clear(); + MainApplication::getInstance()->cookieJar()->setAllCookies(m_cookies); + ui->cookieTree->clear(); +} + +void CookieManager::removeCookie() +{ + QTreeWidgetItem* current = ui->cookieTree->currentItem(); + if (!current) + return; + + if (current->text(1).isEmpty()) { //Remove whole cookie group + QString domain = current->whatsThis(0); + foreach(QNetworkCookie cok, m_cookies) { + if (cok.domain() == domain || cok.domain() == domain.mid(1)) + m_cookies.removeOne(cok); + } + + delete current; + MainApplication::getInstance()->cookieJar()->setAllCookies(m_cookies); + refreshTable(false); + return; + } + + int index = current->whatsThis(1).toInt(); + m_cookies.removeAt(index); + MainApplication::getInstance()->cookieJar()->setAllCookies(m_cookies); + refreshTable(false); + + if (!ui->search->text().isEmpty()) + search(); +} + +void CookieManager::currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *parent) +{ + Q_UNUSED(parent); + if (!current) + return; + + ui->removeCookie->setEnabled(true); + + if (current->text(1).isEmpty()) { + ui->name->setText(tr("")); + ui->value->setText(tr("")); + ui->server->setText(tr("")); + ui->path->setText(tr("")); + ui->secure->setText(tr("")); + ui->expiration->setText(tr("")); + ui->removeCookie->setText(tr("Remove cookies")); + return; + } + ui->removeCookie->setText(tr("Remove cookie")); + + int index = current->whatsThis(1).toInt(); + QNetworkCookie cok = m_cookies.at(index); + + ui->name->setText(cok.name()); + ui->value->setText(cok.value()); + ui->server->setText(cok.domain()); + ui->path->setText(cok.path()); + cok.isSecure() ? ui->secure->setText(tr("Secure only")) : ui->secure->setText(tr("All connections")); + cok.isSessionCookie() ? ui->expiration->setText(tr("Session cookie")) : ui->expiration->setText(QDateTime(cok.expirationDate()).toString("hh:mm:ss dddd d. MMMM yyyy")); + +} + +void CookieManager::refreshTable(bool refreshCookieJar) +{ + if (refreshCookieJar) + m_cookies = MainApplication::getInstance()->cookieJar()->getAllCookies(); + + ui->cookieTree->setUpdatesEnabled(false); + ui->cookieTree->clear(); + + QString cookServer; + for (int i = 0; i findParent = ui->cookieTree->findItems(cookServer, 0); + if (findParent.count() == 1) { + item = new QTreeWidgetItem(findParent.at(0)); + }else{ + QTreeWidgetItem* newParent = new QTreeWidgetItem(ui->cookieTree); + newParent->setText(0, cookServer); + newParent->setIcon(0, style()->standardIcon(QStyle::SP_DirIcon)); + newParent->setWhatsThis(0, cok.domain()); + ui->cookieTree->addTopLevelItem(newParent); + item = new QTreeWidgetItem(newParent); + } + + item->setText(0,"."+cookServer); + item->setText(1, cok.name()); + item->setWhatsThis(1, QString::number(i)); + ui->cookieTree->addTopLevelItem(item); + } + + ui->cookieTree->setUpdatesEnabled(true); +} + +void CookieManager::search() +{ + QString searchText = ui->search->text(); + if (searchText.isEmpty()) { + refreshTable(false); + return; + } + + refreshTable(false); + ui->cookieTree->setUpdatesEnabled(false); + + QList items = ui->cookieTree->findItems(".*"+searchText+"*", Qt::MatchRecursive | Qt::MatchWildcard); + + QList foundItems; + foreach(QTreeWidgetItem* fitem, items) { + if (!fitem->text(0).startsWith(".")) + continue; + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setText(0, fitem->text(0)); + item->setText(1, fitem->text(1)); + item->setWhatsThis(1, fitem->whatsThis(1)); + foundItems.append(item); + } + ui->cookieTree->clear(); + ui->cookieTree->addTopLevelItems(foundItems); + ui->cookieTree->setUpdatesEnabled(true); +} + +CookieManager::~CookieManager() +{ + qDebug() << __FUNCTION__ << "called"; + delete ui; +} diff --git a/src/cookies/cookiemanager.h b/src/cookies/cookiemanager.h new file mode 100644 index 000000000..fbf9e5c20 --- /dev/null +++ b/src/cookies/cookiemanager.h @@ -0,0 +1,41 @@ +#ifndef COOKIEMANAGER_H +#define COOKIEMANAGER_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include + +namespace Ui { + class CookieManager; +} + +class QupZilla; +class CookieManager : public QWidget +{ + Q_OBJECT + +public: + explicit CookieManager(QWidget *parent = 0); + ~CookieManager(); + +public slots: + void refreshTable(bool refreshCookieJar = true); + +private slots: + void currentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* parent); + void removeCookie(); + void removeAll(); + void search(); + +private: + Ui::CookieManager *ui; + + QList m_cookies; +}; + +#endif // COOKIEMANAGER_H diff --git a/src/cookies/cookiemanager.ui b/src/cookies/cookiemanager.ui new file mode 100644 index 000000000..7a94782b1 --- /dev/null +++ b/src/cookies/cookiemanager.ui @@ -0,0 +1,250 @@ + + + CookieManager + + + + 0 + 0 + 617 + 415 + + + + Cookies + + + + :/icons/qupzilla.png:/icons/qupzilla.png + + + + + + Find: + + + + + + + + + + These cookies are stored on your computer: + + + + + + + true + + + true + + + 200 + + + 22 + + + + Server + + + + + Cookie name + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 6 + + + 3 + + + + + + 0 + 0 + + + + Name: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + Value: + + + + + + + Server: + + + + + + + Path: + + + + + + + Secure: + + + + + + + Expiration: + + + + + + + <cookie not selected> + + + + + + + <cookie not selected> + + + + + + + <cookie not selected> + + + + + + + <cookie not selected> + + + + + + + <cookie not selected> + + + + + + + <cookie not selected> + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + + + Remove all cookies + + + + + + + false + + + Remove cookie + + + Del + + + + + + + + 0 + 0 + + + + QDialogButtonBox::Close + + + + + + + + + + + LineEdit + QLineEdit +
    lineedit.h
    +
    + + SqueezeLabel + QLabel +
    squeezelabel.h
    +
    +
    + + + + +
    diff --git a/src/data/html.qrc b/src/data/html.qrc new file mode 100644 index 000000000..6d80a8347 --- /dev/null +++ b/src/data/html.qrc @@ -0,0 +1,6 @@ + + + html/errorPage.html + html/info.png + + diff --git a/src/data/html/errorPage.html b/src/data/html/errorPage.html new file mode 100644 index 000000000..7aff883d4 --- /dev/null +++ b/src/data/html/errorPage.html @@ -0,0 +1,73 @@ + +%TITLE% + + + + +
    + +

    %HEADING%

    +

    %HEADING2%

    +
      +
    • %LI-1%
    • +
    • %LI-2%
    • +
    • %LI-3%
    • + +
    +
    + diff --git a/src/data/html/info.png b/src/data/html/info.png new file mode 100644 index 000000000..fb47ae696 Binary files /dev/null and b/src/data/html/info.png differ diff --git a/src/data/icons.qrc b/src/data/icons.qrc new file mode 100644 index 000000000..4bf491b65 --- /dev/null +++ b/src/data/icons.qrc @@ -0,0 +1,68 @@ + + + icons/navigation/home.png + icons/navigation/reload.png + icons/navigation/stop.png + icons/navigation/vpred.png + icons/navigation/zpet.png + icons/qupzilla.png + icons/qupzillaupdate.png + icons/preferences/applications-accessories.png + icons/preferences/applications-internet.png + icons/preferences/applications-system.png + icons/preferences/applications-webbrowsers.png + icons/preferences/contact-new.png + icons/preferences/preferences-desktop.png + icons/preferences/gnome-window-manager.png + icons/preferences/history_entry.png + icons/preferences/stock_inbox.png + icons/faenza/back.png + icons/faenza/close.png + icons/faenza/forward.png + icons/faenza/home.png + icons/faenza/reload.png + icons/faenza/source.png + icons/faenza/stop.png + icons/preferences/extension.png + icons/faenza/settings.png + qupzilla.png + icons/locationbar/arrow-down.gif + icons/locationbar/gotoaddress.png + icons/locationbar/lineedit.png + icons/locationbar/privatebrowsing.png + icons/locationbar/safeline.png + icons/locationbar/search.png + icons/locationbar/searchchoose.png + icons/locationbar/secure.gif + icons/locationbar/unknownpage.png + icons/menu/bookmark_add.png + icons/menu/book_open_mark.png + icons/menu/bug_magnify.png + icons/menu/circle.png + icons/menu/csfd.png + icons/menu/cz_seznam.png + icons/menu/flash.png + icons/menu/google.png + icons/menu/history.png + icons/menu/history_entry.png + icons/menu/icon-wikipedia.png + icons/menu/popup.png + icons/menu/qt.png + icons/menu/rss.png + icons/menu/youtube.png + icons/other/about.png + icons/other/feed.png + icons/other/plus.png + icons/other/progress.gif + icons/navigation/search.gif + icons/locationbar/star.png + icons/locationbar/starg.png + icons/other/bigstar.png + icons/other/unsortedbookmarks.png + icons/locationbar/accept.png + icons/locationbar/warning.png + icons/other/flash.png + icons/other/flashstart.png + icons/other/keys.png + + diff --git a/src/data/icons/faenza/back.png b/src/data/icons/faenza/back.png new file mode 100644 index 000000000..410c8974b Binary files /dev/null and b/src/data/icons/faenza/back.png differ diff --git a/src/data/icons/faenza/close.png b/src/data/icons/faenza/close.png new file mode 100644 index 000000000..563944431 Binary files /dev/null and b/src/data/icons/faenza/close.png differ diff --git a/src/data/icons/faenza/forward.png b/src/data/icons/faenza/forward.png new file mode 100644 index 000000000..064dc87ea Binary files /dev/null and b/src/data/icons/faenza/forward.png differ diff --git a/src/data/icons/faenza/home.png b/src/data/icons/faenza/home.png new file mode 100644 index 000000000..9e2223dde Binary files /dev/null and b/src/data/icons/faenza/home.png differ diff --git a/src/data/icons/faenza/reload.png b/src/data/icons/faenza/reload.png new file mode 100644 index 000000000..62b325bc1 Binary files /dev/null and b/src/data/icons/faenza/reload.png differ diff --git a/src/data/icons/faenza/settings.png b/src/data/icons/faenza/settings.png new file mode 100644 index 000000000..b06eeff50 Binary files /dev/null and b/src/data/icons/faenza/settings.png differ diff --git a/src/data/icons/faenza/source.png b/src/data/icons/faenza/source.png new file mode 100644 index 000000000..b6494c55e Binary files /dev/null and b/src/data/icons/faenza/source.png differ diff --git a/src/data/icons/faenza/stop.png b/src/data/icons/faenza/stop.png new file mode 100644 index 000000000..6c36b2f6a Binary files /dev/null and b/src/data/icons/faenza/stop.png differ diff --git a/src/data/icons/lineedit.psd b/src/data/icons/lineedit.psd new file mode 100644 index 000000000..d8de8c80e Binary files /dev/null and b/src/data/icons/lineedit.psd differ diff --git a/src/data/icons/locationbar/accept.png b/src/data/icons/locationbar/accept.png new file mode 100644 index 000000000..0a2b4f325 Binary files /dev/null and b/src/data/icons/locationbar/accept.png differ diff --git a/src/data/icons/locationbar/arrow-down.gif b/src/data/icons/locationbar/arrow-down.gif new file mode 100644 index 000000000..e4588a9b5 Binary files /dev/null and b/src/data/icons/locationbar/arrow-down.gif differ diff --git a/src/data/icons/locationbar/gotoaddress.png b/src/data/icons/locationbar/gotoaddress.png new file mode 100644 index 000000000..fdefe966b Binary files /dev/null and b/src/data/icons/locationbar/gotoaddress.png differ diff --git a/src/data/icons/locationbar/lineedit.png b/src/data/icons/locationbar/lineedit.png new file mode 100644 index 000000000..2f159b294 Binary files /dev/null and b/src/data/icons/locationbar/lineedit.png differ diff --git a/src/data/icons/locationbar/privatebrowsing.png b/src/data/icons/locationbar/privatebrowsing.png new file mode 100644 index 000000000..5294896a3 Binary files /dev/null and b/src/data/icons/locationbar/privatebrowsing.png differ diff --git a/src/data/icons/locationbar/safeline.png b/src/data/icons/locationbar/safeline.png new file mode 100644 index 000000000..55f20311f Binary files /dev/null and b/src/data/icons/locationbar/safeline.png differ diff --git a/src/data/icons/locationbar/search.png b/src/data/icons/locationbar/search.png new file mode 100644 index 000000000..5572b418b Binary files /dev/null and b/src/data/icons/locationbar/search.png differ diff --git a/src/data/icons/locationbar/searchchoose.png b/src/data/icons/locationbar/searchchoose.png new file mode 100644 index 000000000..8a53ff74c Binary files /dev/null and b/src/data/icons/locationbar/searchchoose.png differ diff --git a/src/data/icons/locationbar/secure.gif b/src/data/icons/locationbar/secure.gif new file mode 100644 index 000000000..f70cc953a Binary files /dev/null and b/src/data/icons/locationbar/secure.gif differ diff --git a/src/data/icons/locationbar/star.png b/src/data/icons/locationbar/star.png new file mode 100644 index 000000000..c11a61445 Binary files /dev/null and b/src/data/icons/locationbar/star.png differ diff --git a/src/data/icons/locationbar/starg.png b/src/data/icons/locationbar/starg.png new file mode 100644 index 000000000..9f7a8db52 Binary files /dev/null and b/src/data/icons/locationbar/starg.png differ diff --git a/src/data/icons/locationbar/unknownpage.png b/src/data/icons/locationbar/unknownpage.png new file mode 100644 index 000000000..53cb35451 Binary files /dev/null and b/src/data/icons/locationbar/unknownpage.png differ diff --git a/src/data/icons/locationbar/warning.png b/src/data/icons/locationbar/warning.png new file mode 100644 index 000000000..01ad7d038 Binary files /dev/null and b/src/data/icons/locationbar/warning.png differ diff --git a/src/data/icons/menu/book_open_mark.png b/src/data/icons/menu/book_open_mark.png new file mode 100644 index 000000000..d4d33e631 Binary files /dev/null and b/src/data/icons/menu/book_open_mark.png differ diff --git a/src/data/icons/menu/bookmark_add.png b/src/data/icons/menu/bookmark_add.png new file mode 100644 index 000000000..c63960dd7 Binary files /dev/null and b/src/data/icons/menu/bookmark_add.png differ diff --git a/src/data/icons/menu/bug_magnify.png b/src/data/icons/menu/bug_magnify.png new file mode 100644 index 000000000..18795fec3 Binary files /dev/null and b/src/data/icons/menu/bug_magnify.png differ diff --git a/src/data/icons/menu/circle.png b/src/data/icons/menu/circle.png new file mode 100644 index 000000000..702b35ba2 Binary files /dev/null and b/src/data/icons/menu/circle.png differ diff --git a/src/data/icons/menu/copy.png b/src/data/icons/menu/copy.png new file mode 100644 index 000000000..3836257fe Binary files /dev/null and b/src/data/icons/menu/copy.png differ diff --git a/src/data/icons/menu/csfd.png b/src/data/icons/menu/csfd.png new file mode 100644 index 000000000..b50c8194e Binary files /dev/null and b/src/data/icons/menu/csfd.png differ diff --git a/src/data/icons/menu/cz_seznam.png b/src/data/icons/menu/cz_seznam.png new file mode 100644 index 000000000..c8797215f Binary files /dev/null and b/src/data/icons/menu/cz_seznam.png differ diff --git a/src/data/icons/menu/flash.png b/src/data/icons/menu/flash.png new file mode 100644 index 000000000..2e3b8916f Binary files /dev/null and b/src/data/icons/menu/flash.png differ diff --git a/src/data/icons/menu/google.png b/src/data/icons/menu/google.png new file mode 100644 index 000000000..f106c309f Binary files /dev/null and b/src/data/icons/menu/google.png differ diff --git a/src/data/icons/menu/history.png b/src/data/icons/menu/history.png new file mode 100644 index 000000000..7d6c709ff Binary files /dev/null and b/src/data/icons/menu/history.png differ diff --git a/src/data/icons/menu/history_entry.png b/src/data/icons/menu/history_entry.png new file mode 100644 index 000000000..ca070769f Binary files /dev/null and b/src/data/icons/menu/history_entry.png differ diff --git a/src/data/icons/menu/icon-wikipedia.png b/src/data/icons/menu/icon-wikipedia.png new file mode 100644 index 000000000..151431431 Binary files /dev/null and b/src/data/icons/menu/icon-wikipedia.png differ diff --git a/src/data/icons/menu/popup.png b/src/data/icons/menu/popup.png new file mode 100644 index 000000000..8e103fc76 Binary files /dev/null and b/src/data/icons/menu/popup.png differ diff --git a/src/data/icons/menu/qt.png b/src/data/icons/menu/qt.png new file mode 100644 index 000000000..91b80aea6 Binary files /dev/null and b/src/data/icons/menu/qt.png differ diff --git a/src/data/icons/menu/rss.png b/src/data/icons/menu/rss.png new file mode 100644 index 000000000..d1705aa34 Binary files /dev/null and b/src/data/icons/menu/rss.png differ diff --git a/src/data/icons/menu/youtube.png b/src/data/icons/menu/youtube.png new file mode 100644 index 000000000..70455baca Binary files /dev/null and b/src/data/icons/menu/youtube.png differ diff --git a/src/data/icons/navigation/close.png b/src/data/icons/navigation/close.png new file mode 100644 index 000000000..f1f56df16 Binary files /dev/null and b/src/data/icons/navigation/close.png differ diff --git a/src/data/icons/navigation/home.png b/src/data/icons/navigation/home.png new file mode 100644 index 000000000..932b9e20b Binary files /dev/null and b/src/data/icons/navigation/home.png differ diff --git a/src/data/icons/navigation/home_.png b/src/data/icons/navigation/home_.png new file mode 100644 index 000000000..54c377c0c Binary files /dev/null and b/src/data/icons/navigation/home_.png differ diff --git a/src/data/icons/navigation/newtab.png b/src/data/icons/navigation/newtab.png new file mode 100644 index 000000000..4f2fc9d6d Binary files /dev/null and b/src/data/icons/navigation/newtab.png differ diff --git a/src/data/icons/navigation/reload.png b/src/data/icons/navigation/reload.png new file mode 100644 index 000000000..2e67f83ec Binary files /dev/null and b/src/data/icons/navigation/reload.png differ diff --git a/src/data/icons/navigation/search.gif b/src/data/icons/navigation/search.gif new file mode 100644 index 000000000..e521d8bd0 Binary files /dev/null and b/src/data/icons/navigation/search.gif differ diff --git a/src/data/icons/navigation/search.png b/src/data/icons/navigation/search.png new file mode 100644 index 000000000..12750e733 Binary files /dev/null and b/src/data/icons/navigation/search.png differ diff --git a/src/data/icons/navigation/stop.png b/src/data/icons/navigation/stop.png new file mode 100644 index 000000000..3f7b348bb Binary files /dev/null and b/src/data/icons/navigation/stop.png differ diff --git a/src/data/icons/navigation/vpred.png b/src/data/icons/navigation/vpred.png new file mode 100644 index 000000000..e42c86900 Binary files /dev/null and b/src/data/icons/navigation/vpred.png differ diff --git a/src/data/icons/navigation/windowlose.png b/src/data/icons/navigation/windowlose.png new file mode 100644 index 000000000..939a102c9 Binary files /dev/null and b/src/data/icons/navigation/windowlose.png differ diff --git a/src/data/icons/navigation/zpet.png b/src/data/icons/navigation/zpet.png new file mode 100644 index 000000000..d61837ffb Binary files /dev/null and b/src/data/icons/navigation/zpet.png differ diff --git a/src/data/icons/other/about.png b/src/data/icons/other/about.png new file mode 100644 index 000000000..2e0736ad5 Binary files /dev/null and b/src/data/icons/other/about.png differ diff --git a/src/data/icons/other/bigstar.png b/src/data/icons/other/bigstar.png new file mode 100644 index 000000000..f20137b8f Binary files /dev/null and b/src/data/icons/other/bigstar.png differ diff --git a/src/data/icons/other/feed.png b/src/data/icons/other/feed.png new file mode 100644 index 000000000..7d1777449 Binary files /dev/null and b/src/data/icons/other/feed.png differ diff --git a/src/data/icons/other/flash.png b/src/data/icons/other/flash.png new file mode 100644 index 000000000..590c561f3 Binary files /dev/null and b/src/data/icons/other/flash.png differ diff --git a/src/data/icons/other/flashstart.png b/src/data/icons/other/flashstart.png new file mode 100644 index 000000000..c930ee7ae Binary files /dev/null and b/src/data/icons/other/flashstart.png differ diff --git a/src/data/icons/other/keys.png b/src/data/icons/other/keys.png new file mode 100644 index 000000000..621e722ba Binary files /dev/null and b/src/data/icons/other/keys.png differ diff --git a/src/data/icons/other/plus.png b/src/data/icons/other/plus.png new file mode 100644 index 000000000..7428c4899 Binary files /dev/null and b/src/data/icons/other/plus.png differ diff --git a/src/data/icons/other/progress.gif b/src/data/icons/other/progress.gif new file mode 100644 index 000000000..5dafb9cb7 Binary files /dev/null and b/src/data/icons/other/progress.gif differ diff --git a/src/data/icons/other/unsortedbookmarks.png b/src/data/icons/other/unsortedbookmarks.png new file mode 100644 index 000000000..89a94999a Binary files /dev/null and b/src/data/icons/other/unsortedbookmarks.png differ diff --git a/src/data/icons/preferences/applications-accessories.png b/src/data/icons/preferences/applications-accessories.png new file mode 100644 index 000000000..3d68f146c Binary files /dev/null and b/src/data/icons/preferences/applications-accessories.png differ diff --git a/src/data/icons/preferences/applications-internet.png b/src/data/icons/preferences/applications-internet.png new file mode 100644 index 000000000..ad16eda58 Binary files /dev/null and b/src/data/icons/preferences/applications-internet.png differ diff --git a/src/data/icons/preferences/applications-system.png b/src/data/icons/preferences/applications-system.png new file mode 100644 index 000000000..a40ffab1b Binary files /dev/null and b/src/data/icons/preferences/applications-system.png differ diff --git a/src/data/icons/preferences/applications-webbrowsers.png b/src/data/icons/preferences/applications-webbrowsers.png new file mode 100644 index 000000000..41afcfdc1 Binary files /dev/null and b/src/data/icons/preferences/applications-webbrowsers.png differ diff --git a/src/data/icons/preferences/contact-new.png b/src/data/icons/preferences/contact-new.png new file mode 100644 index 000000000..a61c598c5 Binary files /dev/null and b/src/data/icons/preferences/contact-new.png differ diff --git a/src/data/icons/preferences/extension.png b/src/data/icons/preferences/extension.png new file mode 100644 index 000000000..369a16712 Binary files /dev/null and b/src/data/icons/preferences/extension.png differ diff --git a/src/data/icons/preferences/gnome-window-manager.png b/src/data/icons/preferences/gnome-window-manager.png new file mode 100644 index 000000000..3c840aae3 Binary files /dev/null and b/src/data/icons/preferences/gnome-window-manager.png differ diff --git a/src/data/icons/preferences/history_entry.png b/src/data/icons/preferences/history_entry.png new file mode 100644 index 000000000..8e5831ab5 Binary files /dev/null and b/src/data/icons/preferences/history_entry.png differ diff --git a/src/data/icons/preferences/preferences-desktop.png b/src/data/icons/preferences/preferences-desktop.png new file mode 100644 index 000000000..218b34652 Binary files /dev/null and b/src/data/icons/preferences/preferences-desktop.png differ diff --git a/src/data/icons/preferences/stock_inbox.png b/src/data/icons/preferences/stock_inbox.png new file mode 100644 index 000000000..2ce02e932 Binary files /dev/null and b/src/data/icons/preferences/stock_inbox.png differ diff --git a/src/data/icons/qupzilla.png b/src/data/icons/qupzilla.png new file mode 100644 index 000000000..7ab68d53b Binary files /dev/null and b/src/data/icons/qupzilla.png differ diff --git a/src/data/icons/qupzillaupdate.png b/src/data/icons/qupzillaupdate.png new file mode 100644 index 000000000..4873d4b48 Binary files /dev/null and b/src/data/icons/qupzillaupdate.png differ diff --git a/src/data/icons/transp.png b/src/data/icons/transp.png new file mode 100644 index 000000000..c55289094 Binary files /dev/null and b/src/data/icons/transp.png differ diff --git a/src/data/qupzilla.png b/src/data/qupzilla.png new file mode 100644 index 000000000..9eb367c89 Binary files /dev/null and b/src/data/qupzilla.png differ diff --git a/src/downloads/downloaditem.cpp b/src/downloads/downloaditem.cpp new file mode 100644 index 000000000..ae189041f --- /dev/null +++ b/src/downloads/downloaditem.cpp @@ -0,0 +1,255 @@ +#include "downloaditem.h" +#include "ui_downloaditem.h" + +DownloadItem::DownloadItem(QListWidgetItem *item, QNetworkReply *reply, QString path, QString fileName, QPixmap fileIcon, QWidget *parent) + : QWidget(parent) + ,ui(new Ui::DownloadItem) + ,m_item(item) + ,m_reply(reply) + ,m_path(path) + ,m_fileName(fileName) + ,m_downloading(false) +{ + QString fullPath = path+fileName; + if (QFile::exists(fullPath)) + QFile::remove(fullPath); + + m_outputFile.setFileName(fullPath); + + ui->setupUi(this); + ui->button->setPixmap( +#ifdef Q_WS_X11 + style()->standardIcon(QStyle::SP_BrowserStop).pixmap(20,20) +#else + QIcon(":/icons/faenza/stop.png").pixmap(20,20) +#endif + ); + ui->fileName->setText(m_fileName); + ui->downloadInfo->setText(tr("Remaining time unavailable")); + ui->fileIcon->setPixmap(fileIcon); + + setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(customContextMenuRequested(QPoint))); + connect(m_reply, SIGNAL(finished()), this, SLOT(finished())); + connect(m_reply, SIGNAL(readyRead()), this, SLOT(readyRead())); + connect(m_reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(downloadProgress(qint64, qint64))); + connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError))); + connect(ui->button, SIGNAL(clicked(QPoint)), this, SLOT(stop())); + + m_downloading = true; + m_downTimer.start(); + m_timer.start(1000*1, this); + readyRead(); + QTimer::singleShot(500, this, SLOT(updateDownload())); + + if (m_reply->error() != QNetworkReply::NoError) { + stop(); + error(m_reply->error()); + } + show(); +} + +void DownloadItem::finished() +{ + m_timer.stop(); + ui->downloadInfo->setText(tr("Done - %1").arg(m_reply->url().host())); + ui->progressBar->hide(); + ui->button->hide(); + ui->frame->hide(); + m_outputFile.close(); + + m_item->setSizeHint(sizeHint()); +#if QT_VERSION == 0x040700 // Workaround + ui->button->show(); + ui->button->hide(); +#endif + m_downloading = false; +} + +void DownloadItem::downloadProgress(qint64 received, qint64 total) +{ + qint64 currentValue = 0; + qint64 totalValue = 0; + if (total > 0) { + currentValue = received * 100 / total; + totalValue = 100; + } + ui->progressBar->setValue(currentValue); + ui->progressBar->setMaximum(totalValue); + m_currSpeed = received * 1000.0 / m_downTimer.elapsed(); + m_received = received; + m_total = total; +} + +void DownloadItem::timerEvent(QTimerEvent *event) +{ + if (event->timerId() == m_timer.timerId()) { + updateDownloadInfo(m_currSpeed, m_received, m_total); + } else + QWidget::timerEvent(event); +} + +int DownloadItem::progress() +{ + return ui->progressBar->value(); +} + +bool DownloadItem::isCancelled() +{ + return ui->downloadInfo->text().startsWith(tr("Cancelled")); +} + +QString DownloadItem::remaingTimeToString(QTime time) +{ + if (time1000) { + speed/=1024; + return QString::number(speed, 'g', 3)+" MB/s"; + }else + return QString::number(speed, 'g', 3)+" kB/s"; +} + +QString DownloadItem::fileSizeToString(int size) +{ + size/=1024; + if (size>1000) { + size/=1024; + return QString::number(size)+" MB"; + }else + return QString::number(size)+" kB"; +} + +void DownloadItem::updateDownloadInfo(double currSpeed, qint64 received, qint64 total) +{ + // QString QString QString QString + // | m_remTime | |m_currSize| |m_fileSize| |m_speed| + // Remaining 26 minutes - 339MB of 693 MB (350kB/s) + + int estimatedTime=((total-received)/1024) / (currSpeed/1024); + QString speed = currentSpeedToString(currSpeed); + // We have QString speed now + + QTime time; + time = time.addSecs(estimatedTime); + QString remTime = remaingTimeToString(time); + m_remTime = time; + + QString currSize = fileSizeToString(received); + QString fileSize = fileSizeToString(total); + + ui->downloadInfo->setText(tr("Remaining %1 - %2 of %3 (%4)").arg(remTime, currSize, fileSize, speed)); +} + +void DownloadItem::stop() +{ + m_timer.stop(); + m_reply->abort(); + QString outputfile = QFileInfo(m_outputFile).absoluteFilePath(); + m_outputFile.close(); + ui->downloadInfo->setText(tr("Cancelled - %1").arg(m_reply->url().host())); + ui->progressBar->hide(); + ui->button->hide(); + m_item->setSizeHint(sizeHint()); + +#if QT_VERSION == 0x040700 // Workaround + ui->button->show(); + ui->button->hide(); +#endif + + QFile::remove(outputfile); + m_downloading = false; +} + +void DownloadItem::mouseDoubleClickEvent(QMouseEvent *e) +{ + openFile(); + e->accept(); +} + +void DownloadItem::customContextMenuRequested(QPoint pos) +{ + QMenu menu; + menu.addAction(QIcon::fromTheme("document-open"), tr("Open File"), this, SLOT(openFile())); + + menu.addAction(tr("Open Folder"), this, SLOT(openFolder())); + menu.addSeparator(); + menu.addAction( +#ifdef Q_WS_X11 + style()->standardIcon(QStyle::SP_BrowserStop) +#else + QIcon(":/icons/faenza/stop.png") +#endif + ,tr("Cancel downloading"), this, SLOT(stop())); + menu.addAction(QIcon::fromTheme("window-close"), tr("Clear"), this, SLOT(clear())); + + if (m_downloading || ui->downloadInfo->text().startsWith(tr("Cancelled")) || ui->downloadInfo->text().startsWith(tr("Error"))) + menu.actions().at(0)->setEnabled(false); + if (!m_downloading) + menu.actions().at(3)->setEnabled(false); + if (m_downloading) + menu.actions().at(4)->setEnabled(false); + menu.exec(mapToGlobal(pos)); +} + +void DownloadItem::clear() +{ + emit deleteItem(this); +} + +void DownloadItem::openFile() +{ + if (m_downloading) + return; + QFileInfo info(m_path+m_fileName); + if (info.exists()) + QDesktopServices::openUrl(QUrl::fromLocalFile(info.absoluteFilePath())); + else + QMessageBox::warning(m_item->listWidget(), tr("Not found"), tr("Sorry, the file \n %1 \n is not found!").arg(info.absoluteFilePath())); +} + +void DownloadItem::openFolder() +{ + QDesktopServices::openUrl(QUrl::fromLocalFile(m_path)); +} + +void DownloadItem::readyRead() +{ + if (!m_outputFile.isOpen() && !m_outputFile.open(QIODevice::WriteOnly)) { + stop(); + ui->downloadInfo->setText(tr("Error: Cannot write to file!")); + return; + } + m_outputFile.write(m_reply->readAll()); +} + +void DownloadItem::error(QNetworkReply::NetworkError error) +{ + if (error != QNetworkReply::NoError) + ui->downloadInfo->setText(tr("Error: ")+m_reply->errorString()); +} + +void DownloadItem::updateDownload() +{ + if (ui->progressBar->maximum() == 0 && m_outputFile.isOpen() && m_reply->isFinished()) { + downloadProgress(0,0); + finished(); + } +} + +DownloadItem::~DownloadItem() +{ + delete ui; + delete m_item; +} diff --git a/src/downloads/downloaditem.h b/src/downloads/downloaditem.h new file mode 100644 index 000000000..b304d422f --- /dev/null +++ b/src/downloads/downloaditem.h @@ -0,0 +1,76 @@ +#ifndef DOWNLOADITEM_H +#define DOWNLOADITEM_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Ui { + class DownloadItem; +} + +class DownloadItem : public QWidget +{ + Q_OBJECT + +public: + explicit DownloadItem(QListWidgetItem* item, QNetworkReply* reply ,QString path, QString fileName, QPixmap fileIcon, QWidget *parent = 0); + bool isDownloading() { return m_downloading; } + bool isCancelled(); + QTime remainingTime() { return m_remTime; } + double currentSpeed() { return m_currSpeed; } + int progress(); + ~DownloadItem(); + + static QString remaingTimeToString(QTime time); + static QString currentSpeedToString(double speed); + static QString fileSizeToString(int size); + +signals: + void deleteItem(DownloadItem*); + +private slots: + void finished(); + void downloadProgress(qint64 received, qint64 total); + void stop(); + void openFile(); + void openFolder(); + void readyRead(); + void error(QNetworkReply::NetworkError); + void updateDownload(); + void customContextMenuRequested(QPoint pos); + void clear(); + +private: + void timerEvent(QTimerEvent *event); + void updateDownloadInfo(double currSpeed, qint64 received, qint64 total); + void mouseDoubleClickEvent(QMouseEvent *e); + Ui::DownloadItem *ui; + + QListWidgetItem* m_item; + QNetworkReply* m_reply; + QString m_path; + QString m_fileName; + QTime m_downTimer; + QTime m_remTime; + QBasicTimer m_timer; + QFile m_outputFile; + + bool m_downloading; + double m_currSpeed; + qint64 m_received; + qint64 m_total; +}; + +#endif // DOWNLOADITEM_H diff --git a/src/downloads/downloaditem.ui b/src/downloads/downloaditem.ui new file mode 100644 index 000000000..2e31f7b7c --- /dev/null +++ b/src/downloads/downloaditem.ui @@ -0,0 +1,113 @@ + + + DownloadItem + + + + 0 + 0 + 480 + 73 + + + + Form + + + + 2 + + + 2 + + + + + + 30 + 50 + + + + + + + Qt::AlignCenter + + + + + + + font-size: 13pt; + + + A Clockwork Orange.avi + + + + + + + Remaining 26 minutes - 339MB of 693 MB (350kB/s) + + + + + + + + 16777215 + 20 + + + + + 0 + + + + + margin-bottom: 1px; + + + 0 + + + 0 + + + false + + + + + + + + + + + + + + + + + + + + + SqueezeLabel + QLabel +
    squeezelabel.h
    +
    + + ClickableLabel + QLabel +
    clickablelabel.h
    +
    +
    + + +
    diff --git a/src/downloads/downloadmanager.cpp b/src/downloads/downloadmanager.cpp new file mode 100644 index 000000000..d18374264 --- /dev/null +++ b/src/downloads/downloadmanager.cpp @@ -0,0 +1,247 @@ +#include "downloadmanager.h" +#include "ui_downloadmanager.h" +#include "qupzilla.h" +#include "downloadoptionsdialog.h" +#include "downloaditem.h" +#include "ecwin7.h" + +DownloadManager::DownloadManager(QWidget *parent) : + QWidget(parent) + ,ui(new Ui::DownloadManager) + ,m_isClosing(false) +{ + ui->setupUi(this); + ui->clearButton->setIcon(QIcon::fromTheme("edit-clear")); + //CENTER on screen + const QRect screen = QApplication::desktop()->screenGeometry(); + const QRect &size = QWidget::geometry(); + QWidget::move( (screen.width()-size.width())/2, (screen.height()-size.height())/2 ); + + m_iconProvider = new QFileIconProvider(); + m_networkManager = new QNetworkAccessManager(); + + QSettings settings(MainApplication::getInstance()->getActiveProfil()+"settings.ini", QSettings::IniFormat); + settings.beginGroup("DownloadManager"); + m_downloadPath = settings.value("defaultDownloadPath", QDir::homePath()).toString(); + m_lastDownloadPath = settings.value("lastDownloadPath","").toString(); + settings.endGroup(); + + connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clearList())); + +#ifdef Q_WS_WIN + win7.init(this->winId()); +#endif +} + +#ifdef Q_WS_WIN +bool DownloadManager::winEvent(MSG *message, long *result) +{ + return win7.winEvent(message, result); +} +#endif + +void DownloadManager::timerEvent(QTimerEvent *event) +{ + QList remTimes; + QList progresses; + QList speeds; + + if (event->timerId() == m_timer.timerId()) { + if (!ui->list->count()) { + ui->speedLabel->clear(); + setWindowTitle(tr("Download Manager")); + return; + } + for (int i = 0; i < ui->list->count(); i++) { + DownloadItem* downItem = qobject_cast(ui->list->itemWidget(ui->list->item(i))); + if (!downItem || (downItem && downItem->isCancelled())) + continue; + if (!downItem->isDownloading()) { + progresses.append(100); + continue; + } else + progresses.append(downItem->progress()); + remTimes.append(downItem->remainingTime()); + speeds.append(downItem->currentSpeed()); + } + if (remTimes.isEmpty()) { + ui->speedLabel->clear(); + setWindowTitle(tr("Download Manager")); + return; + } + + QTime remaining; + foreach (QTime time, remTimes) { + if (time > remaining) + remaining = time; + } + + int progress = 0; + foreach (int prog, progresses) + progress+=prog; + progress = progress / progresses.count(); + + double speed = 0.00; + foreach (double spee, speeds) + speed+=spee; + + ui->speedLabel->setText(tr("%1% of %2 files (%3) %4 remaining").arg(QString::number(progress),QString::number(progresses.count()), + DownloadItem::currentSpeedToString(speed), + DownloadItem::remaingTimeToString(remaining))); + setWindowTitle(QString::number(progress) + tr("% - Download Manager")); +#ifdef Q_WS_WIN + win7.setProgressValue(progress, 100); + win7.setProgressState(win7.Normal); +#endif + } else + QWidget::timerEvent(event); +} + +void DownloadManager::clearList() +{ + QList items; + for (int i = 0; i < ui->list->count(); i++) { + DownloadItem* downItem = qobject_cast(ui->list->itemWidget(ui->list->item(i))); + if (!downItem) + continue; + if (downItem->isDownloading()) + continue; + items.append(downItem); + } + qDeleteAll(items); +} + +void DownloadManager::download(const QNetworkRequest &request) +{ + handleUnsupportedContent(m_networkManager->get(request)); +} + +void DownloadManager::handleUnsupportedContent(QNetworkReply *reply) +{ +// DownloadOptionsDialog* dialog = new DownloadOptionsDialog(); +// dialog->show(); +// dialog->setAttribute(Qt::WA_DeleteOnClose); + + QString path; + QString fileName; + + QString userFileName; + + QString _fileName = getFileName(reply); + + if (m_downloadPath.isEmpty()) + userFileName = QFileDialog::getSaveFileName(MainApplication::getInstance()->getWindow(), tr("Save file as..."),m_lastDownloadPath+_fileName); + else + userFileName = m_downloadPath+_fileName; + + if (userFileName.isEmpty()) { + reply->abort(); + return; + } + + int pos = userFileName.lastIndexOf("/"); + if (pos!=-1) { + int size = userFileName.size(); + path = userFileName.left(pos+1); + fileName = userFileName.right(size-pos-1); + } + + m_lastDownloadPath = path; + QSettings settings(MainApplication::getInstance()->getActiveProfil()+"settings.ini", QSettings::IniFormat); + settings.beginGroup("DownloadManager"); + settings.setValue("lastDownloadPath",m_lastDownloadPath); + settings.endGroup(); + + QFileInfo info(reply->url().toString()); + QTemporaryFile tempFile("XXXXXX."+info.suffix()); + tempFile.open(); + QFileInfo tempInfo(tempFile.fileName()); + QPixmap fileIcon = m_iconProvider->icon(tempInfo).pixmap(30,30); + + QListWidgetItem* item = new QListWidgetItem(ui->list); + DownloadItem* downItem = new DownloadItem(item, reply, path, fileName, fileIcon); + connect(downItem, SIGNAL(deleteItem(DownloadItem*)), this, SLOT(deleteItem(DownloadItem*))); + ui->list->setItemWidget(item, downItem); + item->setSizeHint(downItem->sizeHint()); + show(); + activateWindow(); +} + +void DownloadManager::deleteItem(DownloadItem *item) +{ + if (item && !item->isDownloading()) + delete item; +} + +QString DownloadManager::getFileName(QNetworkReply *reply) +{ + QString path; + if (reply->hasRawHeader("Content-Disposition")) { + QString value = reply->rawHeader("Content-Disposition"); + int pos = value.indexOf("filename="); + if (pos!=-1) { + QString name = value.mid(pos + 9); + if (name.startsWith('"') && name.endsWith('"')) + name = name.mid(1, name.size() - 2); + path = name; + } + } + if (path.isEmpty()) + path = reply->url().path(); + + QFileInfo info(path); + QString baseName = info.completeBaseName(); + QString endName = info.suffix(); + + if (baseName.isEmpty()) { + baseName = tr("NoNameDownload"); + } + + if (!endName.isEmpty()) + endName="."+endName; + + return baseName+endName; +} + +bool DownloadManager::canClose() +{ + if (m_isClosing) + return true; + + bool isDownloading = false; + for (int i = 0; i < ui->list->count(); i++) { + DownloadItem* downItem = qobject_cast(ui->list->itemWidget(ui->list->item(i))); + if (!downItem) + continue; + if (downItem->isDownloading()) { + isDownloading = true; + break; + } + } + + return !isDownloading; +} + +void DownloadManager::closeEvent(QCloseEvent *e) +{ + if (!MainApplication::getInstance()->getWindow()) { // No main windows -> we are going to quit + if (!canClose()){ + QMessageBox::StandardButton button = QMessageBox::warning(this, tr("Warning"), + tr("Are you sure to quit? All uncompleted downloads will be cancelled!"), QMessageBox::Yes | QMessageBox::No); + if (button != QMessageBox::Yes) { + e->ignore(); + return; + } + m_isClosing = true; + } + MainApplication::getInstance()->quitApplication(); + } + e->accept(); +} + +DownloadManager::~DownloadManager() +{ + delete ui; + delete m_networkManager; + delete m_iconProvider; +} diff --git a/src/downloads/downloadmanager.h b/src/downloads/downloadmanager.h new file mode 100644 index 000000000..761384dc5 --- /dev/null +++ b/src/downloads/downloadmanager.h @@ -0,0 +1,74 @@ +#ifndef DOWNLOADMANAGER_H +#define DOWNLOADMANAGER_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Ui { + class DownloadManager; +} + +class DownloadItem; +class EcWin7; +class DownloadManager : public QWidget +{ + Q_OBJECT + +public: + explicit DownloadManager(QWidget *parent = 0); + ~DownloadManager(); + + void download(const QNetworkRequest &request); + void handleUnsupportedContent(QNetworkReply* reply); + bool canClose(); + + void show() { m_timer.start(1000*2, this); QWidget::show(); } + +#ifdef Q_WS_WIN +protected: + virtual bool winEvent(MSG *message, long *result); +#endif + +private slots: + void clearList(); + void deleteItem(DownloadItem* item); + +private: +#ifdef Q_WS_WIN + EcWin7 win7; +#endif + void timerEvent(QTimerEvent *event); + QString getFileName(QNetworkReply* reply); + void closeEvent(QCloseEvent *e); + + Ui::DownloadManager *ui; + QNetworkAccessManager* m_networkManager; + QFileIconProvider* m_iconProvider; + + QString m_lastDownloadPath; + QString m_downloadPath; + QBasicTimer m_timer; + + bool m_isClosing; +}; + +#endif // DOWNLOADMANAGER_H diff --git a/src/downloads/downloadmanager.ui b/src/downloads/downloadmanager.ui new file mode 100644 index 000000000..db6575caa --- /dev/null +++ b/src/downloads/downloadmanager.ui @@ -0,0 +1,128 @@ + + + DownloadManager + + + + 0 + 0 + 529 + 315 + + + + Download Manager + + + + :/icons/qupzilla.png:/icons/qupzilla.png + + + + 0 + + + 0 + + + 0 + + + 0 + + + 4 + + + + + border: none; + + + true + + + + + + + Qt::Horizontal + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 2 + 20 + + + + + + + + + 0 + 0 + + + + Clear + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Minimum + + + + 40 + 20 + + + + + + + + + + + + + diff --git a/src/downloads/downloadoptionsdialog.cpp b/src/downloads/downloadoptionsdialog.cpp new file mode 100644 index 000000000..34d8fb3e0 --- /dev/null +++ b/src/downloads/downloadoptionsdialog.cpp @@ -0,0 +1,14 @@ +#include "downloadoptionsdialog.h" +#include "ui_downloadoptionsdialog.h" + +DownloadOptionsDialog::DownloadOptionsDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::DownloadOptionsDialog) +{ + ui->setupUi(this); +} + +DownloadOptionsDialog::~DownloadOptionsDialog() +{ + delete ui; +} diff --git a/src/downloads/downloadoptionsdialog.h b/src/downloads/downloadoptionsdialog.h new file mode 100644 index 000000000..a057261f9 --- /dev/null +++ b/src/downloads/downloadoptionsdialog.h @@ -0,0 +1,22 @@ +#ifndef DOWNLOADOPTIONSDIALOG_H +#define DOWNLOADOPTIONSDIALOG_H + +#include + +namespace Ui { + class DownloadOptionsDialog; +} + +class DownloadOptionsDialog : public QDialog +{ + Q_OBJECT + +public: + explicit DownloadOptionsDialog(QWidget *parent = 0); + ~DownloadOptionsDialog(); + +private: + Ui::DownloadOptionsDialog *ui; +}; + +#endif // DOWNLOADOPTIONSDIALOG_H diff --git a/src/downloads/downloadoptionsdialog.ui b/src/downloads/downloadoptionsdialog.ui new file mode 100644 index 000000000..3c82a2c58 --- /dev/null +++ b/src/downloads/downloadoptionsdialog.ui @@ -0,0 +1,205 @@ + + + DownloadOptionsDialog + + + + 0 + 0 + 416 + 279 + + + + Opening + + + + :/icons/qupzilla.png:/icons/qupzilla.png + + + + + + + + + 0 + 0 + + + + which is a: + + + + + + + + + + + + + + + + + + + 0 + 0 + + + + from: + + + + + + + + + + + + + + + + You have chosen to open + + + + + + + <b>What should QupZilla do with this file?</b> + + + + + + + Open... + + + true + + + + + + + Save File + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + DownloadOptionsDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + DownloadOptionsDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/history/historymanager.cpp b/src/history/historymanager.cpp new file mode 100644 index 000000000..677919ab8 --- /dev/null +++ b/src/history/historymanager.cpp @@ -0,0 +1,192 @@ +#include "historymanager.h" +#include "ui_historymanager.h" +#include "qupzilla.h" +#include "locationbar.h" + +HistoryManager::HistoryManager(QupZilla* mainClass, QWidget *parent) : + QWidget(parent) + ,ui(new Ui::HistoryManager) + ,p_QupZilla(mainClass) +{ + ui->setupUi(this); + //CENTER on scren + const QRect screen = QApplication::desktop()->screenGeometry(); + const QRect &size = QWidget::geometry(); + QWidget::move( (screen.width()-size.width())/2, (screen.height()-size.height())/2 ); + + connect(ui->historyTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),this, SLOT(itemDoubleClicked(QTreeWidgetItem*))); + connect(ui->close, SIGNAL(clicked(QAbstractButton*)), this, SLOT(hide())); + connect(ui->deleteB, SIGNAL(clicked()), this, SLOT(deleteItem())); + connect(ui->clearAll, SIGNAL(clicked()), this, SLOT(clearHistory())); + connect(ui->search, SIGNAL(cursorPositionChanged(int, int)), this, SLOT(search())); + connect(ui->historyTree, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(contextMenuRequested(const QPoint &))); + connect(ui->historyTree, SIGNAL(itemControlClicked(QTreeWidgetItem*)), this, SLOT(itemControlClicked(QTreeWidgetItem*))); + + //QTimer::singleShot(0, this, SLOT(refreshTable())); + + ui->search->setInactiveText(tr("Search")); +} + +QupZilla* HistoryManager::getQupZilla() +{ + if (!p_QupZilla) + p_QupZilla = MainApplication::getInstance()->getWindow(); + return p_QupZilla; +} + +void HistoryManager::setMainWindow(QupZilla *window) +{ + if (window) + p_QupZilla = window; +} + +void HistoryManager::itemDoubleClicked(QTreeWidgetItem *item) +{ + if (!item || item->text(1).isEmpty()) + return; + getQupZilla()->loadAddress(QUrl(item->text(1))); +} + +void HistoryManager::itemControlClicked(QTreeWidgetItem *item) +{ + if (!item || item->text(1).isEmpty()) + return; + getQupZilla()->tabWidget()->addView(QUrl(item->text(1))); +} + +void HistoryManager::loadInNewTab() +{ + if (QAction *action = qobject_cast(sender())) + getQupZilla()->tabWidget()->addView(action->data().toUrl(), tr("New Tab"), TabWidget::NewNotSelectedTab); +} + +void HistoryManager::contextMenuRequested(const QPoint &position) +{ + if (!ui->historyTree->itemAt(position)) + return; + QString link = ui->historyTree->itemAt(position)->text(1); + if (link.isEmpty()) + return; + + QMenu menu; + menu.addAction(tr("Open link in actual tab"), getQupZilla(), SLOT(loadActionUrl()))->setData(link); + menu.addAction(tr("Open link in new tab"), this, SLOT(loadInNewTab()))->setData(link); + menu.addSeparator(); + + menu.addSeparator(); + menu.addAction(tr("Close"), this, SLOT(close())); + + //Prevent choosing first option with double rightclick + QPoint pos = QCursor::pos(); + QPoint p(pos.x(), pos.y()+1); + menu.exec(p); +} + +void HistoryManager::deleteItem() +{ + QTreeWidgetItem* item = ui->historyTree->currentItem(); + if (!item) + return; + if (item->text(1).isEmpty()) + return; + + QString id = item->whatsThis(1); + QSqlQuery query; + query.exec("DELETE FROM history WHERE id="+id); + delete item; +} + +void HistoryManager::clearHistory() +{ + QMessageBox::StandardButton button = QMessageBox::warning(this, tr("Confirmation"), + tr("Are you sure to delete all history?"), QMessageBox::Yes | QMessageBox::No); + if (button != QMessageBox::Yes) + return; + + QSqlQuery query; + query.exec("DELETE FROM history"); + ui->historyTree->clear(); + query.exec("VACUUM"); +} + +void HistoryManager::refreshTable() +{ + ui->historyTree->setUpdatesEnabled(false); + ui->historyTree->clear(); + + QLocale locale(getQupZilla()->activeLanguage().remove(".qm")); + + QSqlQuery query; + query.exec("SELECT title, url, id, date FROM history ORDER BY date DESC"); + + while(query.next()) { + QString title = query.value(0).toString(); + QUrl url = query.value(1).toUrl(); + int id = query.value(2).toInt(); + qint64 unixDate = query.value(3).toLongLong(); + QDateTime date = QDateTime(); + date = date.fromMSecsSinceEpoch(unixDate); + + QString localDate; //date.toString("dddd d. MMMM yyyy"); + //QString day = locale.dayName(date.toString("d").toInt()); + + QString month = locale.monthName(date.toString("M").toInt()); + localDate = date.toString(" d. ") + month + date.toString(" yyyy"); + + QTreeWidgetItem* item; + QList findParent = ui->historyTree->findItems(localDate, 0); + if (findParent.count() == 1) { + item = new QTreeWidgetItem(findParent.at(0)); + }else{ + QTreeWidgetItem* newParent = new QTreeWidgetItem(ui->historyTree); + newParent->setText(0, localDate); + newParent->setIcon(0, QIcon(":/icons/menu/history_entry.png")); + ui->historyTree->addTopLevelItem(newParent); + item = new QTreeWidgetItem(newParent); + } + + item->setText(0, title); + item->setText(1, url.toEncoded()); + item->setToolTip(0, title); + item->setToolTip(1, url.toEncoded()); + + item->setWhatsThis(1, QString::number(id)); + item->setIcon(0, LocationBar::icon(url)); + ui->historyTree->addTopLevelItem(item); + } + + ui->historyTree->setUpdatesEnabled(true); +} + +void HistoryManager::search() +{ + QString searchText = ui->search->text(); + if (searchText.isEmpty()) { + refreshTable(); + return; + } + + refreshTable(); + ui->historyTree->setUpdatesEnabled(false); + + QList items = ui->historyTree->findItems("*"+searchText+"*", Qt::MatchRecursive | Qt::MatchWildcard); + + QList foundItems; + foreach(QTreeWidgetItem* fitem, items) { + if (fitem->text(1).isEmpty()) + continue; + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setText(0, fitem->text(0)); + item->setText(1, fitem->text(1)); + item->setWhatsThis(1, fitem->whatsThis(1)); + foundItems.append(item); + } + ui->historyTree->clear(); + ui->historyTree->addTopLevelItems(foundItems); + ui->historyTree->setUpdatesEnabled(true); +} + +HistoryManager::~HistoryManager() +{ + delete ui; +} diff --git a/src/history/historymanager.h b/src/history/historymanager.h new file mode 100644 index 000000000..f38d84b7b --- /dev/null +++ b/src/history/historymanager.h @@ -0,0 +1,45 @@ +#ifndef HISTORYMANAGER_H +#define HISTORYMANAGER_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include + +namespace Ui { + class HistoryManager; +} + +class QupZilla; +class HistoryManager : public QWidget +{ + Q_OBJECT + +public: + explicit HistoryManager(QupZilla* mainClass, QWidget *parent = 0); + ~HistoryManager(); + + void setMainWindow(QupZilla *window); + +public slots: + void refreshTable(); + +private slots: + void itemDoubleClicked(QTreeWidgetItem* item); + void deleteItem(); + void clearHistory(); + void search(); + void contextMenuRequested(const QPoint &position); + void loadInNewTab(); + void itemControlClicked(QTreeWidgetItem* item); + +private: + QupZilla* getQupZilla(); + Ui::HistoryManager *ui; + QPointer p_QupZilla; +}; + +#endif // HISTORYMANAGER_H diff --git a/src/history/historymanager.ui b/src/history/historymanager.ui new file mode 100644 index 000000000..0849ea07a --- /dev/null +++ b/src/history/historymanager.ui @@ -0,0 +1,96 @@ + + + HistoryManager + + + + 0 + 0 + 735 + 547 + + + + History + + + + :/icons/qupzilla.png:/icons/qupzilla.png + + + + + + Search in history: + + + + + + + + + + Qt::CustomContextMenu + + + true + + + 330 + + + + Title + + + + + Url + + + + + + + + Delete + + + Del + + + + + + + Clear All History + + + + + + + QDialogButtonBox::Close + + + + + + + + LineEdit + QLineEdit +
    lineedit.h
    +
    + + TreeWidget + QTreeWidget +
    treewidget.h
    +
    +
    + + + + +
    diff --git a/src/history/historymodel.cpp b/src/history/historymodel.cpp new file mode 100644 index 000000000..22669f570 --- /dev/null +++ b/src/history/historymodel.cpp @@ -0,0 +1,102 @@ +#include "historymodel.h" +#include "webview.h" +#include "qupzilla.h" + +HistoryModel::HistoryModel(QupZilla *mainClass, QObject *parent) + : QObject(parent) + ,m_isSaving(true) + ,p_QupZilla(mainClass) +{ + loadSettings(); +} + +void HistoryModel::loadSettings() +{ + QSettings settings(MainApplication::getInstance()->getActiveProfil()+"settings.ini", QSettings::IniFormat); + settings.beginGroup("Web-Browser-Settings"); + m_isSaving = settings.value("allowHistory",true).toBool(); +} + +int HistoryModel::addHistoryEntry(const QString &url, QString &title) +{ + if (!m_isSaving) + return -2; + if (url.contains("file://") || title.contains(tr("Failed loading page")) || url.isEmpty() || url.contains("about:blank") ) + return -1; + + QSqlQuery query; + query.prepare("SELECT id FROM history WHERE url=?"); + query.bindValue(0, url); + query.exec(); + if (!query.next()) { + QDateTime now = QDateTime::currentDateTime(); + if (title == "") + title=tr("No Named Page"); + query.prepare("INSERT INTO history (count, date, url, title) VALUES (1,?,?,?)"); + query.bindValue(0, now.toMSecsSinceEpoch()); + query.bindValue(1, url); + query.bindValue(2, title); + query.exec(); + }else{ + QDateTime now = QDateTime::currentDateTime(); + if (title == "") + title=tr("No Named Page"); + query.prepare("UPDATE history SET count = count + 1, date=? WHERE url=?"); + query.bindValue(0, now.toMSecsSinceEpoch()); + query.bindValue(1, url); + query.exec(); + } + return query.lastInsertId().toInt(); +} + +int HistoryModel::addHistoryEntry(WebView *view) +{ + if (!m_isSaving) + return -2; + QString url = view->url().toString(); + QString title = view->title(); + return addHistoryEntry(url, title); +} + +bool HistoryModel::deleteHistoryEntry(int index) +{ + QSqlQuery query; + query.prepare("DELETE FROM history WHERE id=?"); + query.bindValue(0, index); + if (query.exec()) + return true; + else return false; +} + +bool HistoryModel::deleteHistoryEntry(const QString &url, const QString &title) +{ + QSqlQuery query; + query.prepare("DELETE FROM history WHERE url=? AND title=?"); + query.bindValue(0, url); + query.bindValue(1, title); + if (query.exec()) + return true; + else return false; +} + +bool HistoryModel::optimizeHistory() +{ + QSqlQuery query; + return query.exec("VACUUM"); +} + +bool HistoryModel::clearHistory() +{ + QSqlQuery query; + return query.exec("DELETE FROM history"); +} + +void HistoryModel::setSaving(bool state) +{ + m_isSaving = state; +} + +bool HistoryModel::isSaving() +{ + return m_isSaving; +} diff --git a/src/history/historymodel.h b/src/history/historymodel.h new file mode 100644 index 000000000..ccee2780e --- /dev/null +++ b/src/history/historymodel.h @@ -0,0 +1,38 @@ +#ifndef HISTORYMODEL_H +#define HISTORYMODEL_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include "QtSql/QSqlDatabase" +#include "QSqlQuery" +#include "QDateTime" +#include "QFile" + +class QupZilla; +class WebView; +class HistoryModel : public QObject +{ + Q_OBJECT +public: + HistoryModel(QupZilla* mainClass, QObject* parent = 0); + + int addHistoryEntry(WebView* view); + int addHistoryEntry(const QString &url, QString &title); + bool deleteHistoryEntry(int index); + bool deleteHistoryEntry(const QString &url, const QString &title); + + bool clearHistory(); + bool optimizeHistory(); + bool isSaving(); + void setSaving(bool state); + + void loadSettings(); + +private: + bool m_isSaving; + QupZilla* p_QupZilla; +}; + +#endif // HISTORYMODEL_H diff --git a/src/icon.ico b/src/icon.ico new file mode 100644 index 000000000..acd93a8a3 Binary files /dev/null and b/src/icon.ico differ diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 000000000..964edb6d9 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,25 @@ +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include +#include "mainapplication.h" + +int main(int argc, char *argv[]) +{ + Q_INIT_RESOURCE(icons); + Q_INIT_RESOURCE(html); + + QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); +#ifdef Q_WS_X11 + QApplication::setGraphicsSystem("raster"); // Better overall performance on X11 +#endif + + MainApplication app(argc, argv); + if (app.isExited()) + return 1; + return app.exec(); +} diff --git a/src/navigation/locationbar.cpp b/src/navigation/locationbar.cpp new file mode 100644 index 000000000..a02e82e5f --- /dev/null +++ b/src/navigation/locationbar.cpp @@ -0,0 +1,375 @@ +#include "locationbar.h" +#include "qupzilla.h" +#include "webview.h" +#include "rssmanager.h" +#include "mainapplication.h" +#include "locationcompleter.h" +#include "clickablelabel.h" +#include "bookmarkswidget.h" +#include "bookmarksmodel.h" +#include "siteinfowidget.h" + +LocationBar::LocationBar(QupZilla* mainClass, QWidget *parent) + : LineEdit(parent) + ,m_selectAllOnDoubleClick(false) + ,m_addComWithCtrl(false) + ,m_addCountryWithAlt(false) + ,p_QupZilla(mainClass) + ,m_bookmarksModel(0) +{ + + m_siteIcon = new QToolButton(this); + m_siteIcon->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + m_siteIcon->setCursor(Qt::ArrowCursor); + m_siteIcon->setMaximumSize(35, 25); + m_siteIcon->setMinimumSize(35, 25); + m_siteIcon->setToolTip(tr("Show informations about this page")); + m_siteIcon->setStyleSheet("QToolButton{border-image: url(:/icons/locationbar/searchchoose.png); margin-left:2px;}"); + + m_rssIcon = new QToolButton(this); + m_rssIcon->setIcon(QIcon(":/icons/menu/rss.png")); + m_rssIcon->setCursor(Qt::ArrowCursor); + m_rssIcon->setMaximumSize(30, 23); + m_rssIcon->setAutoRaise(true); + m_rssIcon->setVisible(false); + m_rssIcon->setPopupMode(QToolButton::InstantPopup); + m_rssIcon->setToolTip(tr("Add RSS from this page...")); + m_rssIcon->setStyleSheet("margin-bottom:2px"); + m_rssMenu = new QMenu(this); + + m_goButton = new ClickableLabel(this); + m_goButton->setPixmap(QPixmap(":/icons/locationbar/gotoaddress.png")); + m_goButton->setCursor(Qt::PointingHandCursor); + m_goButton->setHidden(true); + m_goButton->setStyleSheet("margin-bottom:2px;"); + + m_bookmarkButton = new ClickableLabel(this); + m_bookmarkButton->setPixmap(QPixmap(":/icons/locationbar/starg.png")); + m_bookmarkButton->setCursor(Qt::PointingHandCursor); + m_bookmarkButton->setStyleSheet("margin-bottom: 2px;"); + m_bookmarkButton->setToolTip(tr("Bookmark this Page")); + + ClickableLabel* down = new ClickableLabel(this); + down->setPixmap(QPixmap(":icons/locationbar/arrow-down.gif")); + down->setCursor(Qt::ArrowCursor); + + addWidget(down, LineEdit::RightSide); + addWidget(m_bookmarkButton, LineEdit::RightSide); + addWidget(m_goButton, LineEdit::RightSide); + addWidget(m_rssIcon, LineEdit::RightSide); + + setPlaceholderText(tr("Enter URL address or search on Google.com")); + + setWidgetSpacing(0); + this->setMinimumHeight(25); + this->setMaximumHeight(25); + loadSettings(); + + m_locationCompleter = new LocationCompleter(); + setCompleter(m_locationCompleter); + + connect(this, SIGNAL(textEdited(QString)), this, SLOT(textEdit())); + connect(this, SIGNAL(textEdited(QString)), m_locationCompleter, SLOT(refreshCompleter(QString))); + connect(m_locationCompleter->popup(), SIGNAL(clicked(QModelIndex)), p_QupZilla, SLOT(urlEnter())); + connect(m_siteIcon, SIGNAL(clicked()), this, SLOT(showSiteInfo())); + connect(down, SIGNAL(clicked(QPoint)), this, SLOT(showPopup())); + connect(m_goButton, SIGNAL(clicked(QPoint)), p_QupZilla, SLOT(urlEnter())); + connect(m_bookmarkButton, SIGNAL(clicked(QPoint)), this, SLOT(bookmarkIconClicked())); + + setLeftMargin(33); + + setStyleSheet("QLineEdit { background: transparent; border-image: url(:/icons/locationbar/lineedit.png); border-width:4; color:black;}"); +} + +void LocationBar::loadSettings() +{ + QSettings settings(p_QupZilla->activeProfil()+"settings.ini", QSettings::IniFormat); + settings.beginGroup("AddressBar"); + m_selectAllOnDoubleClick = settings.value("SelectAllTextOnDoubleClick",true).toBool(); + m_addComWithCtrl = settings.value("AddComDomainWithCtrlKey",false).toBool(); + m_addCountryWithAlt = settings.value("AddCountryDomainWithAltKey",true).toBool(); +} + +void LocationBar::textEdit() +{ + m_locationCompleter->popup()->setUpdatesEnabled(false); + showGoButton(); +} + +void LocationBar::showGoButton() +{ + if (m_goButton->isVisible()) + return; + + m_rssIconVisible = m_rssIcon->isVisible(); + + m_bookmarkButton->hide(); + m_rssIcon->hide(); + m_goButton->show(); +} + +void LocationBar::hideGoButton() +{ + if (!m_goButton->isVisible()) + return; + + m_rssIcon->setVisible(m_rssIconVisible); + m_bookmarkButton->show(); + m_goButton->hide(); +} + +void LocationBar::showPopup() +{ + //TODO: Fix to next version + return; + emit textEdited(""); + m_locationCompleter->popup()->showNormal(); +} + +void LocationBar::showSiteInfo() +{ + SiteInfoWidget* info = new SiteInfoWidget(p_QupZilla); + info->showAt(this); +} + +void LocationBar::bookmarkIconClicked() +{ + QUrl url = p_QupZilla->weView()->url(); + + if (m_bookmarksModel->isBookmarked(url)) { + BookmarksWidget* menu = new BookmarksWidget(m_bookmarksModel->bookmarkId(url), this); + menu->showAt(this); + connect(menu, SIGNAL(bookmarkDeleted()), this, SLOT(checkBookmark())); + } else if (m_bookmarksModel->saveBookmark(p_QupZilla->weView())) { + m_bookmarkButton->setPixmap(QPixmap(":/icons/locationbar/star.png")); + m_bookmarkButton->setToolTip(tr("Edit this bookmark")); + } +} + +void LocationBar::checkBookmark() +{ + if (m_bookmarksModel->isBookmarked(QUrl(text()))) { + m_bookmarkButton->setPixmap(QPixmap(":/icons/locationbar/star.png")); + m_bookmarkButton->setToolTip(tr("Edit this bookmark")); + } else { + m_bookmarkButton->setPixmap(QPixmap(":/icons/locationbar/starg.png")); + m_bookmarkButton->setToolTip(tr("Bookmark this Page")); + } +} + +void LocationBar::checkRss() +{ + WebView* view = p_QupZilla->weView(); + if (!view) + return; + QWebFrame* frame = view->page()->mainFrame(); + QWebElementCollection links = frame->findAllElements("link"); + + bool found = false; + m_rssMenu->clear(); + for (int i = 0; isetData(href); + act->setToolTip(title); + m_rssMenu->addAction(act); + found = true; + } + + m_rssMenu->addSeparator(); + m_rssMenu->addAction(QIcon(":/icons/menu/rss.png"), tr("Read RSS news"), p_QupZilla, SLOT(showRSSManager())); + + m_rssIcon->setVisible(found); + m_rssIcon->setMenu(m_rssMenu); +} + +QIcon LocationBar::icon(const QUrl &url) +{ + QUrl url2 = url.scheme() + "://" + url.host(); + url2.host().remove("www"); + + QIcon icon = QWebSettings::iconForUrl(url); + if (icon.isNull()) + icon = QWebSettings::iconForUrl(url2); + + if (icon.isNull()) + icon = QWebSettings::iconForUrl(url2.host().prepend("www")); + + if (!icon.isNull()) + return icon.pixmap(16, 16); + if (icon.isNull()) { + QPixmap pixmap = QWebSettings::webGraphic(QWebSettings::DefaultFrameIconGraphic); + if (pixmap.isNull()) { + pixmap = QPixmap(":icons/locationbar/unknownpage.png"); + QWebSettings::setWebGraphic(QWebSettings::DefaultFrameIconGraphic, pixmap); + } + return pixmap; + } + return icon; +} + +void LocationBar::showUrl(const QUrl &url, bool empty) +{ + if (url.isEmpty() && empty) + return; + + if (url.toEncoded()!=text()) { + setText(url.toEncoded()); + setCursorPosition(0); + } + if (url.scheme() == "https") + setPrivacy(true); + else setPrivacy(false); + + if (p_QupZilla->weView()->isLoading()) { + p_QupZilla->ipLabel()->hide(); + p_QupZilla->progressBar()->setVisible(true); + p_QupZilla->progressBar()->setValue(p_QupZilla->weView()->getLoading()); + p_QupZilla->buttonStop()->setVisible(true); + p_QupZilla->buttonReload()->setVisible(false); + p_QupZilla->statusBar()->showMessage(tr("Loading...")); + }else{ + p_QupZilla->progressBar()->setVisible(false); + p_QupZilla->buttonStop()->setVisible(false); + p_QupZilla->buttonReload()->setVisible(true); + p_QupZilla->statusBar()->showMessage(tr("Done")); + p_QupZilla->ipLabel()->show(); + } + hideGoButton(); + + if (!m_bookmarksModel) + m_bookmarksModel = MainApplication::getInstance()->bookmarks(); + + checkBookmark(); +} + +void LocationBar::siteIconChanged() +{ + const QPixmap* icon_ = 0; + if (!p_QupZilla->weView()->isLoading()) + icon_ = p_QupZilla->weView()->animationLoading( p_QupZilla->tabWidget()->currentIndex(), false)->pixmap(); + + if (!icon_) { + m_siteIcon->setIcon(QIcon(":icons/locationbar/unknownpage.png")); + } else { + QIcon icon = *icon_; + m_siteIcon->setIcon(icon); + } +} + +void LocationBar::setPrivacy(bool state) +{ + if (state) + m_siteIcon->setStyleSheet("QToolButton{border-image: url(:/icons/locationbar/safeline.png); margin-left:2px;}"); + else + m_siteIcon->setStyleSheet("QToolButton{border-image: url(:/icons/locationbar/searchchoose.png); margin-left:2px;}"); +} + +void LocationBar::focusOutEvent(QFocusEvent *e) +{ + QLineEdit::focusOutEvent(e); + if (!selectedText().isEmpty() && e->reason() != Qt::TabFocusReason) + return; + setCursorPosition(0); + hideGoButton(); +} + +void LocationBar::dropEvent(QDropEvent *event) +{ + if (event->mimeData()->hasUrls()) { + QUrl dropUrl = event->mimeData()->urls().at(0); + if (WebView::isUrlValid(dropUrl)) { + setText(dropUrl.toEncoded()); + p_QupZilla->loadAddress(dropUrl); + QLineEdit::focusOutEvent(new QFocusEvent(QFocusEvent::FocusOut)); + return; + } + } + if (event->mimeData()->hasText()) { + QUrl dropUrl = QUrl(event->mimeData()->text()); + if (WebView::isUrlValid(dropUrl)) { + setText(dropUrl.toEncoded()); + p_QupZilla->loadAddress(dropUrl); + QLineEdit::focusOutEvent(new QFocusEvent(QFocusEvent::FocusOut)); + return; + } + + } + QLineEdit::dropEvent(event); +} + +void LocationBar::mouseDoubleClickEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton && m_selectAllOnDoubleClick) + selectAll(); + else + QLineEdit::mouseDoubleClickEvent(event); +} + +void LocationBar::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Escape) { + showUrl(p_QupZilla->weView()->url()); + event->accept(); + return; + } + + QString localDomain = tr(".co.uk","Append domain name on ALT key = Should be different for every country"); + if (event->key() == Qt::Key_Control && m_addComWithCtrl && !text().endsWith(".com")) //Disabled for a while + setText(text().append(".com")); + if (event->key() == Qt::Key_Alt && m_addCountryWithAlt && !text().endsWith(localDomain) && !text().endsWith("/")) + setText(text().append(localDomain)); + + QLineEdit::keyPressEvent(event); +} + +void LocationBar::addRss() +{ + WebView* view = p_QupZilla->weView(); + if(!view) + return; + if (QAction *action = qobject_cast(sender())) { + QUrl url = action->data().toUrl(); + QString urlString = url.toString(); + if(url.host().isEmpty()) { + if(!urlString.startsWith("/")) + urlString="/"+urlString; + urlString = view->url().host()+urlString; + QUrl temp(urlString); + if(temp.scheme().isEmpty()) + urlString="http://"+urlString; + temp = QUrl(urlString); + if(temp.scheme().isEmpty() || temp.host().isEmpty()) + return; + } + if (!url.isValid()) + return; + + QString title; + if (action->toolTip().isEmpty()) + title = view->url().host(); + else + title = action->toolTip(); + + p_QupZilla->getMainApp()->rssManager()->addRssFeed(urlString, title); + } +} + +LocationBar::~LocationBar() +{ + delete m_bookmarkButton; + delete m_goButton; + delete m_siteIcon; + delete m_rssIcon; + delete m_rssMenu; + delete m_locationCompleter; +} diff --git a/src/navigation/locationbar.h b/src/navigation/locationbar.h new file mode 100644 index 000000000..328794f88 --- /dev/null +++ b/src/navigation/locationbar.h @@ -0,0 +1,75 @@ +#ifndef LOCATIONBAR_H +#define LOCATIONBAR_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lineedit.h" + +class QupZilla; +class LineEdit; +class LocationCompleter; +class ClickableLabel; +class BookmarksModel; + +class LocationBar : public LineEdit +{ + Q_OBJECT; +public: + explicit LocationBar(QupZilla* mainClass, QWidget *parent = 0); + ~LocationBar(); + static QIcon icon(const QUrl &url); + + void loadSettings(); + +public slots: + void checkRss(); + void showUrl(const QUrl &url, bool empty = true); + void siteIconChanged(); + void setPrivacy(bool state); + void addRss(); + void textEdit(); + void showPopup(); + void bookmarkIconClicked(); + void checkBookmark(); + void showSiteInfo(); + +private: + void focusOutEvent(QFocusEvent* e); + void mouseDoubleClickEvent(QMouseEvent *event); + void keyPressEvent(QKeyEvent *event); + void dropEvent(QDropEvent *event); + + void showGoButton(); + void hideGoButton(); + + ClickableLabel* m_bookmarkButton; + ClickableLabel* m_goButton; + QToolButton* m_siteIcon; + QToolButton* m_rssIcon; + QMenu* m_rssMenu; + + bool m_selectAllOnDoubleClick; + bool m_addComWithCtrl; + bool m_addCountryWithAlt; + QupZilla* p_QupZilla; + LocationCompleter* m_locationCompleter; + BookmarksModel* m_bookmarksModel; + + bool m_rssIconVisible; +}; + +#endif // LOCATIONBAR_H diff --git a/src/navigation/locationcompleter.cpp b/src/navigation/locationcompleter.cpp new file mode 100644 index 000000000..450570bb5 --- /dev/null +++ b/src/navigation/locationcompleter.cpp @@ -0,0 +1,140 @@ +#include "locationcompleter.h" +#include "locationbar.h" + +LocationCompleter::LocationCompleter(QObject *parent) : + QCompleter(parent) +{ + setMaxVisibleItems(6); + QStandardItemModel* completeModel = new QStandardItemModel(); + + setModel(completeModel); + QTreeView *treeView = new QTreeView; + + setPopup(treeView); + treeView->setRootIsDecorated(false); + treeView->header()->hide(); + treeView->header()->setStretchLastSection(false); + treeView->header()->setResizeMode(0, QHeaderView::Stretch); + treeView->header()->resizeSection(1,0); + + setCompletionMode(QCompleter::PopupCompletion); + setCaseSensitivity(Qt::CaseInsensitive); + setWrapAround(true); + setCompletionColumn(1); + QTimer::singleShot(0, this, SLOT(loadInitialHistory())); +} + +//QString LocationCompleter::pathFromIndex(const QModelIndex &index) const +//{ +// qDebug() << __FUNCTION__ << "called"; +// return QCompleter::pathFromIndex(index); +//} + +QStringList LocationCompleter::splitPath(const QString &path) const +{ + Q_UNUSED(path); + return QStringList(""); +#if 0 + QStringList returned = QCompleter::splitPath(path); + QStringList returned2; + QSqlQuery query; + query.exec("SELECT url FROM history WHERE title LIKE '%"+path+"%' OR url LIKE '%"+path+"%' ORDER BY count DESC LIMIT 1"); + if (query.next()) { + QString url = query.value(0).toString(); + bool titleSearching = false; + if (!url.contains(path)) + titleSearching = true; + QString prefix = url.mid(0,url.indexOf(path)); + foreach (QString string, returned) { + if (titleSearching) + returned2.append(url); + else + returned2.append(prefix+string); + } + return returned2; + } else { + foreach (QString string, returned) + returned2.append("http://www.google.com/search?client=qupzilla&q=" + string); + return returned2; + } +#endif +} + +void LocationCompleter::loadInitialHistory() +{ + QSqlQuery query; + query.exec("SELECT title, url FROM history LIMIT 5"); + int i = 0; + QStandardItemModel* cModel = (QStandardItemModel*)model(); + + while(query.next()) { + QStandardItem* iconText = new QStandardItem(); + QStandardItem* findUrl = new QStandardItem(); + QString url = query.value(1).toUrl().toEncoded(); + + iconText->setIcon(LocationBar::icon(query.value(1).toUrl()).pixmap(16,16)); + iconText->setText(query.value(0).toString().replace("\n","").append("\n"+url)); + + findUrl->setText(url); + QList items; + items.append(iconText); + items.append(findUrl); + cModel->insertRow(i, items); + i++; + } +} + +void LocationCompleter::refreshCompleter(QString string) +{ + QSqlQuery query; + int limit; + if (string.size() < 3) + limit = 25; + else + limit = 15; + + query.exec("SELECT title, url FROM history WHERE title LIKE '%"+string+"%' OR url LIKE '%"+string+"%' ORDER BY count DESC LIMIT "+QString::number(limit)); + int i = 0; + QStandardItemModel* cModel = (QStandardItemModel*)model(); + QTreeView *treeView = (QTreeView*)popup(); + + cModel->clear(); + while(query.next()) { + QStandardItem* iconText = new QStandardItem(); + QStandardItem* findUrl = new QStandardItem(); + QString url = query.value(1).toUrl().toEncoded(); + + iconText->setIcon(LocationBar::icon(query.value(1).toUrl()).pixmap(16,16)); + iconText->setText(query.value(0).toString().replace("\n","").append("\n"+url)); + + findUrl->setText(url); + QList items; + items.append(iconText); + items.append(findUrl); + cModel->insertRow(i, items); + i++; + } + + if (i == 0) { + QStandardItem* iconText = new QStandardItem(); + QStandardItem* findUrl = new QStandardItem(); + QString url("http://www.google.com/search?client=qupzilla&q="+string); + + iconText->setIcon(QIcon(":/icons/menu/google.png")); + iconText->setText(tr("Search %1 on Google.com\n..........").arg(string)); + findUrl->setText(url); + QList items; + items.append(iconText); + items.append(findUrl); + cModel->insertRow(i, items); + } + + treeView->header()->setResizeMode(0, QHeaderView::Stretch); + treeView->header()->resizeSection(1,0); + + if (i>6) + popup()->setMinimumHeight(190); + else + popup()->setMinimumHeight(0); + popup()->setUpdatesEnabled(true); +} diff --git a/src/navigation/locationcompleter.h b/src/navigation/locationcompleter.h new file mode 100644 index 000000000..aec6035c0 --- /dev/null +++ b/src/navigation/locationcompleter.h @@ -0,0 +1,35 @@ +#ifndef LOCATIONCOMPLETER_H +#define LOCATIONCOMPLETER_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class LocationCompleter : public QCompleter +{ + Q_OBJECT +public: + explicit LocationCompleter(QObject *parent = 0); + + //virtual QString pathFromIndex(const QModelIndex &index) const; + virtual QStringList splitPath(const QString &path) const; + +signals: + +public slots: + void loadInitialHistory(); + void refreshCompleter(QString string); + +}; + +#endif // LOCATIONCOMPLETER_H diff --git a/src/navigation/websearchbar.cpp b/src/navigation/websearchbar.cpp new file mode 100644 index 000000000..1df7b50fa --- /dev/null +++ b/src/navigation/websearchbar.cpp @@ -0,0 +1,115 @@ +#include "websearchbar.h" +#include "qupzilla.h" +#include "webview.h" +#include "clickablelabel.h" + +WebSearchBar::WebSearchBar(QupZilla* mainClass, QWidget *parent) + :LineEdit(parent) + ,p_QupZilla(mainClass) +{ + m_buttonSearch = new ClickableLabel(this); + m_buttonSearch->setPixmap(QPixmap(":/icons/locationbar/search.png")); + m_buttonSearch->setCursor(QCursor(Qt::PointingHandCursor)); + m_buttonSearch->setStyleSheet("QLabel{margin-bottom:2px;}"); + + m_boxSearchType = new QToolButton(this); + m_boxSearchType->setPopupMode(QToolButton::InstantPopup); + m_boxSearchType->setCursor(Qt::ArrowCursor); + m_boxSearchType->setMaximumSize(35, 25); + m_boxSearchType->setMinimumSize(35, 25); + + this->setMinimumHeight(25); + this->setMaximumHeight(25); + m_boxSearchType->setStyleSheet("QToolButton{border-image: url(:/icons/locationbar/searchchoose.png); padding-left:-6px; margin-left:2px;}" + "QToolButton::menu-indicator {background-image: url(:icons/locationbar/arrow-down.gif); background-repeat: no-repeat;}"); + + addWidget(m_buttonSearch, LineEdit::RightSide); + + setupSearchTypes(); + connect(this, SIGNAL(returnPressed()), this, SLOT(search())); + connect(m_buttonSearch, SIGNAL(clicked(QPoint)), this, SLOT(search())); + + setStyleSheet("QLineEdit { background: transparent; border-image: url(:/icons/locationbar/lineedit.png) ;border-width:4;color:black;}"); + + setLeftMargin(33); + setWidgetSpacing(0); +} + +void WebSearchBar::setupSearchTypes() +{ + QMenu* menu = new QMenu(this); + menu->addAction(QIcon(":/icons/menu/google.png"),"Google", this, SLOT(searchChanged()))->setData("Google"); + menu->addAction(QIcon(":/icons/menu/cz_seznam.png"),"Seznam", this, SLOT(searchChanged()))->setData("Seznam"); + menu->addAction(QIcon(":/icons/menu/icon-wikipedia.png"),"Wikipedia (en)", this, SLOT(searchChanged()))->setData("Wikipedia (en)"); + menu->addAction(QIcon(":/icons/menu/icon-wikipedia.png"),"Wikipedia (cs)", this, SLOT(searchChanged()))->setData("Wikipedia (cs)"); + menu->addAction(QIcon(":/icons/menu/csfd.png"),"CSFD", this, SLOT(searchChanged()))->setData("CSFD"); + menu->addAction(QIcon(":/icons/menu/youtube.png"),"Youtube", this, SLOT(searchChanged()))->setData("Youtube"); + + m_boxSearchType->setMenu(menu); + m_boxSearchType->setIcon(QIcon(":/icons/menu/google.png")); + m_boxSearchType->setToolTip("Google"); + + setPlaceholderText("Google"); + +} + +void WebSearchBar::searchChanged() +{ + if (QAction *action = qobject_cast(sender())) { + if (action->data().toString() == "Google") + m_boxSearchType->setIcon(QIcon(":/icons/menu/google.png")); + else if (action->data().toString() == "Seznam") + m_boxSearchType->setIcon(QIcon(":/icons/menu/cz_seznam.png")); + else if (action->data().toString().contains("Wikipedia")) + m_boxSearchType->setIcon(QIcon(":/icons/menu/icon-wikipedia.png")); + else if (action->data().toString() == "CSFD") + m_boxSearchType->setIcon(QIcon(":/icons/menu/csfd.png")); + else if (action->data().toString() == "Youtube") + m_boxSearchType->setIcon(QIcon(":/icons/menu/youtube.png")); + + m_boxSearchType->setToolTip(action->data().toString()); + } +} + +void WebSearchBar::search() +{ + if (text().isEmpty()) + return; + + QUrl searchUrl; + if (m_boxSearchType->toolTip() == "Google") + searchUrl = QUrl("http://www.google.com/search?client=qupzilla&q="+text()); + if (m_boxSearchType->toolTip() == "Seznam") + searchUrl = QUrl("http://search.seznam.cz/?q="+text()); + if (m_boxSearchType->toolTip() == "Wikipedia (cs)") + searchUrl = QUrl("http://cs.wikipedia.org/w/index.php?search="+text()); + if (m_boxSearchType->toolTip() == "Wikipedia (en)") + searchUrl = QUrl("http://en.wikipedia.org/w/index.php?search="+text()); + if (m_boxSearchType->toolTip() == "CSFD") + searchUrl = QUrl("http://www.csfd.cz/hledani-filmu-hercu-reziseru-ve-filmove-databazi/?search="+text()); + if (m_boxSearchType->toolTip() == "Youtube") + searchUrl = QUrl("http://www.youtube.com/results?search_query="+text()); + + p_QupZilla->weView()->load(searchUrl); + p_QupZilla->weView()->setFocus(); +} + +void WebSearchBar::focusOutEvent(QFocusEvent *e) +{ + if (text().isEmpty()) { + QString search = m_boxSearchType->toolTip(); + //clear(); + setPlaceholderText(search); + } + QLineEdit::focusOutEvent(e); +} + +void WebSearchBar::focusInEvent(QFocusEvent *e) +{ + QString search = m_boxSearchType->toolTip(); + + if (text() == search) { + clear(); + } + QLineEdit::focusInEvent(e); +} diff --git a/src/navigation/websearchbar.h b/src/navigation/websearchbar.h new file mode 100644 index 000000000..5a8a15926 --- /dev/null +++ b/src/navigation/websearchbar.h @@ -0,0 +1,38 @@ +#ifndef WEBSEARCHBAR_H +#define WEBSEARCHBAR_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include +#include "lineedit.h" + +class QupZilla; +class LineEdit; +class ClickableLabel; +class WebSearchBar : public LineEdit +{ + Q_OBJECT; +public: + explicit WebSearchBar(QupZilla* mainClass, QWidget *parent = 0); + +private slots: + void searchChanged(); + void search(); + +private: + ClickableLabel* m_buttonSearch; + QToolButton* m_boxSearchType; + + void setupSearchTypes(); + void focusInEvent(QFocusEvent* e); + void focusOutEvent(QFocusEvent* e); + + QupZilla* p_QupZilla; +}; + +#endif // WEBSEARCHBAR_H diff --git a/src/network/networkmanager.cpp b/src/network/networkmanager.cpp new file mode 100644 index 000000000..ef948b7b1 --- /dev/null +++ b/src/network/networkmanager.cpp @@ -0,0 +1,171 @@ +#include "networkmanager.h" +#include "qupzilla.h" +#include "autofillmodel.h" +#include "networkmanagerproxy.h" +#include "mainapplication.h" + +NetworkManager::NetworkManager(QupZilla* mainClass, QObject *parent) : + NetworkManagerProxy(mainClass, parent) + ,p_QupZilla(mainClass) +{ + connect(this, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), this, SLOT(authentication(QNetworkReply*, QAuthenticator* ))); + connect(this, SIGNAL(sslErrors(QNetworkReply*,QList)), this, SLOT(sslError(QNetworkReply*,QList))); + + loadSettings(); +} + +void NetworkManager::loadSettings() +{ + QSettings settings(MainApplication::getInstance()->getActiveProfil()+"settings.ini", QSettings::IniFormat); + settings.beginGroup("Web-Browser-Settings"); + + if (settings.value("AllowLocalCache", true).toBool()) { + m_diskCache = new QNetworkDiskCache(this); + m_diskCache->setCacheDirectory(MainApplication::getInstance()->getActiveProfil()+"/networkcache"); + m_diskCache->setMaximumCacheSize(settings.value("MaximumCacheSize",50).toInt() * 1024*1024); //MegaBytes + setCache(m_diskCache); + } + settings.endGroup(); +} + +void NetworkManager::sslError(QNetworkReply *reply, QList errors) +{ + QString title = tr("SSL Certificate Error!"); + QString text1 = tr("The page you trying to access has following errors in SSL Certificate:"); + + QStringList actions; + + foreach (QSslError error, errors) { + if (m_certExceptions.contains(error.certificate())) + continue; + if (error.error() == QSslError::NoError) //Weird behavior on Windows + continue; + + QSslCertificate cert = error.certificate(); + actions.append(tr("Organization: ") + cert.subjectInfo(QSslCertificate::Organization)); + actions.append(tr("Domain Name: ") + cert.subjectInfo(QSslCertificate::CommonName)); + actions.append(tr("Expiration Date: ") + cert.expiryDate().toString("hh:mm:ss dddd d. MMMM yyyy")); + actions.append(tr("Error: ") + error.errorString()); + } + + QString text2 = tr("Would you like to make exception for this certificate?"); + QString message = QString(QLatin1String("%1

    %2

    • %3

    %4

    ")).arg(title, text1, actions.join(QLatin1String("
  • ")), text2); + + if (!actions.isEmpty()) { + QMessageBox::StandardButton button = QMessageBox::critical(p_QupZilla, tr("SSL Certificate Error"), + message, QMessageBox::Yes | QMessageBox::No); + if (button != QMessageBox::Yes) + return; + } + + foreach (QSslError error, errors) { + if (m_certExceptions.contains(error.certificate())) + continue; + m_certExceptions.append(error.certificate()); + } + + reply->ignoreSslErrors(errors); +} + +void NetworkManager::authentication(QNetworkReply* reply, QAuthenticator* auth) +{ + QDialog* dialog = new QDialog(p_QupZilla); + dialog->setWindowTitle(tr("Authorization required")); + + QFormLayout* formLa = new QFormLayout(dialog); + + QLabel* label = new QLabel(dialog); + QLabel* userLab = new QLabel(dialog); + QLabel* passLab = new QLabel(dialog); + userLab->setText(tr("Username: ")); + passLab->setText(tr("Password: ")); + + QLineEdit* user = new QLineEdit(dialog); + QLineEdit* pass = new QLineEdit(dialog); + QCheckBox* save = new QCheckBox(dialog); + save->setText(tr("Save username and password on this site")); + pass->setEchoMode(QLineEdit::Password); + + QDialogButtonBox* box = new QDialogButtonBox(dialog); + box->addButton(QDialogButtonBox::Ok); + box->addButton(QDialogButtonBox::Cancel); + connect(box, SIGNAL(rejected()), dialog, SLOT(reject())); + connect(box, SIGNAL(accepted()), dialog, SLOT(accept())); + + label->setText(tr("A username and password are being requested by %1. " + "The site says: \"%2\"").arg(reply->url().toEncoded(), auth->realm())); + formLa->addRow(label); + + formLa->addRow(userLab, user); + formLa->addRow(passLab, pass); + formLa->addRow(save); + + formLa->addWidget(box); + AutoFillModel* fill = MainApplication::getInstance()->autoFill(); + if (fill->isStored(reply->url())) { + save->setChecked(true); + user->setText(fill->getUsername(reply->url())); + pass->setText(fill->getPassword(reply->url())); + } + emit wantsFocus(reply->url()); + + //Do not save when private browsing is enabled + if (p_QupZilla->getMainApp()->webSettings()->testAttribute(QWebSettings::PrivateBrowsingEnabled)) + save->setVisible(false); + + if (!dialog->exec() == QDialog::Accepted) + return; + auth->setUser(user->text()); + auth->setPassword(pass->text()); + + if (save->isChecked()) + fill->addEntry(reply->url(), user->text(), pass->text()); +} + +QNetworkReply *NetworkManager::createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData) +{ + if (op == PostOperation && outgoingData) { + QByteArray outgoingDataByteArray = outgoingData->peek(1024 * 1024); + MainApplication::getInstance()->autoFill()->post(request, outgoingDataByteArray); + } + + QNetworkRequest req = request; + req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); + QNetworkReply* reply = QNetworkAccessManager::createRequest(op, req, outgoingData); + //emit requestCreated(op, request, reply); + return reply; +} + +void NetworkManager::saveCertExceptions() +{ + QFile file(MainApplication::getInstance()->getActiveProfil()+"sslexceptions.dat"); + file.open(QIODevice::WriteOnly); + QDataStream stream(&file); + + int count = m_certExceptions.count(); + stream << count; + + for (int i = 0; i < count; i++) { + stream << m_certExceptions.at(i).toPem(); + } + + file.close(); +} + +void NetworkManager::loadCertExceptions() +{ + QFile file(MainApplication::getInstance()->getActiveProfil()+"sslexceptions.dat"); + file.open(QIODevice::ReadOnly); + QDataStream stream(&file); + + int count; + stream >> count; + QByteArray cert; + + for (int i = 0; i < count; i++) { + stream >> cert; + m_certExceptions.append(QSslCertificate::fromData(cert)); + } + + file.close(); +} diff --git a/src/network/networkmanager.h b/src/network/networkmanager.h new file mode 100644 index 000000000..051181ca7 --- /dev/null +++ b/src/network/networkmanager.h @@ -0,0 +1,49 @@ +#ifndef NETWORKMANAGER_H +#define NETWORKMANAGER_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "networkmanagerproxy.h" + +class QupZilla; +class NetworkManager : public NetworkManagerProxy +{ + Q_OBJECT +public: + explicit NetworkManager(QupZilla* mainClass, QObject *parent = 0); + QNetworkReply *createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData); + + void saveCertExceptions(); + void loadCertExceptions(); + void loadSettings(); + +signals: + void finishLoading(bool state); + void wantsFocus(const QUrl &url); + void sslDialogClosed(); + +public slots: + void authentication(QNetworkReply* reply, QAuthenticator* auth); + void sslError(QNetworkReply* reply, QList errors); + +private: + QupZilla* p_QupZilla; + QList m_certExceptions; + QNetworkDiskCache* m_diskCache; + +}; + +#endif // NETWORKMANAGER_H diff --git a/src/network/networkmanagerproxy.cpp b/src/network/networkmanagerproxy.cpp new file mode 100644 index 000000000..f133bdaf3 --- /dev/null +++ b/src/network/networkmanagerproxy.cpp @@ -0,0 +1,46 @@ +#include "networkmanagerproxy.h" +#include "networkmanager.h" +#include "webpage.h" +#include "qupzilla.h" +#include "cookiejar.h" +#include "mainapplication.h" + +NetworkManagerProxy::NetworkManagerProxy(QupZilla* mainClass, QObject *parent) : + QNetworkAccessManager(parent) + ,p_QupZilla(mainClass) + ,m_view(0) + ,m_page(0) +{ + setCookieJar(MainApplication::getInstance()->cookieJar()); +} + +void NetworkManagerProxy::populateNetworkRequest(QNetworkRequest &request) +{ + qDebug() << __FUNCTION__ << "called"; + QVariant variant = qVariantFromValue((void *) m_page); + request.setAttribute((QNetworkRequest::Attribute)(QNetworkRequest::User + 100), variant); +} + +void NetworkManagerProxy::setPrimaryNetworkAccessManager(NetworkManagerProxy *manager) +{ + Q_ASSERT(manager); + m_manager = manager; + + connect(this, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)), + manager, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*))); + connect(this, SIGNAL(finished(QNetworkReply *)), + manager, SIGNAL(finished(QNetworkReply *))); + + connect(this, SIGNAL(sslErrors(QNetworkReply*, const QList&)), + manager, SIGNAL(sslErrors(QNetworkReply*, const QList&))); +} + +QNetworkReply *NetworkManagerProxy::createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData) +{ + if (m_manager && m_page) { + QNetworkRequest pageRequest = request; + m_page->populateNetworkRequest(pageRequest); + return m_manager->createRequest(op, pageRequest, outgoingData); + } + return QNetworkAccessManager::createRequest(op, request, outgoingData); +} diff --git a/src/network/networkmanagerproxy.h b/src/network/networkmanagerproxy.h new file mode 100644 index 000000000..2a6bce0f3 --- /dev/null +++ b/src/network/networkmanagerproxy.h @@ -0,0 +1,37 @@ +#ifndef NETWORKMANAGERPROXY_H +#define NETWORKMANAGERPROXY_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include + +class WebView; +class WebPage; +class QupZilla; + +class NetworkManagerProxy : public QNetworkAccessManager +{ + Q_OBJECT +public: + explicit NetworkManagerProxy(QupZilla* mainClass, QObject *parent = 0); + void setView(WebView* view) { m_view = view; } + void setPage(WebPage* page) { m_page = page; } + + void setPrimaryNetworkAccessManager(NetworkManagerProxy *manager); + QNetworkReply* createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData); + +protected: + virtual void populateNetworkRequest(QNetworkRequest &request); + +private: + QupZilla* p_QupZilla; + WebView* m_view; + WebPage* m_page; + NetworkManagerProxy *m_manager; +}; + +#endif // NETWORKMANAGERPROXY_H diff --git a/src/other/aboutdialog.cpp b/src/other/aboutdialog.cpp new file mode 100644 index 000000000..2137362ad --- /dev/null +++ b/src/other/aboutdialog.cpp @@ -0,0 +1,59 @@ +#include "aboutdialog.h" +#include "ui_aboutdialog.h" +#include "qupzilla.h" +#include "webview.h" +#include "webpage.h" + +AboutDialog::AboutDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::AboutDialog) +{ + ui->setupUi(this); + + connect(ui->buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(close())); + connect(ui->authorsButton, SIGNAL(clicked()), this, SLOT(buttonClicked())); + + showAbout(); +} + +void AboutDialog::buttonClicked() +{ + if (ui->authorsButton->text() == tr("Authors and Contributors")) + showAuthors(); + else if (ui->authorsButton->text() == tr("< About QupZilla")) + showAbout(); +} + +void AboutDialog::showAbout() +{ + ui->authorsButton->setText(tr("Authors and Contributors")); + if (m_aboutHtml.isEmpty()) { + m_aboutHtml.append("
    "); + m_aboutHtml.append(tr("

    Application version %1
    ").arg(QupZilla::VERSION)); + m_aboutHtml.append(tr("WebKit version %1

    ").arg(QupZilla::WEBKITVERSION)); + m_aboutHtml.append(tr("

    © %1 %2
    All rights reserved.
    ").arg(QupZilla::COPYRIGHT, QupZilla::AUTHOR)); + m_aboutHtml.append(tr("Build time: %1

    ").arg(QupZilla::BUILDTIME)); + m_aboutHtml.append(QString("

    %1

    ").arg(QupZilla::WWWADDRESS)); + m_aboutHtml.append("

    "+MainApplication::getInstance()->getWindow()->weView()->getPage()->userAgentForUrl(QUrl())+"

    "); + m_aboutHtml.append("
    "); + } + ui->textBrowser->setHtml(m_aboutHtml); +} + +void AboutDialog::showAuthors() +{ + ui->authorsButton->setText(tr("< About QupZilla")); + if (m_authorsHtml.isEmpty()) { + m_authorsHtml.append("
    "); + m_authorsHtml.append(tr("

    Main developers:
    %1 <%2>

    ").arg(QupZilla::AUTHOR, "nowrep@gmail.com")); + m_authorsHtml.append(tr("

    Other contributors:
    %1

    ").arg("Rajny :: Graphics
    Mikino :: Slovakia Translation")); + m_authorsHtml.append(tr("

    Thanks to:
    %1

    ").arg("Patrick :: First User")); + m_authorsHtml.append("
    "); + } + ui->textBrowser->setHtml(m_authorsHtml); +} + +AboutDialog::~AboutDialog() +{ + delete ui; +} diff --git a/src/other/aboutdialog.h b/src/other/aboutdialog.h new file mode 100644 index 000000000..e175a49e9 --- /dev/null +++ b/src/other/aboutdialog.h @@ -0,0 +1,34 @@ +#ifndef ABOUTDIALOG_H +#define ABOUTDIALOG_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include + +namespace Ui { + class AboutDialog; +} + +class AboutDialog : public QDialog +{ + Q_OBJECT + +public: + explicit AboutDialog(QWidget *parent = 0); + ~AboutDialog(); + +private slots: + void showAbout(); + void showAuthors(); + void buttonClicked(); + +private: + Ui::AboutDialog *ui; + + QString m_aboutHtml; + QString m_authorsHtml; +}; + +#endif // ABOUTDIALOG_H diff --git a/src/other/aboutdialog.ui b/src/other/aboutdialog.ui new file mode 100644 index 000000000..737e55174 --- /dev/null +++ b/src/other/aboutdialog.ui @@ -0,0 +1,132 @@ + + + AboutDialog + + + + 0 + 0 + 271 + 440 + + + + About QupZilla + + + + :/icons/qupzilla.png:/icons/qupzilla.png + + + + 0 + + + + + background:white; + + + + + + :/icons/other/about.png + + + Qt::AlignCenter + + + + + + + border:none; + + + Qt::ScrollBarAlwaysOff + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Ubuntu'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + true + + + true + + + + + + + 5 + + + + + + 0 + 0 + + + + Authors + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + + + + + + buttonBox + accepted() + AboutDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + AboutDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/other/clearprivatedata.cpp b/src/other/clearprivatedata.cpp new file mode 100644 index 000000000..27c3a800d --- /dev/null +++ b/src/other/clearprivatedata.cpp @@ -0,0 +1,74 @@ +#include "clearprivatedata.h" +#include "qupzilla.h" +#include "cookiejar.h" +#include "mainapplication.h" +#include "networkmanager.h" +#include "clickablelabel.h" + +ClearPrivateData::ClearPrivateData(QupZilla* mainClass, QWidget *parent) : + QDialog(parent) + ,p_QupZilla(mainClass) +{ + setWindowTitle(tr("Clear Recent History")); + setWindowIcon(QIcon(":/icons/qupzilla.png")); + m_layout = new QBoxLayout(QBoxLayout::TopToBottom, this); + m_label = new QLabel(this); + m_buttonBox = new QDialogButtonBox(this); + m_buttonBox->addButton(QDialogButtonBox::Ok); + m_buttonBox->addButton(QDialogButtonBox::Cancel); + connect(m_buttonBox, SIGNAL(accepted()), this, SLOT(dialogAccepted())); + connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(close())); + m_layout->addWidget(m_label); + m_label->setText(tr("Choose what you want to delete:")); + m_layout->addWidget(m_buttonBox); + + m_clearHistory = new QCheckBox(tr("Clear history"), this); + m_clearCookies = new QCheckBox(tr("Clear cookies"), this); + m_clearCache = new QCheckBox(tr("Clear cache"), this); + m_clearIcons = new QCheckBox(tr("Clear icons"), this); + m_clearFlashCookies = new ClickableLabel(this); + m_clearFlashCookies->setText(tr("Clear cookies from Adobe Flash Player")); + + m_clearHistory->setChecked(true); + m_clearCookies->setChecked(true); + m_clearCache->setChecked(true); + m_clearIcons->setChecked(true); + m_clearFlashCookies->setStyleSheet("color: blue; text-decoration: underline;"); + m_clearFlashCookies->setCursor(Qt::PointingHandCursor); + + m_layout->addWidget(m_clearHistory); + m_layout->addWidget(m_clearCookies); + m_layout->addWidget(m_clearCache); + m_layout->addWidget(m_clearIcons); + m_layout->addWidget(m_clearFlashCookies); + + m_layout->addWidget(m_buttonBox); + + connect(m_clearFlashCookies, SIGNAL(clicked(QPoint)), this, SLOT(clearFlash())); +} + +void ClearPrivateData::clearFlash() +{ + p_QupZilla->loadAddress(QUrl("http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager07.html")); +} + +void ClearPrivateData::dialogAccepted() +{ + if (m_clearHistory->isChecked()) { + QSqlQuery query; + query.exec("DELETE FROM history"); + query.exec("VACUUM"); + } + if (m_clearCookies->isChecked()) { + QList cookies; + p_QupZilla->getMainApp()->cookieJar()->setAllCookies(cookies); + } + if (m_clearCache->isChecked()) { + p_QupZilla->getMainApp()->webSettings()->clearMemoryCaches(); + p_QupZilla->getMainApp()->networkManager()->cache()->clear(); + } + if (m_clearIcons->isChecked()) { + p_QupZilla->getMainApp()->webSettings()->clearIconDatabase(); + } + close(); +} diff --git a/src/other/clearprivatedata.h b/src/other/clearprivatedata.h new file mode 100644 index 000000000..40ea0c88a --- /dev/null +++ b/src/other/clearprivatedata.h @@ -0,0 +1,45 @@ +#ifndef CLEARPRIVATEDATA_H +#define CLEARPRIVATEDATA_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include +#include + +class ClickableLabel; +class QupZilla; +class ClearPrivateData : public QDialog +{ + Q_OBJECT +public: + explicit ClearPrivateData(QupZilla* mainClass, QWidget *parent = 0); + +signals: + +public slots: + +private slots: + void dialogAccepted(); + void clearFlash(); + +private: + QupZilla* p_QupZilla; + + QBoxLayout* m_layout; + QLabel* m_label; + QDialogButtonBox* m_buttonBox; + + QCheckBox* m_clearHistory; + QCheckBox* m_clearCookies; + QCheckBox* m_clearCache; + QCheckBox* m_clearIcons; + + ClickableLabel* m_clearFlashCookies; +}; + +#endif // CLEARPRIVATEDATA_H diff --git a/src/other/sourceviewer.cpp b/src/other/sourceviewer.cpp new file mode 100644 index 000000000..15cf23242 --- /dev/null +++ b/src/other/sourceviewer.cpp @@ -0,0 +1,25 @@ +#include "sourceviewer.h" +#include "qupzilla.h" +#include "webview.h" +SourceViewer::SourceViewer(QupZilla* mainClass, QWidget *parent) : + QWidget(parent) + ,p_QupZilla(mainClass) +{ + setWindowTitle(tr("Source of ")+p_QupZilla->weView()->url().toString()); + setWindowIcon(QIcon(":/icons/qupzilla.png")); + m_layout = new QBoxLayout(QBoxLayout::TopToBottom, this); + m_sourceEdit = new QTextEdit(this); + + m_layout->addWidget(m_sourceEdit); + m_layout->setContentsMargins(1, 2, 1, 2); + + m_sourceEdit->insertPlainText(p_QupZilla->weView()->page()->mainFrame()->toHtml()); + + this->resize(650, 600); + m_sourceEdit->setReadOnly(true); + m_sourceEdit->moveCursor(QTextCursor::Start); + //CENTER on scren + const QRect screen = QApplication::desktop()->screenGeometry(); + const QRect &size = QWidget::geometry(); + QWidget::move( (screen.width()-size.width())/2, (screen.height()-size.height())/2 ); +} diff --git a/src/other/sourceviewer.h b/src/other/sourceviewer.h new file mode 100644 index 000000000..70bd0936f --- /dev/null +++ b/src/other/sourceviewer.h @@ -0,0 +1,32 @@ +#ifndef SOURCEVIEWER_H +#define SOURCEVIEWER_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include + +class QupZilla; +class SourceViewer : public QWidget +{ + Q_OBJECT +public: + explicit SourceViewer(QupZilla* mainClass, QWidget *parent = 0); + +signals: + +public slots: + +private: + QupZilla* p_QupZilla; + + QBoxLayout* m_layout; + QTextEdit* m_sourceEdit; + +}; + +#endif // SOURCEVIEWER_H diff --git a/src/other/updater.cpp b/src/other/updater.cpp new file mode 100644 index 000000000..e2577d7e5 --- /dev/null +++ b/src/other/updater.cpp @@ -0,0 +1,79 @@ +#include "updater.h" +#include "qupzilla.h" +#include "tabwidget.h" + +Updater::Updater(QupZilla* mainClass, QObject *parent) : + QObject(parent) + ,p_QupZilla(mainClass) +{ + createTrayIcon(); +#ifndef DEVELOPING + QTimer::singleShot(60*1000, this, SLOT(start()) ); //Start checking after 1 minute +#endif +} + +void Updater::start() +{ + startDownloadingUpdateInfo(QUrl(QupZilla::WWWADDRESS+"/update.php?i=actualversion")); +} + +void Updater::createTrayIcon() +{ + m_trayIcon = new QSystemTrayIcon(this); + m_trayIconMenu = new QMenu(); + m_trayIconMenu->addAction(tr("Go to download page"), p_QupZilla, SLOT(loadActionUrl()))->setData(QUrl(QupZilla::WWWADDRESS+"/download.php")); + m_trayIconMenu->addAction(tr("Go to QupZilla website"), p_QupZilla, SLOT(loadActionUrl()))->setData(QUrl(QupZilla::WWWADDRESS)); + m_trayIconMenu->addSeparator(); + m_trayIconMenu->addAction(tr("Hide notification"), m_trayIcon, SLOT(hide())); + + + m_trayIcon->setContextMenu(m_trayIconMenu); + m_trayIcon->setIcon(QIcon(":/icons/qupzillaupdate.png")); + m_trayIcon->setToolTip(tr("QupZilla is checking for updates")); +} +void Updater::startDownloadingUpdateInfo(const QUrl &url) +{ +// trayIcon->show(); // Disabled, it was getting focus, so mainwindow lost focus + QNetworkAccessManager* manager = new QNetworkAccessManager(); + QNetworkReply* reply; + reply=manager->get(QNetworkRequest(QUrl(url))); + + connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(downCompleted(QNetworkReply *))); +} + +void Updater::downCompleted(QNetworkReply* reply) +{ + m_trayIcon->show(); + QString html = QString(reply->readAll()); + if (html.startsWith("Version:")){ + html.remove("Version:"); + if (html != QupZilla::VERSION) { + connect(m_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(clicked(QSystemTrayIcon::ActivationReason))); + connect(m_trayIcon, SIGNAL(messageClicked()), this, SLOT(goUpdate())); + m_trayIcon->setToolTip(tr("QupZilla found a new version!")); + m_trayIcon->showMessage(tr("New version is available"), tr("New version of QupZilla %1 is available!").arg(html)); + } + else + m_trayIcon->hide(); + } + + reply->manager()->deleteLater(); +} + +void Updater::goUpdate() +{ + p_QupZilla->tabWidget()->addView(QUrl(QupZilla::WWWADDRESS+"/download.php"), tr("QupZilla Update")); +} + +void Updater::clicked(QSystemTrayIcon::ActivationReason reason) +{ + if (reason == QSystemTrayIcon::DoubleClick) + p_QupZilla->tabWidget()->addView(QUrl(QupZilla::WWWADDRESS+"/download.php"), tr("QupZilla Update")); +} + +Updater::~Updater() +{ + m_trayIcon->hide(); + delete m_trayIconMenu; + delete m_trayIcon; +} diff --git a/src/other/updater.h b/src/other/updater.h new file mode 100644 index 000000000..d1312a48b --- /dev/null +++ b/src/other/updater.h @@ -0,0 +1,40 @@ +#ifndef UPDATER_H +#define UPDATER_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include + +class QupZilla; +class Updater : public QObject +{ + Q_OBJECT +public: + explicit Updater(QupZilla* mainClass, QObject *parent = 0); + ~Updater(); + +signals: + +public slots: + void downCompleted(QNetworkReply* reply); + void start(); + void goUpdate(); + void clicked(QSystemTrayIcon::ActivationReason reason); + +private: + void createTrayIcon(); + void startDownloadingUpdateInfo(const QUrl &url); + + QSystemTrayIcon* m_trayIcon; + QMenu* m_trayIconMenu; + + QupZilla* p_QupZilla; + +}; + +#endif // UPDATER_H diff --git a/src/plugins/clicktoflash.cpp b/src/plugins/clicktoflash.cpp new file mode 100644 index 000000000..6b0a87450 --- /dev/null +++ b/src/plugins/clicktoflash.cpp @@ -0,0 +1,139 @@ +/* ============================================================ +* +* Copyright (C) 2009 by Benjamin C. Meyer +* Copyright (C) 2010 by Matthieu Gicquel +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* 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, see . +* +* ============================================================ */ + +#include "clicktoflash.h" +#include "clickablelabel.h" +#include "mainapplication.h" +#include "pluginproxy.h" + +ClickToFlash::ClickToFlash(const QUrl &pluginUrl, QWidget *parent) + : QWidget(parent) + , m_url(pluginUrl) +{ + QHBoxLayout *horizontalLayout; + QFrame *frame; + QHBoxLayout *horizontalLayout_2; + QToolButton *toolButton; + + horizontalLayout = new QHBoxLayout(this); + frame = new QFrame(this); + frame->setStyleSheet("QFrame { border: 1px solid #e8e8e8; }"); + frame->setContentsMargins(0,0,0,0); + horizontalLayout_2 = new QHBoxLayout(frame); + toolButton = new QToolButton(frame); + toolButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + toolButton->setStyleSheet("QToolButton { background: url(:/icons/other/flash.png) no-repeat;\n" + "background-position: center; border: none;}\n" + "QToolButton:hover { background: url(:/icons/other/flashstart.png) no-repeat; \n" + "background-position: center; border:none;}"); + toolButton->setCursor(Qt::PointingHandCursor); + horizontalLayout_2->addWidget(toolButton); + horizontalLayout->addWidget(frame); + horizontalLayout->setContentsMargins(0,0,0,0); + horizontalLayout_2->setContentsMargins(0,0,0,0); + + connect(toolButton, SIGNAL(clicked(bool)), this, SLOT(load())); + setMinimumSize(27,27); + + setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(customContextMenuRequested(QPoint))); +} + +void ClickToFlash::customContextMenuRequested(const QPoint &pos) +{ + QMenu menu; + menu.addAction(tr("Flash blocked by ClickToFlash")); + menu.addSeparator(); + menu.addAction(tr("Add %1 to whitelist").arg(m_url.host()), this, SLOT(toWhitelist())); + menu.actions().at(0)->setEnabled(false); + menu.exec(mapToGlobal(pos)); +} + +void ClickToFlash::toWhitelist() +{ + MainApplication::getInstance()->plugins()->c2f_addWhitelist(m_url.host()); + load(); +} + +void ClickToFlash::load() +{ + QWidget *parent = parentWidget(); + QWebView *view = 0; + while (parent) { + if (QWebView *aView = qobject_cast(parent)) { + view = aView; + break; + } + parent = parent->parentWidget(); + } + if (!view) + return; + + const QString selector = "%1[type=\"application/x-shockwave-flash\"]"; + hide(); + + QList frames; + frames.append(view->page()->mainFrame()); + while (!frames.isEmpty()) { + QWebFrame *frame = frames.takeFirst(); + QWebElement docElement = frame->documentElement(); + + QWebElementCollection elements; + elements.append(docElement.findAll(selector.arg("object"))); + elements.append(docElement.findAll(selector.arg("embed"))); + + foreach(QWebElement element, elements) { + if (checkElement(element)) { + QWebElement substitute = element.clone(); + emit signalLoadClickToFlash(true); + element.replace(substitute); + deleteLater(); + return; + } + } + frames += frame->childFrames(); + } +} + + +bool ClickToFlash::checkElement(QWebElement el) +{ + QString checkString; + QString urlString; + checkString = QUrl(el.attribute("src")).toString(QUrl::RemoveQuery); + urlString = m_url.toString(QUrl::RemoveQuery); + + if (urlString.contains(checkString)) + return true; + QWebElementCollection collec = el.findAll("*"); + int i = 0; + while (i < collec.count()) { + QWebElement el = collec.at(i); + checkString = QUrl(el.attribute("src")).toString(QUrl::RemoveQuery); + urlString = m_url.toString(QUrl::RemoveQuery); + if (urlString.contains(checkString)) + return true; + i++; + } + return false; +} diff --git a/src/plugins/clicktoflash.h b/src/plugins/clicktoflash.h new file mode 100644 index 000000000..ce9c74215 --- /dev/null +++ b/src/plugins/clicktoflash.h @@ -0,0 +1,67 @@ +/* ============================================================ +* +* Copyright (C) 2009 by Benjamin C. Meyer +* Copyright (C) 2010 by Matthieu Gicquel +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* 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, see . +* +* ============================================================ */ + +#ifndef CLICKTOFLASH_H +#define CLICKTOFLASH_H + +// Qt Includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class QWebElement; +class ClickToFlash : public QWidget +{ + Q_OBJECT + +public: + explicit ClickToFlash(const QUrl &pluginUrl, QWidget *parent = 0); + +signals: + void signalLoadClickToFlash(bool); + +private slots: + void load(); + void customContextMenuRequested(const QPoint &pos); + void toWhitelist(); + +private: + bool checkElement(QWebElement el); + + /** + used to find the right QWebElement between the ones of the different plugins + */ + const QUrl m_url; +}; + +#endif // CLICKTOFLASH_H + diff --git a/src/plugins/plugininterface.h b/src/plugins/plugininterface.h new file mode 100644 index 000000000..52d6b8edf --- /dev/null +++ b/src/plugins/plugininterface.h @@ -0,0 +1,44 @@ +#ifndef PLUGININTERFACE_H +#define PLUGININTERFACE_H + +#include +#include +#include +#include +#include +#include +#include + +class PluginInterface +{ +public: + //Plugin Necessary Init Functions + //You have to reimplement those functions, otherwise QupZilla crash + virtual ~PluginInterface() { } + virtual QString pluginName() = 0; + virtual QString pluginInfo() = 0; + virtual QString pluginDescription() = 0; + virtual QString pluginVersion() = 0; + virtual QString pluginAuthor() = 0; + virtual void init(QString settingsPath) = 0; + virtual bool testPlugin() = 0; + //End Plugin Necessary Init Functions + + virtual QTranslator* getTranslator(QString locale) { Q_UNUSED(locale) return 0; } + virtual QIcon pluginIcon() { return QIcon(); } + virtual bool hasSettings() { return false; } + virtual void showSettings() { } + + virtual void populateToolsMenu(QMenu* menu) { Q_UNUSED(menu) } + virtual void populateHelpMenu(QMenu* menu) { Q_UNUSED(menu) } + virtual void populateWebViewMenu(QMenu* menu, QWebView* view, QWebHitTestResult r) { Q_UNUSED(menu) Q_UNUSED(view) Q_UNUSED(r) } + + virtual void formSent(const QNetworkRequest &request, const QByteArray &outgoingData) { Q_UNUSED(request) Q_UNUSED(outgoingData)} + virtual void pageLoaded(QWebView* view) { Q_UNUSED(view) } + virtual void downloadRequested(QWidget* requestWidget) { Q_UNUSED(requestWidget) } +}; + + Q_DECLARE_INTERFACE(PluginInterface, "Qupzilla.Browser.PluginInterface/1.0") + + +#endif // PLUGININTERFACE_H diff --git a/src/plugins/pluginproxy.cpp b/src/plugins/pluginproxy.cpp new file mode 100644 index 000000000..bb82b866a --- /dev/null +++ b/src/plugins/pluginproxy.cpp @@ -0,0 +1,70 @@ +#include "pluginproxy.h" +#include "plugininterface.h" +#include "mainapplication.h" + +PluginProxy::PluginProxy() : + Plugins() +{ + c2f_loadSettings(); +} + +void PluginProxy::populateWebViewMenu(QMenu *menu, QWebView *view, QWebHitTestResult r) +{ + if (!menu || !view || loadedPlugins.count() == 0) + return; + + menu->addSeparator(); + int count = menu->actions().count(); + + foreach(PluginInterface* iPlugin, loadedPlugins) + iPlugin->populateWebViewMenu(menu, view, r); + + if (menu->actions().count() == count) + menu->removeAction(menu->actions().at(count)); +} + +void PluginProxy::populateToolsMenu(QMenu *menu) +{ + if (!menu || loadedPlugins.count() == 0) + return; + + int count = menu->actions().count(); + + foreach(PluginInterface* iPlugin, loadedPlugins) + iPlugin->populateToolsMenu(menu); + + if (menu->actions().count() != count) + menu->addSeparator(); +} + +void PluginProxy::populateHelpMenu(QMenu *menu) +{ + if (!menu || loadedPlugins.count() == 0) + return; + + int count = menu->actions().count(); + + foreach(PluginInterface* iPlugin, loadedPlugins) + iPlugin->populateHelpMenu(menu); + + if (menu->actions().count() != count) + menu->addSeparator(); +} + +void PluginProxy::c2f_loadSettings() +{ + QSettings settings(MainApplication::getInstance()->getActiveProfil()+"settings.ini", QSettings::IniFormat); + settings.beginGroup("ClickToFlash"); + c2f_whitelist = settings.value("whitelist", QStringList()).toStringList(); + c2f_enabled = settings.value("Enabled", true).toBool(); + settings.endGroup(); +} + +void PluginProxy::c2f_saveSettings() +{ + QSettings settings(MainApplication::getInstance()->getActiveProfil()+"settings.ini", QSettings::IniFormat); + settings.beginGroup("ClickToFlash"); + settings.setValue("whitelist", c2f_whitelist); + settings.setValue("Enabled", c2f_enabled); + settings.endGroup(); +} diff --git a/src/plugins/pluginproxy.h b/src/plugins/pluginproxy.h new file mode 100644 index 000000000..dacd4015b --- /dev/null +++ b/src/plugins/pluginproxy.h @@ -0,0 +1,34 @@ +#ifndef PLUGINPROXY_H +#define PLUGINPROXY_H +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include + +#include "plugins.h" + +class PluginProxy : public Plugins +{ +public: + PluginProxy(); + void populateWebViewMenu(QMenu* menu, QWebView* view, QWebHitTestResult r); + void populateToolsMenu(QMenu* menu); + void populateHelpMenu(QMenu* menu); + + // CLick2Flash + void c2f_loadSettings(); + void c2f_saveSettings(); + void c2f_addWhitelist(QString page) { c2f_whitelist.append(page); } + void c2f_removeWhitelist(QString page) { c2f_whitelist.removeOne(page); } + void c2f_setEnabled(bool en) { c2f_enabled = en; } + bool c2f_isEnabled() { return c2f_enabled; } + QStringList c2f_getWhiteList() { return c2f_whitelist; } + QStringList c2f_whitelist; + bool c2f_enabled; +}; + +#endif // PLUGINPROXY_H diff --git a/src/plugins/plugins.cpp b/src/plugins/plugins.cpp new file mode 100644 index 000000000..1be2ca8a7 --- /dev/null +++ b/src/plugins/plugins.cpp @@ -0,0 +1,68 @@ +#include "pluginproxy.h" +#include "plugininterface.h" +#include "mainapplication.h" + +Plugins::Plugins(QObject *parent) : + QObject(parent) +{ + loadSettings(); +} + +void Plugins::loadSettings() +{ + m_allowedPluginFileNames.clear(); + + QSettings settings(MainApplication::getInstance()->getActiveProfil()+"settings.ini", QSettings::IniFormat); + settings.beginGroup("Plugin-Settings"); + m_pluginsEnabled = settings.value("EnablePlugins", true).toBool(); + m_allowedPluginFileNames = settings.value("AllowedPlugins", QStringList()).toStringList(); + settings.endGroup(); +} + +void Plugins::loadPlugins() +{ + if (!m_pluginsEnabled) + return; + + m_availablePluginFileNames.clear(); + loadedPlugins.clear(); + + QDir pluginsDir = QDir(MainApplication::getInstance()->DATADIR+"plugins/"); + + foreach (QString fileName, pluginsDir.entryList(QDir::Files)) { + m_availablePluginFileNames.append(fileName); + + if (!m_allowedPluginFileNames.contains(fileName)) + continue; + + QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); + QObject *plugin = loader.instance(); + if (plugin) { + PluginInterface *iPlugin = qobject_cast(plugin); + iPlugin->init(MainApplication::getInstance()->getActiveProfil()+"plugins.ini"); + if (!iPlugin->testPlugin()) { + loader.unload(); + continue; + } + + qApp->installTranslator(iPlugin->getTranslator(MainApplication::getInstance()->getActiveLanguage())); + loadedPlugins.append(iPlugin); + m_loadedPluginFileNames.append(fileName); + } + } + qDebug() << loadedPlugins.count() << "plugins loaded"; +} + +PluginInterface* Plugins::getPlugin(QString pluginFileName) +{ + QString path = MainApplication::getInstance()->DATADIR+"plugins/"+pluginFileName; + if (!QFile::exists(path)) + return 0; + QPluginLoader loader(path); + QObject *plugin = loader.instance(); + if (plugin) { + PluginInterface *iPlugin = qobject_cast(plugin); + return iPlugin; + } else + return 0; +} diff --git a/src/plugins/plugins.h b/src/plugins/plugins.h new file mode 100644 index 000000000..42299afce --- /dev/null +++ b/src/plugins/plugins.h @@ -0,0 +1,41 @@ +#ifndef PLUGINLOADER_H +#define PLUGINLOADER_H +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include +#include +#include +#include + +class PluginInterface; +class Plugins : public QObject +{ + Q_OBJECT +public: + explicit Plugins(QObject *parent = 0); + + QStringList getAvailablePlugins() { return m_availablePluginFileNames; } + QStringList getAllowedPlugins () { return m_allowedPluginFileNames; } + PluginInterface* getPlugin(QString pluginFileName); + //void setPluginsAllowed(bool state) { pluginsEnabled = state; qDebug() << state;} + +public slots: + void loadSettings(); + void loadPlugins(); + +protected: + QList loadedPlugins; + +private: + QStringList m_availablePluginFileNames; + QStringList m_allowedPluginFileNames; + QStringList m_loadedPluginFileNames; + bool m_pluginsEnabled; +}; + +#endif // PLUGINLOADER_H diff --git a/src/plugins/webpluginfactory.cpp b/src/plugins/webpluginfactory.cpp new file mode 100644 index 000000000..81f8e8f7a --- /dev/null +++ b/src/plugins/webpluginfactory.cpp @@ -0,0 +1,53 @@ +#include "webpluginfactory.h" +#include "clicktoflash.h" +#include "mainapplication.h" +#include "pluginproxy.h" + +WebPluginFactory::WebPluginFactory(QObject *parent) + : QWebPluginFactory(parent) + ,m_loadClickToFlash(false) +{ + connect(this, SIGNAL(signalLoadClickToFlash(bool)), SLOT(setLoadClickToFlash(bool))); +} + +QObject* WebPluginFactory::create(const QString &mimeType, const QUrl &url, const QStringList &argumentNames, const QStringList &argumentValues) const +{ + Q_UNUSED(argumentNames) + Q_UNUSED(argumentValues) + + if (mimeType != "application/x-shockwave-flash") { + qDebug() << mimeType; + return 0; + } + + if (!MainApplication::getInstance()->plugins()->c2f_isEnabled()) + return 0; + + //Click2Flash whitelist + QStringList whitelist = MainApplication::getInstance()->plugins()->c2f_getWhiteList(); + if (whitelist.contains(url.host()) || whitelist.contains("www."+url.host()) || whitelist.contains(url.host().remove("www."))) + return 0; + + if (m_loadClickToFlash) { + emit signalLoadClickToFlash(false); + return 0; + } else { + ClickToFlash* ctf = new ClickToFlash(url); + connect(ctf, SIGNAL(signalLoadClickToFlash(bool)), this, SLOT(setLoadClickToFlash(bool))); + return ctf; + } +} + +QList WebPluginFactory::plugins() const +{ + QList plugins; + return plugins; +// QWebPluginFactory::Plugin plugin; +// plugin.name = QLatin1String("ClickToFlashPlugin"); // Mmmm, it should return this, +// QWebPluginFactory::MimeType mimeType; // but with WebKit 533.3, click2flash +// mimeType.fileExtensions << QLatin1String("swf"); // fails on some pages, like youtube.com +// mimeType.name = QLatin1String("application/x-shockwave-flash"); // so we will return empty QList +// plugin.mimeTypes.append(mimeType); // On some pages it also force to load non-flash +// plugins.append(plugin); // content -> in most cases advertisements. +// return plugins; // Not bad to have it hidden :-) +} diff --git a/src/plugins/webpluginfactory.h b/src/plugins/webpluginfactory.h new file mode 100644 index 000000000..6a32d1af9 --- /dev/null +++ b/src/plugins/webpluginfactory.h @@ -0,0 +1,25 @@ +#ifndef WEB_PLUGIN_FACTORY_H +#define WEB_PLUGIN_FACTORY_H + +#include +#include + +class WebPluginFactory : public QWebPluginFactory +{ + Q_OBJECT + +public: + WebPluginFactory(QObject *parent); + virtual QObject*create (const QString &mimeType, const QUrl &url, const QStringList &argumentNames, const QStringList &argumentValues) const; + QList plugins() const; + +signals: + void signalLoadClickToFlash(bool) const; + +public slots: + void setLoadClickToFlash(bool load) { m_loadClickToFlash = load; } + +private: + bool m_loadClickToFlash; +}; +#endif // WEB_PLUGIN_FACTORY_H diff --git a/src/preferences/autofillmanager.cpp b/src/preferences/autofillmanager.cpp new file mode 100644 index 000000000..ecdd1ee11 --- /dev/null +++ b/src/preferences/autofillmanager.cpp @@ -0,0 +1,108 @@ +#include "autofillmanager.h" +#include "ui_autofillmanager.h" + +AutoFillManager::AutoFillManager(QWidget *parent) : + QDialog(parent), + ui(new Ui::AutoFillManager) +{ + ui->setupUi(this); + + connect(ui->removePass, SIGNAL(clicked()), this, SLOT(removePass())); + connect(ui->removeAllPass, SIGNAL(clicked()), this, SLOT(removeAllPass())); + connect(ui->editPass, SIGNAL(clicked()), this, SLOT(editPass())); + + connect(ui->removeExcept, SIGNAL(clicked()), this, SLOT(removeExcept())); + connect(ui->removeAllExcept, SIGNAL(clicked()), this, SLOT(removeAllExcept())); + + QTimer::singleShot(0, this, SLOT(loadPasswords())); +} + +void AutoFillManager::loadPasswords() +{ + QSqlQuery query; + query.exec("SELECT server, password, id FROM autofill"); + ui->treePass->clear(); + while(query.next()) { + QTreeWidgetItem* item = new QTreeWidgetItem(ui->treePass); + item->setText(0, query.value(0).toString()); + item->setText(1, query.value(1).toString()); + item->setWhatsThis(1, query.value(2).toString()); + ui->treePass->addTopLevelItem(item); + } + + query.exec("SELECT server, id FROM autofill_exceptions"); + ui->treeExcept->clear(); + while(query.next()) { + QTreeWidgetItem* item = new QTreeWidgetItem(ui->treeExcept); + item->setText(0, query.value(0).toString()); + item->setWhatsThis(0, query.value(1).toString()); + ui->treeExcept->addTopLevelItem(item); + } +} + +void AutoFillManager::removePass() +{ + QTreeWidgetItem* curItem = ui->treePass->currentItem(); + if (!curItem) + return; + QString id = curItem->whatsThis(1); + QSqlQuery query; + query.exec("DELETE FROM autofill WHERE id="+id); + loadPasswords(); +} + +void AutoFillManager::removeAllPass() +{ + QMessageBox::StandardButton button = QMessageBox::warning(this, tr("Confirmation"), + tr("Are you sure to delete all passwords on your computer?"), QMessageBox::Yes | QMessageBox::No); + if (button != QMessageBox::Yes) + return; + + QSqlQuery query; + query.exec("DELETE FROM autofill"); + loadPasswords(); +} + +void AutoFillManager::editPass() +{ + QTreeWidgetItem* curItem = ui->treePass->currentItem(); + if (!curItem) + return; + bool ok; + QString text = QInputDialog::getText(this, tr("Edit password"), tr("Change password:"), QLineEdit::Normal, curItem->text(1), &ok); + + if (ok && !text.isEmpty()) { + QSqlQuery query; + query.exec("UPDATE autofill SET password='"+text+"' WHERE id="+curItem->whatsThis(1)); + loadPasswords(); + } +} + +void AutoFillManager::removeExcept() +{ + QTreeWidgetItem* curItem = ui->treeExcept->currentItem(); + if (!curItem) + return; + QString id = curItem->whatsThis(0); + QSqlQuery query; + qDebug() << id; + query.exec("DELETE FROM autofill_exceptions WHERE id="+id); + loadPasswords(); +} + +void AutoFillManager::removeAllExcept() +{ + QSqlQuery query; + query.exec("DELETE FROM autofill_exceptions"); + loadPasswords(); +} + +void AutoFillManager::showExceptions() +{ + ui->tabWidget->setCurrentIndex(1); +} + +AutoFillManager::~AutoFillManager() +{ + delete ui; +} diff --git a/src/preferences/autofillmanager.h b/src/preferences/autofillmanager.h new file mode 100644 index 000000000..b4d20034d --- /dev/null +++ b/src/preferences/autofillmanager.h @@ -0,0 +1,45 @@ +#ifndef AUTOFILLMANAGER_H +#define AUTOFILLMANAGER_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Ui { + class AutoFillManager; +} + +class AutoFillManager : public QDialog +{ + Q_OBJECT + +public: + explicit AutoFillManager(QWidget *parent = 0); + ~AutoFillManager(); + + void showExceptions(); + +private slots: + void loadPasswords(); + + void removePass(); + void removeAllPass(); + void editPass(); + + void removeExcept(); + void removeAllExcept(); + +private: + Ui::AutoFillManager *ui; +}; + +#endif // AUTOFILLMANAGER_H diff --git a/src/preferences/autofillmanager.ui b/src/preferences/autofillmanager.ui new file mode 100644 index 000000000..2419251f1 --- /dev/null +++ b/src/preferences/autofillmanager.ui @@ -0,0 +1,146 @@ + + + AutoFillManager + + + + 0 + 0 + 524 + 412 + + + + Password Manager + + + + :/icons/qupzilla.png:/icons/qupzilla.png + + + + + + Qt::NoFocus + + + 0 + + + + Passwords + + + + + + 200 + + + + Server + + + + + Password + + + + + + + + + + Remove + + + + + + + Edit + + + + + + + Remove All + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + Exceptions + + + + + + + Server + + + + + + + + + + Remove + + + + + + + Remove All + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + + + diff --git a/src/preferences/pluginslist.cpp b/src/preferences/pluginslist.cpp new file mode 100644 index 000000000..91ed28f11 --- /dev/null +++ b/src/preferences/pluginslist.cpp @@ -0,0 +1,175 @@ +#include "pluginslist.h" +#include "ui_pluginslist.h" +#include "pluginproxy.h" +#include "mainapplication.h" +#include "plugininterface.h" + +PluginsList::PluginsList(QWidget *parent) : + QWidget(parent), + ui(new Ui::PluginsList) +{ + ui->setupUi(this); + + //Application Extensions + refresh(); + connect(ui->butSettings, SIGNAL(clicked()), this, SLOT(settingsClicked())); + connect(ui->list, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), this, SLOT(currentChanged(QListWidgetItem*))); + connect(ui->butLoad, SIGNAL(clicked()), this, SLOT(reloadPlugins())); + connect(ui->allowAppPlugins, SIGNAL(clicked(bool)), this, SLOT(allowAppPluginsChanged(bool))); + + QSettings settings(MainApplication::getInstance()->getActiveProfil()+"settings.ini", QSettings::IniFormat); + settings.beginGroup("Plugin-Settings"); + ui->allowAppPlugins->setChecked( settings.value("EnablePlugins",true).toBool() ); + settings.endGroup(); + allowAppPluginsChanged(ui->allowAppPlugins->isChecked()); + + //WebKit Plugins + connect(ui->add, SIGNAL(clicked()), this, SLOT(addWhitelist())); + connect(ui->remove, SIGNAL(clicked()), this, SLOT(removeWhitelist())); + connect(ui->allowClick2Flash, SIGNAL(clicked(bool)), this, SLOT(allowC2FChanged(bool))); + + settings.beginGroup("ClickToFlash"); + QStringList whitelist = MainApplication::getInstance()->plugins()->c2f_getWhiteList(); + ui->allowClick2Flash->setChecked( settings.value("Enable",true).toBool() ); + settings.endGroup(); + foreach (QString site, whitelist) { + QTreeWidgetItem* item = new QTreeWidgetItem(ui->whitelist); + item->setText(0, site); + } + allowC2FChanged(ui->allowClick2Flash->isChecked()); +} + +void PluginsList::addWhitelist() +{ + QString site = QInputDialog::getText(this, tr("Add site to whitelist"), tr("Server without http:// (ex. youtube.com)")); + if (site.isEmpty()) + return; + + MainApplication::getInstance()->plugins()->c2f_addWhitelist(site); + ui->whitelist->insertTopLevelItem(0, new QTreeWidgetItem(QStringList(site))); +} + +void PluginsList::removeWhitelist() +{ + QTreeWidgetItem* item = ui->whitelist->currentItem(); + if (!item) + return; + + MainApplication::getInstance()->plugins()->c2f_removeWhitelist(item->text(0)); + delete item; +} + +void PluginsList::save() +{ + QSettings settings(MainApplication::getInstance()->getActiveProfil()+"settings.ini", QSettings::IniFormat); + settings.beginGroup("Plugin-Settings"); + settings.setValue("EnablePlugins",ui->allowAppPlugins->isChecked()); + settings.endGroup(); + + reloadPlugins(); +} + +void PluginsList::allowAppPluginsChanged(bool state) +{ + QSettings settings(MainApplication::getInstance()->getActiveProfil()+"settings.ini", QSettings::IniFormat); + settings.beginGroup("Plugin-Settings"); + settings.setValue("EnablePlugins", state); + settings.endGroup(); + + ui->verticalFrame->setEnabled(state); +} + +void PluginsList::allowC2FChanged(bool state) +{ + QSettings settings(MainApplication::getInstance()->getActiveProfil()+"settings.ini", QSettings::IniFormat); + settings.beginGroup("ClickToFlash"); + settings.setValue("Enable", state); + settings.endGroup(); + + ui->whitelist->setEnabled(state); + ui->add->setEnabled(state); + ui->remove->setEnabled(state); + + MainApplication::getInstance()->plugins()->c2f_setEnabled(state); +} + +void PluginsList::refresh() +{ + ui->list->clear(); + ui->butSettings->setEnabled(false); + + QStringList availablePlugins = MainApplication::getInstance()->plugins()->getAvailablePlugins(); + QStringList allowedPlugins = MainApplication::getInstance()->plugins()->getAllowedPlugins(); + foreach (QString fileName, availablePlugins) { + PluginInterface* plugin = MainApplication::getInstance()->plugins()->getPlugin(fileName); + if (!plugin) + continue; + + QListWidgetItem* item = new QListWidgetItem(ui->list); + item->setText(""+plugin->pluginName()+" ("+plugin->pluginVersion()+") by "+plugin->pluginAuthor()+"\n" + +plugin->pluginInfo()+"\n"+plugin->pluginDescription() ); + + QIcon icon = plugin->pluginIcon(); + if (icon.isNull()) + icon = QIcon(":/icons/preferences/extension.png"); + item->setIcon(icon); + + item->setFlags(item->flags() | Qt::ItemIsUserCheckable); + item->setCheckState( (allowedPlugins.contains(fileName) ) ? Qt::Checked : Qt::Unchecked); + item->setWhatsThis(plugin->hasSettings() ? "1" : "0"); + item->setToolTip(fileName); + + ui->list->addItem(item); + } +} + +void PluginsList::currentChanged(QListWidgetItem *item) +{ + if (!item) + return; + + QString has = item->whatsThis(); + bool show; + if (has == "1") + show = true; + else + show = false; + + if(item->checkState() == Qt::Unchecked) + show = false; + + ui->butSettings->setEnabled(show); +} + +void PluginsList::settingsClicked() +{ + if (!ui->list->currentItem()) + return; + + QString name = ui->list->currentItem()->toolTip(); + PluginInterface* plugin = MainApplication::getInstance()->plugins()->getPlugin(name); + plugin->showSettings(); +} + +void PluginsList::reloadPlugins() +{ + QStringList allowedPlugins; + for (int i = 0; i < ui->list->count(); i++) { + if (ui->list->item(i)->checkState() == Qt::Checked) + allowedPlugins.append(ui->list->item(i)->toolTip()); + } + QSettings settings(MainApplication::getInstance()->getActiveProfil()+"settings.ini", QSettings::IniFormat); + settings.beginGroup("Plugin-Settings"); + settings.setValue("AllowedPlugins",allowedPlugins); + settings.endGroup(); + + MainApplication::getInstance()->plugins()->loadSettings(); + MainApplication::getInstance()->plugins()->loadPlugins(); + + refresh(); +} + +PluginsList::~PluginsList() +{ + delete ui; +} diff --git a/src/preferences/pluginslist.h b/src/preferences/pluginslist.h new file mode 100644 index 000000000..9b64b3139 --- /dev/null +++ b/src/preferences/pluginslist.h @@ -0,0 +1,42 @@ +#ifndef PLUGINSLIST_H +#define PLUGINSLIST_H +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include + +namespace Ui { + class PluginsList; +} + +class PluginsList : public QWidget +{ + Q_OBJECT + +public: + explicit PluginsList(QWidget *parent = 0); + ~PluginsList(); + void save(); + +public slots: + void reloadPlugins(); + +private slots: + //App extension + void settingsClicked(); + void currentChanged(QListWidgetItem* item); + void allowAppPluginsChanged(bool state); + //WebKit plugins + void addWhitelist(); + void removeWhitelist(); + void allowC2FChanged(bool state); + +private: + void refresh(); + Ui::PluginsList *ui; +}; + +#endif // PLUGINSLIST_H diff --git a/src/preferences/pluginslist.ui b/src/preferences/pluginslist.ui new file mode 100644 index 000000000..ca549d51a --- /dev/null +++ b/src/preferences/pluginslist.ui @@ -0,0 +1,185 @@ + + + PluginsList + + + + 0 + 0 + 623 + 462 + + + + Form + + + + + + 0 + + + + Application Extensions + + + + + + Allow Application Extensions to be loaded + + + + + + + + + + true + + + true + + + + + + + + + false + + + + 0 + 0 + + + + Settings + + + + :/icons/preferences/preferences-desktop.png:/icons/preferences/preferences-desktop.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Load Plugins + + + + :/icons/faenza/reload.png:/icons/faenza/reload.png + + + + + + + + + + + + + WebKit Plugins + + + + + + <b>Click To Flash Plugin</b> + + + + + + + Click To Flash is a plugin which blocks auto loading of Flash content at page. You can always load it manually by clicking on the Flash play icon. + + + true + + + + + + + + + + Whitelist + + + + + + + + Add + + + + + + + Remove + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Allow Click To Flash + + + + + + + + + + + + + + diff --git a/src/preferences/preferences.cpp b/src/preferences/preferences.cpp new file mode 100644 index 000000000..553a54281 --- /dev/null +++ b/src/preferences/preferences.cpp @@ -0,0 +1,470 @@ +#include "preferences.h" +#include "ui_preferences.h" +#include "qupzilla.h" +#include "bookmarkstoolbar.h" +#include "historymodel.h" +#include "tabwidget.h" +#include "cookiejar.h" +#include "locationbar.h" +#include "autofillmanager.h" +#include "mainapplication.h" +#include "cookiemanager.h" +#include "pluginslist.h" +#include "qtwin.h" +#include "pluginproxy.h" + +Preferences::Preferences(QupZilla* mainClass, QWidget *parent) : + QDialog(parent) + ,ui(new Ui::Preferences) + ,p_QupZilla(mainClass) + ,m_pluginsList(0) +{ + ui->setupUi(this); + m_bgLabelSize = this->sizeHint(); + + QSettings settings(MainApplication::getInstance()->getActiveProfil()+"settings.ini", QSettings::IniFormat); + //GENERAL URLs + settings.beginGroup("Web-URL-Settings"); + m_homepage = settings.value("homepage","http://qupzilla.ic.cz/search/").toString(); + m_newTabUrl = settings.value("newTabUrl","").toString(); + ui->homepage->setText(m_homepage); + ui->newTabUrl->setText(m_newTabUrl); + int afterLaunch = settings.value("afterLaunch",1).toInt(); + ui->afterLaunch->setCurrentIndex(afterLaunch); + + ui->newTabFrame->setVisible(false); + if (m_newTabUrl.isEmpty()) + ui->newTab->setCurrentIndex(0); + else if (m_newTabUrl == m_homepage) + ui->newTab->setCurrentIndex(1); + else{ + ui->newTab->setCurrentIndex(2); + ui->newTabFrame->setVisible(true); + } + connect(ui->newTab, SIGNAL(currentIndexChanged(int)), this, SLOT(newTabChanged())); + connect(ui->useActualBut, SIGNAL(clicked()), this, SLOT(useActualHomepage())); + connect(ui->newTabUseActual, SIGNAL(clicked()), this, SLOT(useActualNewTab())); + + //PROFILES + ui->startPRofile->setEnabled(false); + ui->createProfile->setEnabled(false); + ui->deleteProfile->setEnabled(false); + settings.endGroup(); + + //WINDOW + settings.beginGroup("Browser-View-Settings"); + ui->showStatusbar->setChecked( settings.value("showStatusBar",true).toBool() ); + ui->showBookmarksToolbar->setChecked( p_QupZilla->bookmarksToolbar()->isVisible() ); + ui->showNavigationToolbar->setChecked( p_QupZilla->navigationToolbar()->isVisible() ); + ui->showHome->setChecked( settings.value("showHomeButton",true).toBool() ); + ui->showBackForward->setChecked( settings.value("showBackForwardButtons",true).toBool() ); + if (settings.value("useTransparentBackground",false).toBool()) + ui->useTransparentBg->setChecked(true); + else + ui->useBgImage->setChecked(true); + + m_menuTextColor = settings.value("menuTextColor", QColor(Qt::black)).value(); + ui->textColor->setStyleSheet("color: "+m_menuTextColor.name()+";"); + useBgImageChanged(ui->useBgImage->isChecked()); + settings.endGroup(); +#ifdef Q_WS_WIN + ui->useTransparentBg->setEnabled(QtWin::isCompositionEnabled()); +#endif + connect(ui->useBgImage, SIGNAL(toggled(bool)), this, SLOT(useBgImageChanged(bool))); + connect(ui->backgroundButton, SIGNAL(clicked()), this, SLOT(chooseBackgroundPath())); + connect(ui->resetDefaultBgButton, SIGNAL(clicked()), this, SLOT(resetBackground())); + connect(ui->textColorChooser, SIGNAL(clicked()), this, SLOT(chooseColor())); + updateBgLabel(); + + //TABS + settings.beginGroup("Browser-Tabs-Settings"); + ui->makeMovable->setChecked( settings.value("makeTabsMovable",true).toBool() ); + ui->hideCloseOnTab->setChecked( settings.value("hideCloseButtonWithOneTab",false).toBool() ); + ui->hideTabsOnTab->setChecked( settings.value("hideTabsWithOneTab",false).toBool() ); + ui->activateLastTab->setChecked( settings.value("ActivateLastTabWhenClosingActual", false).toBool() ); + settings.endGroup(); + //AddressBar + settings.beginGroup("AddressBar"); + ui->selectAllOnFocus->setChecked( settings.value("SelectAllTextOnDoubleClick",true).toBool() ); + ui->addComWithCtrl->setChecked( settings.value("AddComDomainWithCtrlKey",false).toBool() ); + ui->addCountryWithAlt->setChecked( settings.value("AddCountryDomainWithAltKey",true).toBool() ); + settings.endGroup(); + + //BROWSING + settings.beginGroup("Web-Browser-Settings"); + ui->allowPlugins->setChecked( settings.value("allowFlash",true).toBool() ); + ui->allowJavaScript->setChecked( settings.value("allowJavaScript",true).toBool() ); + ui->blockPopup->setChecked( !settings.value("allowJavaScriptOpenWindow", false).toBool() ); + ui->allowJava->setChecked( settings.value("allowJava",true).toBool() ); + ui->loadImages->setChecked( settings.value("autoLoadImages",true).toBool() ); + ui->allowDNSPrefetch->setChecked( settings.value("DNS-Prefetch", false).toBool() ); + ui->jscanAccessClipboard->setChecked( settings.value("JavaScriptCanAccessClipboard", true).toBool() ); + ui->linksInFocusChain->setChecked( settings.value("IncludeLinkInFocusChain", false).toBool() ); + ui->zoomTextOnly->setChecked( settings.value("zoomTextOnly", false).toBool() ); + ui->printEBackground->setChecked( settings.value("PrintElementBackground", true).toBool() ); + ui->wheelScroll->setValue( settings.value("wheelScrollLines", qApp->wheelScrollLines()).toInt() ); + + if (!ui->allowJavaScript->isChecked()) + ui->blockPopup->setEnabled(false); + connect(ui->allowJavaScript, SIGNAL(toggled(bool)), this, SLOT(allowJavaScriptChanged(bool))); + //Cache + ui->pagesInCache->setValue( settings.value("maximumCachedPages",3).toInt() ); + connect(ui->pagesInCache, SIGNAL(valueChanged(int)), this, SLOT(pageCacheValueChanged(int))); + ui->pageCacheLabel->setText(QString::number(ui->pagesInCache->value())); + + ui->allowCache->setChecked( settings.value("AllowLocalCache",true).toBool() ); + ui->cacheMB->setValue( settings.value("LocalCacheSize", 50).toInt() ); + ui->MBlabel->setText( settings.value("LocalCacheSize", 50).toString() + " MB"); + connect(ui->allowCache, SIGNAL(clicked(bool)), this, SLOT(allowCacheChanged(bool))); + connect(ui->cacheMB, SIGNAL(valueChanged(int)), this, SLOT(cacheValueChanged(int)) ); + allowCacheChanged(ui->allowCache->isChecked()); + + //PASSWORD MANAGER + ui->allowPassManager->setChecked(settings.value("AutoFillForms",true).toBool()); + connect(ui->allowPassManager, SIGNAL(toggled(bool)), this, SLOT(showPassManager(bool))); + + m_autoFillManager = new AutoFillManager(this); + ui->autoFillFrame->addWidget(m_autoFillManager); + + //PRIVACY + //Web storage + ui->storeIcons->setChecked( settings.value("allowPersistentStorage",true).toBool() ); + ui->saveHistory->setChecked( p_QupZilla->getMainApp()->history()->isSaving() ); + ui->deleteHistoryOnClose->setChecked( settings.value("deleteHistoryOnClose",false).toBool() ); + if (!ui->saveHistory->isChecked()) + ui->deleteHistoryOnClose->setEnabled(false); + connect(ui->saveHistory, SIGNAL(toggled(bool)), this, SLOT(saveHistoryChanged(bool))); + //Cookies + ui->saveCookies->setChecked( settings.value("allowCookies",true).toBool() ); + if (!ui->saveCookies->isChecked()) + ui->deleteCookiesOnClose->setEnabled(false); + connect(ui->saveCookies, SIGNAL(toggled(bool)), this, SLOT(saveCookiesChanged(bool))); + ui->deleteCookiesOnClose->setChecked( settings.value("deleteCookiesOnClose", false).toBool() ); + ui->matchExactly->setChecked( settings.value("allowCookiesFromVisitedDomainOnly",false).toBool() ); + ui->filterTracking->setChecked( settings.value("filterTrackingCookie",false).toBool() ); + settings.endGroup(); + + //DOWNLOADS + settings.beginGroup("DownloadManager"); + ui->downLoc->setText( settings.value("defaultDownloadPath","").toString() ); + if (ui->downLoc->text().isEmpty()) + ui->askEverytime->setChecked(true); + else + ui->useDefined->setChecked(true); + connect(ui->useDefined, SIGNAL(toggled(bool)), this, SLOT(downLocChanged(bool))); + ui->closeDownDialogOnFinish->setChecked( settings.value("autoCloseOnFinish",false).toBool() ); + connect(ui->downButt, SIGNAL(clicked()), this, SLOT(chooseDownPath())); + downLocChanged(ui->useDefined->isChecked()); + settings.endGroup(); + + //PLUGINS + m_pluginsList = new PluginsList(this); + ui->pluginsFrame->addWidget(m_pluginsList); + + //OTHER + //Languages + QString activeLanguage=""; + if (!p_QupZilla->activeLanguage().isEmpty()) { + activeLanguage = p_QupZilla->activeLanguage(); + QString loc = activeLanguage; + loc.remove(".qm"); + QLocale locale(loc); + QString country = QLocale::countryToString(locale.country()); + QString language = QLocale::languageToString(locale.language()); + ui->languages->addItem(language+", "+country+" ("+loc+")", activeLanguage); + } + ui->languages->addItem("English (en_US)"); + + QDir lanDir(MainApplication::getInstance()->DATADIR+"locale"); + QStringList list = lanDir.entryList(QStringList("*.qm")); + foreach(QString name, list) { + if (name.startsWith("qt_") || name == activeLanguage) + continue; + + QString loc = name; + loc.remove(".qm"); + QLocale locale(loc); + QString country = QLocale::countryToString(locale.country()); + QString language = QLocale::languageToString(locale.language()); + ui->languages->addItem(language+", "+country+" ("+loc+")", name); + } + + connect(ui->buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(buttonClicked(QAbstractButton*))); + connect(ui->cookieManagerBut, SIGNAL(clicked()), this, SLOT(showCookieManager())); + + connect(ui->listWidget, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), this, SLOT(showStackedPage(QListWidgetItem*))); + ui->listWidget->setItemSelected(ui->listWidget->itemAt(5,5), true); + + ui->version->setText(" QupZilla v"+QupZilla::VERSION); +} + +void Preferences::showStackedPage(QListWidgetItem *item) +{ + if (!item) + return; + ui->caption->setText(""+item->text()+""); + ui->stackedWidget->setCurrentIndex(item->whatsThis().toInt()); +} + +void Preferences::chooseColor() +{ + m_menuTextColor = QColorDialog::getColor(Qt::black, this); + ui->textColor->setStyleSheet("color: "+m_menuTextColor.name()+";"); +} + +void Preferences::allowCacheChanged(bool state) +{ + ui->cacheFrame->setEnabled(state); + ui->cacheMB->setEnabled(state); +} + +void Preferences::useActualHomepage() +{ + ui->homepage->setText(p_QupZilla->weView()->url().toString()); +} + +void Preferences::useActualNewTab() +{ + ui->newTabUrl->setText(p_QupZilla->weView()->url().toString()); +} + +void Preferences::resetBackground() +{ + QFile::remove(p_QupZilla->activeProfil()+"background.png"); + QFile(MainApplication::getInstance()->DATADIR+"data/default/profiles/default/background.png").copy(p_QupZilla->activeProfil()+"background.png"); + + m_menuTextColor = QColor(Qt::black); + ui->textColor->setStyleSheet("color: "+m_menuTextColor.name()+";"); + + updateBgLabel(); +} + +void Preferences::updateBgLabel() +{ + ui->bgLabel->setStyleSheet("#bgLabel {background: url("+p_QupZilla->activeProfil()+"background.png) top right;}"); +} + +void Preferences::chooseDownPath() +{ + QString userFileName = QFileDialog::getExistingDirectory(p_QupZilla, tr("Choose download location..."), QDir::homePath()); + if (userFileName.isEmpty()) + return; + ui->downLoc->setText(userFileName); +} + +void Preferences::chooseBackgroundPath() +{ + QString file = QFileDialog::getOpenFileName(p_QupZilla, tr("Choose background location..."), QDir::homePath(), "*.png"); + if (file.isEmpty()) + return; + QFile::remove(p_QupZilla->activeProfil()+"background.png"); + QFile(file).copy(p_QupZilla->activeProfil()+"background.png"); + + updateBgLabel(); +} + +void Preferences::newTabChanged() +{ + if (ui->newTab->currentIndex() == 2) + ui->newTabFrame->setVisible(true); + else + ui->newTabFrame->setVisible(false); +} + +void Preferences::useBgImageChanged(bool state) +{ + ui->bgLabel->setEnabled(state); +} + +void Preferences::downLocChanged(bool state) +{ + ui->downButt->setEnabled(state); + ui->downLoc->setEnabled(state); +} + +void Preferences::allowJavaScriptChanged(bool stat) +{ + ui->blockPopup->setEnabled(stat); +} + +void Preferences::saveHistoryChanged(bool stat) +{ + ui->deleteHistoryOnClose->setEnabled(stat); +} + +void Preferences::saveCookiesChanged(bool stat) +{ + ui->deleteCookiesOnClose->setEnabled(stat); +} + +void Preferences::showCookieManager() +{ + CookieManager* m = new CookieManager(); + m->refreshTable(); + m->setAttribute(Qt::WA_DeleteOnClose); + m->setWindowModality(Qt::WindowModal); + m->show(); +} + +void Preferences::cacheValueChanged(int value) +{ + ui->MBlabel->setText(QString::number(value) + " MB"); + if (value == 0) { + ui->allowCache->setChecked(false); + allowCacheChanged(false); + } + else if (!ui->allowCache->isChecked()) { + ui->allowCache->setChecked(true); + allowCacheChanged(true); + } +} + +void Preferences::pageCacheValueChanged(int value) +{ + ui->pageCacheLabel->setText(QString::number(value)); +} + +void Preferences::showPassManager(bool state) +{ + m_autoFillManager->setVisible(state); +} + +void Preferences::buttonClicked(QAbstractButton *button) +{ + switch (ui->buttonBox->buttonRole(button)) { + case QDialogButtonBox::ApplyRole: + saveSettings(); + break; + + case QDialogButtonBox::RejectRole: + close(); + break; + + case QDialogButtonBox::AcceptRole: + saveSettings(); + close(); + break; + + default: + break; + } +} + +void Preferences::saveSettings() +{ + QSettings settings(MainApplication::getInstance()->getActiveProfil()+"settings.ini", QSettings::IniFormat); + //GENERAL URLs + settings.beginGroup("Web-URL-Settings"); + settings.setValue("homepage",ui->homepage->text()); + + QString homepage = ui->homepage->text(); + settings.setValue("afterLaunch",ui->afterLaunch->currentIndex() ); + + + if (ui->newTab->currentIndex() == 0) + settings.setValue("newTabUrl",""); + else if (ui->newTab->currentIndex() == 1) + settings.setValue("newTabUrl",homepage); + else + settings.setValue("newTabUrl",ui->newTabUrl->text()); + + settings.endGroup(); + //PROFILES + /* + * + * + * + */ + + //WINDOW + settings.beginGroup("Browser-View-Settings"); + + settings.setValue("showStatusbar",ui->showStatusbar->isChecked()); + settings.setValue("showBookmarksToolbar", ui->showBookmarksToolbar->isChecked()); + settings.setValue("showNavigationToolbar", ui->showNavigationToolbar->isChecked()); + settings.setValue("showHomeButton", ui->showHome->isChecked()); + settings.setValue("showBackForwardButtons",ui->showBackForward->isChecked()); + settings.setValue("useTransparentBackground", ui->useTransparentBg->isChecked()); + settings.setValue("menuTextColor", m_menuTextColor); + settings.endGroup(); + + //TABS + settings.beginGroup("Browser-Tabs-Settings"); + settings.setValue("makeTabsMovable",ui->makeMovable->isChecked() ); + settings.setValue("hideCloseButtonWithOneTab",ui->hideCloseOnTab->isChecked()); + settings.setValue("hideTabsWithOneTab",ui->hideTabsOnTab->isChecked() ); + settings.setValue("ActivateLastTabWhenClosingActual", ui->activateLastTab->isChecked()); + settings.endGroup(); + //Downloads + settings.beginGroup("DownloadManager"); + if (ui->askEverytime->isChecked()) + settings.setValue("defaultDownloadPath",""); + else{ + QString text = ui->downLoc->text(); + if (!text.endsWith("/")) + text+="/"; + settings.setValue("defaultDownloadPath",text); + } + settings.setValue("autoCloseOnFinish",ui->closeDownDialogOnFinish->isChecked()); + settings.endGroup(); + + //BROWSING + settings.beginGroup("Web-Browser-Settings"); + settings.setValue("allowFlash",ui->allowPlugins->isChecked()); + settings.setValue("allowJavaScript",ui->allowJavaScript->isChecked()); + settings.setValue("allowJavaScriptOpenWindow", !ui->blockPopup->isChecked()); + settings.setValue("allowJava",ui->allowJava->isChecked()); + settings.setValue("autoLoadImages",ui->loadImages->isChecked()); + settings.setValue("maximumCachedPages",ui->pagesInCache->value()); + settings.setValue("DNS-Prefetch", ui->allowDNSPrefetch->isChecked()); + settings.setValue("JavaScriptCanAccessClipboard", ui->jscanAccessClipboard->isChecked()); + settings.setValue("IncludeLinkInFocusChain", ui->linksInFocusChain->isChecked()); + settings.setValue("zoomTextOnly", ui->zoomTextOnly->isChecked()); + settings.setValue("PrintElementBackground", ui->printEBackground->isChecked()); + settings.setValue("wheelScrollLines", ui->wheelScroll->value()); + //Cache + settings.setValue("AllowLocalCache", ui->allowCache->isChecked()); + settings.setValue("LocalCacheSize", ui->cacheMB->value()); + + //PRIVACY + //Web storage + settings.setValue("allowPersistentStorage", ui->storeIcons->isChecked()); + //ui->saveHistory->setChecked( p_QupZilla->history->isSaving() ); + settings.setValue("deleteHistoryOnClose",ui->deleteHistoryOnClose->isChecked()); + + //Cookies + settings.setValue("allowCookies",ui->saveCookies->isChecked()); + settings.setValue("deleteCookiesOnClose", ui->deleteCookiesOnClose->isChecked()); + settings.setValue("allowCookiesFromVisitedDomainOnly",ui->matchExactly->isChecked() ); + settings.setValue("filterTrackingCookie",ui->filterTracking->isChecked() ); + settings.endGroup(); + + //OTHER + //AddressBar + settings.beginGroup("AddressBar"); + settings.setValue("SelectAllTextOnDoubleClick",ui->selectAllOnFocus->isChecked() ); + settings.setValue("AddComDomainWithCtrlKey",ui->addComWithCtrl->isChecked() ); + settings.setValue("AddCountryDomainWithAltKey", ui->addCountryWithAlt->isChecked() ); + settings.endGroup(); + //Languages + settings.beginGroup("Browser-Window-Settings"); + settings.setValue("language",ui->languages->itemData(ui->languages->currentIndex()).toString()); + settings.endGroup(); + + m_pluginsList->save(); + p_QupZilla->loadSettings(); + p_QupZilla->tabWidget()->loadSettings(); + p_QupZilla->getMainApp()->cookieJar()->loadSettings(); + p_QupZilla->getMainApp()->history()->loadSettings(); + p_QupZilla->locationBar()->loadSettings(); + MainApplication::getInstance()->loadSettings(); + MainApplication::getInstance()->plugins()->c2f_saveSettings(); +} + +Preferences::~Preferences() +{ + qDebug() << __FUNCTION__ << "called"; + delete ui; + delete m_autoFillManager; + delete m_pluginsList; +} diff --git a/src/preferences/preferences.h b/src/preferences/preferences.h new file mode 100644 index 000000000..2823e27ac --- /dev/null +++ b/src/preferences/preferences.h @@ -0,0 +1,69 @@ +#ifndef PREFERENCES_H +#define PREFERENCES_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include +#include + +namespace Ui { + class Preferences; +} + +class AutoFillManager; +class QupZilla; +class PluginsList; + +class Preferences : public QDialog +{ + Q_OBJECT + +public: + explicit Preferences(QupZilla* mainClass, QWidget *parent = 0); + ~Preferences(); + +private slots: + void saveSettings(); + void buttonClicked(QAbstractButton* button); + + void showStackedPage(QListWidgetItem* item); + void newTabChanged(); + void chooseDownPath(); + void showCookieManager(); + void chooseBackgroundPath(); + void useActualHomepage(); + void useActualNewTab(); + void resetBackground(); + void chooseColor(); + + void allowJavaScriptChanged(bool stat); + void saveHistoryChanged(bool stat); + void saveCookiesChanged(bool stat); + void downLocChanged(bool state); + void allowCacheChanged(bool state); + void showPassManager(bool state); + void useBgImageChanged(bool state); + void cacheValueChanged(int value); + void pageCacheValueChanged(int value); + +private: + void updateBgLabel(); + Ui::Preferences *ui; + QupZilla* p_QupZilla; + AutoFillManager* m_autoFillManager; + PluginsList* m_pluginsList; + + QColor m_menuTextColor; + QString m_homepage; + QString m_newTabUrl; + int m_afterLaunch; + int m_onNewTab; + QSize m_bgLabelSize; +}; + +#endif // PREFERENCES_H diff --git a/src/preferences/preferences.ui b/src/preferences/preferences.ui new file mode 100644 index 000000000..17e846c2f --- /dev/null +++ b/src/preferences/preferences.ui @@ -0,0 +1,1523 @@ + + + Preferences + + + + 0 + 0 + 754 + 483 + + + + Preferences + + + + :/icons/qupzilla.png:/icons/qupzilla.png + + + + + + + 200 + 16777215 + + + + false + + + + 32 + 32 + + + + QListView::Static + + + 2 + + + true + + + true + + + false + + + + General + + + 0 + + + + :/icons/preferences/preferences-desktop.png:/icons/preferences/preferences-desktop.png + + + + + Window + + + 1 + + + + :/icons/preferences/gnome-window-manager.png:/icons/preferences/gnome-window-manager.png + + + + + Tabs + + + 2 + + + + :/icons/preferences/applications-internet.png:/icons/preferences/applications-internet.png + + + + + Browsing + + + 3 + + + + :/icons/preferences/applications-webbrowsers.png:/icons/preferences/applications-webbrowsers.png + + + + + Downloads + + + 4 + + + + :/icons/preferences/stock_inbox.png:/icons/preferences/stock_inbox.png + + + + + Password Manager + + + 5 + + + + :/icons/preferences/contact-new.png:/icons/preferences/contact-new.png + + + + + Privacy + + + 6 + + + + :/icons/preferences/history_entry.png:/icons/preferences/history_entry.png + + + + + Plugins + + + 7 + + + + :/icons/preferences/extension.png:/icons/preferences/extension.png + + + + + Other + + + 8 + + + + :/icons/preferences/applications-system.png:/icons/preferences/applications-system.png + + + + + + + + <b>General</b> + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + QupZilla + + + + + + + QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Qt::NoFocus + + + 0 + + + + + + + <b>Launching</b> + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 10 + + + + + + + + After launch: + + + + + + + + Open blank page + + + + + Open homepage + + + + + Restore session + + + + + + + + Homepage: + + + + + + + + + + + + Use actual + + + + + + + + + On new tab: + + + + + + + + Open blank tab + + + + + Open homepage + + + + + Open other page... + + + + + + + + <b>Profiles</b> + + + + + + + Startup profile: + + + + + + + + default + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 20 + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Create New + + + + + + + + 0 + 0 + + + + Delete + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 40 + + + + + + + + + 0 + + + + + + + + Use actual + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + <b>Browser Window</b> + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + Show StatusBar on start + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Show Bookmarks ToolBar on start + + + + + + + Show Navigation ToolBar on start + + + + + + + <b>Navigation ToolBar</b> + + + + + + + Show Home button + + + + + + + Show Back / Forward buttons + + + + + + + <b>Background<b/> + + + + + + + Use transparent background + + + + + + + Use background image + + + + + + + + 0 + 0 + + + + + + + + 9 + + + 0 + + + + + Reset default + + + + + + + Choose image... + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + This is text color used in Menu + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + + + Menu text color + + + + + + + + + + + <b>Tabs behavior</b> + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + Make tabs movable + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Hide close button if there is only one tab + + + + + + + Hide tabs when if there is only one tab + + + + + + + <b>Address Bar behaviour</b> + + + + + + + Select all text by double clicking in address bar + + + + + + + Add .com domain by pressing CTRL key + + + + + + + Add .co.uk domain by pressing ALT key + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Activate last tab when closing active tab + + + + + + + + + + + + + Load images + + + + + + + Allow JAVA + + + + + + + Allow JavaScript + + + + + + + <b>WebKit</b> + + + + + + + Allow Plugins (Flash plugin) + + + + + + + Block PopUp windows + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + Allow DNS Prefetch + + + + + + + JavaScript can access clipboard + + + + + + + Include links in focus chain + + + + + + + Zoom text only + + + + + + + Print element background + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Wheel scrolls + + + + + + + 1 + + + + + + + lines + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + <b>Network Cache</b> + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + Maximum pages in cache: + + + + + + + + 0 + 0 + + + + + 20 + 0 + + + + 1 + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 6 + + + 0 + + + 6 + + + + + 20 + + + Qt::Horizontal + + + + + + + + + + Allow storing network cache on disk + + + + + + + + + + Maximum + + + + + + + 50 MB + + + + + + + + + + 10 + + + 50 + + + Qt::Horizontal + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + <b>Downloads</b> + + + + + + + Automatically close download dialog after finish + + + + + + + Ask everytime for download location + + + + + + + Use defined location: + + + + + + + + + + + + ... + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + + + + <b>AutoFill options</b> + + + + + + + Allow saving passwords from sites + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + QLayout::SetMinAndMaxSize + + + + + + + + + + + + + + <b>Cookies</b> + + + + + + + Filter Tracking Cookies + + + + + + + Allow storing of cookies + + + + + + + Delete cookies on close + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Match domain exactly + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + <b>Warning:</b> Match domain exactly and Filter Tracking Cookies options can lead to deny some cookies from sites. If you have problems with cookies, try to disable this options first! + + + true + + + + + + + + 0 + 0 + + + + Cookies Manager + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + <b>Web storage</b> + + + + + + + Allow storing web icons + + + + + + + Allow saving history + + + + + + + Delete history on close + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + 0 + 0 + + + + + 0 + + + + + + + + + + + + <b>Language</b> + + + + + + + Available translations: + + + + + + + + + + In order to change language, you must restart browser. + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + SqueezeLabel + QLabel +
    squeezelabel.h
    +
    +
    + + + + +
    diff --git a/src/rss/rssmanager.cpp b/src/rss/rssmanager.cpp new file mode 100644 index 000000000..69d87c4cb --- /dev/null +++ b/src/rss/rssmanager.cpp @@ -0,0 +1,305 @@ +#include "rssmanager.h" +#include "ui_rssmanager.h" +#include "qupzilla.h" +#include "locationbar.h" +#include "tabwidget.h" +#include "mainapplication.h" +#include "treewidget.h" + +RSSManager::RSSManager(QupZilla* mainClass, QWidget *parent) : + QWidget(parent) + ,ui(new Ui::RSSManager) + ,p_QupZilla(mainClass) +{ + ui->setupUi(this); +// CENTER on scren + const QRect screen = QApplication::desktop()->screenGeometry(); + const QRect &size = geometry(); + QWidget::move( (screen.width()-size.width())/2, (screen.height()-size.height())/2 ); + + ui->tabWidget->setElideMode(Qt::ElideRight); + m_networkManager = new QNetworkAccessManager(); + connect(ui->buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(close())); + connect(ui->reload, SIGNAL(clicked()), this, SLOT(reloadFeed())); + connect(ui->deletebutton, SIGNAL(clicked()), this, SLOT(deleteFeed())); + connect(ui->edit, SIGNAL(clicked()), this, SLOT(editFeed())); +} + +QupZilla* RSSManager::getQupZilla() +{ + if (!p_QupZilla) + p_QupZilla = MainApplication::getInstance()->getWindow(); + return p_QupZilla; +} + +void RSSManager::setMainWindow(QupZilla *window) +{ + if (window) + p_QupZilla = window; +} + +void RSSManager::refreshTable() +{ + QSqlQuery query; + query.exec("SELECT count(id) FROM rss"); + if (!query.next()) + return; + if (query.value(0).toInt() == 0) + return; + + ui->tabWidget->clear(); + query.exec("SELECT address, title FROM rss"); + int i = 0; + while (query.next()) { + QUrl address = query.value(0).toUrl(); + QString title = query.value(1).toString(); + TreeWidget* tree = new TreeWidget(); + tree->setHeaderLabel(tr("News")); + tree->setContextMenuPolicy(Qt::CustomContextMenu); + connect(tree, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(customContextMenuRequested(const QPoint &))); + + ui->tabWidget->addTab(tree, title); + ui->tabWidget->setTabToolTip(i, address.toString()); + connect(tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(loadFeed(QTreeWidgetItem*))); + connect(tree, SIGNAL(itemControlClicked(QTreeWidgetItem*)), this, SLOT(controlLoadFeed(QTreeWidgetItem*))); + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setText(0, tr("Loading...")); + tree->addTopLevelItem(item); + + QIcon icon = LocationBar::icon(address); + + if (icon.pixmap(16,16).toImage() == QIcon(":/icons/locationbar/unknownpage.png").pixmap(16,16).toImage()) + icon = QIcon(":/icons/menu/rss.png"); + ui->tabWidget->setTabIcon(i, icon ); + beginToLoadSlot(address); + i++; + } + if (i > 0) { + ui->deletebutton->setEnabled(true); + ui->reload->setEnabled(true); + ui->edit->setEnabled(true); + } +} + +void RSSManager::reloadFeed() +{ + TreeWidget* treeWidget = qobject_cast(ui->tabWidget->widget(ui->tabWidget->currentIndex())); + if (!treeWidget) + return; + treeWidget->clear(); + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setText(0, tr("Loading...")); + treeWidget->addTopLevelItem(item); + + beginToLoadSlot( QUrl(ui->tabWidget->tabToolTip(ui->tabWidget->currentIndex())) ); +} + +void RSSManager::deleteFeed() +{ + QString url = ui->tabWidget->tabToolTip(ui->tabWidget->currentIndex()); + if (url.isEmpty()) + return; + QSqlQuery query; + query.exec("DELETE FROM rss WHERE address='"+url+"'"); + + ui->tabWidget->removeTab(ui->tabWidget->currentIndex()); + if (ui->tabWidget->count() == 0) { + ui->deletebutton->setEnabled(false); + ui->reload->setEnabled(false); + ui->edit->setEnabled(false); + refreshTable(); + } +} + +void RSSManager::editFeed() +{ + QString url = ui->tabWidget->tabToolTip(ui->tabWidget->currentIndex()); + if (url.isEmpty()) + return; + + QDialog* dialog = new QDialog(this); + QFormLayout* layout = new QFormLayout(dialog); + QLabel* label = new QLabel(dialog); + QLineEdit* editUrl = new QLineEdit(dialog); + QLineEdit* editTitle = new QLineEdit(dialog); + QDialogButtonBox* box = new QDialogButtonBox(dialog); + box->addButton(QDialogButtonBox::Ok); + box->addButton(QDialogButtonBox::Cancel); + connect(box, SIGNAL(rejected()), dialog, SLOT(reject())); + connect(box, SIGNAL(accepted()), dialog, SLOT(accept())); + + label->setText(tr("Fill title and URL of a feed: ")); + layout->addRow(label); + layout->addRow(new QLabel(tr("Feed title: ")), editTitle); + layout->addRow(new QLabel(tr("Feed URL: ")), editUrl); + layout->addRow(box); + + editUrl->setText( ui->tabWidget->tabToolTip(ui->tabWidget->currentIndex()) ); + editTitle->setText( ui->tabWidget->tabText(ui->tabWidget->currentIndex()) ); + + dialog->setWindowTitle(tr("Edit RSS Feed")); + dialog->setMinimumSize(400, 100); + dialog->exec(); + if (dialog->result() == QDialog::Rejected) + return; + + QString address = editUrl->text(); + QString title = editTitle->text(); + + if (address.isEmpty() || title.isEmpty()) + return; + + QSqlQuery query; + query.prepare("UPDATE rss SET address=?, title=? WHERE address=?"); + query.bindValue(0, address); + query.bindValue(1, title); + query.bindValue(2, url); + query.exec(); + + refreshTable(); + +} + +void RSSManager::customContextMenuRequested(const QPoint &position) +{ + TreeWidget* treeWidget = qobject_cast(ui->tabWidget->widget(ui->tabWidget->currentIndex())); + if (!treeWidget) + return; + + if (!treeWidget->itemAt(position)) + return; + + QString link = treeWidget->itemAt(position)->toolTip(0); + if (link.isEmpty()) + return; + + QMenu menu; + menu.addAction(tr("Open link in actual tab"), getQupZilla(), SLOT(loadActionUrl()))->setData(link); + menu.addAction(tr("Open link in new tab"), this, SLOT(loadFeedInNewTab()))->setData(link); + menu.addSeparator(); + menu.addAction(tr("Close"), this, SLOT(close())); + + //Prevent choosing first option with double rightclick + QPoint pos = QCursor::pos(); + QPoint p(pos.x(), pos.y()+1); + menu.exec(p); +} + +void RSSManager::loadFeed(QTreeWidgetItem *item) +{ + if (!item) + return; + if (item->whatsThis(0).isEmpty()) + return; + getQupZilla()->loadAddress(QUrl(item->whatsThis(0))); +} + +void RSSManager::controlLoadFeed(QTreeWidgetItem *item) +{ + if (!item) + return; + if (item->whatsThis(0).isEmpty()) + return; + getQupZilla()->tabWidget()->addView(QUrl(item->whatsThis(0)), tr("New Tab"), TabWidget::NewNotSelectedTab); +} + +void RSSManager::loadFeedInNewTab() +{ + if (QAction *action = qobject_cast(sender())) + getQupZilla()->tabWidget()->addView(action->data().toUrl(), tr("New Tab"), TabWidget::NewNotSelectedTab); +} + +void RSSManager::beginToLoadSlot(const QUrl &url) +{ + QNetworkReply* reply; + reply=m_networkManager->get(QNetworkRequest(QUrl(url))); + + connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(finished(QNetworkReply *))); +} + +void RSSManager::finished(QNetworkReply *reply) +{ + if (m_networkReplies.contains(reply)) + return; + + QString currentTag; + QString linkString; + QString titleString; + QXmlStreamReader xml; + xml.addData(reply->readAll()); + + int tabIndex = -1; + for (int i=0; itabWidget->count(); i++) { + QString replyUrl = reply->url().toString(); + if (replyUrl == ui->tabWidget->tabToolTip(i)) { + tabIndex = i; + break; + } + } + + if (tabIndex == -1) + return; + + TreeWidget* treeWidget = qobject_cast(ui->tabWidget->widget(tabIndex)); + if (!treeWidget) + return; + treeWidget->clear(); + + while (!xml.atEnd()) { + xml.readNext(); + if (xml.isStartElement()) { + if (xml.name() == "item") + linkString = xml.attributes().value("rss:about").toString(); + currentTag = xml.name().toString(); + } else if (xml.isEndElement()) { + if (xml.name() == "item") { + QTreeWidgetItem *item = new QTreeWidgetItem; + item->setText(0, titleString); + item->setWhatsThis(0, linkString); + item->setIcon(0, QIcon(":/icons/other/feed.png")); + item->setToolTip(0, linkString); + treeWidget->addTopLevelItem(item); + + titleString.clear(); + linkString.clear(); + } + } else if (xml.isCharacters() && !xml.isWhitespace()) { + if (currentTag == "title") + titleString = xml.text().toString(); + else if (currentTag == "link") + linkString += xml.text().toString(); + } + } + + if (treeWidget->topLevelItemCount() == 0) { + QTreeWidgetItem *item = new QTreeWidgetItem; + item->setText(0, tr("Error in fetching feed")); + treeWidget->addTopLevelItem(item); + } + + m_networkReplies.append(reply); +} + +bool RSSManager::addRssFeed(const QString &address, const QString &title) +{ + if (address.isEmpty()) + return false; + QSqlQuery query; + query.exec("SELECT id FROM rss WHERE address='"+address+"'"); + if (!query.next()) { + query.prepare("INSERT INTO rss (address, title) VALUES(?,?)"); + query.bindValue(0, address); + query.bindValue(1, title); + query.exec(); + QMessageBox::information(getQupZilla(), tr("RSS feed added"), tr("RSS with title '%1' has been successfuly added.").arg(title)); + return true; + } else { + QMessageBox::warning(getQupZilla(), tr("RSS feed duplicated"), tr("You already have this feed.")); + } + return false; +} + +RSSManager::~RSSManager() +{ + delete ui; +} diff --git a/src/rss/rssmanager.h b/src/rss/rssmanager.h new file mode 100644 index 000000000..1e9050751 --- /dev/null +++ b/src/rss/rssmanager.h @@ -0,0 +1,53 @@ +#ifndef RSSMANAGER_H +#define RSSMANAGER_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include +#include +#include + +namespace Ui { + class RSSManager; +} + +class QupZilla; +class RSSManager : public QWidget +{ + Q_OBJECT + +public: + explicit RSSManager(QupZilla* mainClass, QWidget *parent = 0); + ~RSSManager(); + + bool addRssFeed(const QString &address, const QString &title); + void setMainWindow(QupZilla* window); + +public slots: + void refreshTable(); + +private slots: + void beginToLoadSlot(const QUrl &url); + void finished(QNetworkReply* reply); + void loadFeed(QTreeWidgetItem* item); + void controlLoadFeed(QTreeWidgetItem* item); + void reloadFeed(); + void deleteFeed(); + void editFeed(); + void customContextMenuRequested(const QPoint &position); + void loadFeedInNewTab(); + +private: + QupZilla* getQupZilla(); + QList m_networkReplies; + QNetworkAccessManager* m_networkManager; + Ui::RSSManager *ui; + QPointer p_QupZilla; +}; + +#endif // RSSMANAGER_H diff --git a/src/rss/rssmanager.ui b/src/rss/rssmanager.ui new file mode 100644 index 000000000..114ce1e53 --- /dev/null +++ b/src/rss/rssmanager.ui @@ -0,0 +1,158 @@ + + + RSSManager + + + + 0 + 0 + 600 + 431 + + + + RSS Reader + + + + :/icons/qupzilla.png:/icons/qupzilla.png + + + + + + Qt::NoFocus + + + QTabBar::tab{ max-width:100px;} + + + false + + + true + + + + Empty + + + + 0 + + + 0 + + + 0 + + + + + background: white; + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + 0 + 0 + + + + + + + :/icons/menu/rss.png + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + You don't have any RSS Feeds.<br/> +Please add some with RSS icon in navigation bar on site which offers feeds. + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + + + + + + + + + + + false + + + Reload + + + + + + + false + + + Edit feed + + + + + + + false + + + Delete feed + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + QDialogButtonBox::Close + + + + + + + + + + + + diff --git a/src/sidebar/sidebar.cpp b/src/sidebar/sidebar.cpp new file mode 100644 index 000000000..4a87a86e0 --- /dev/null +++ b/src/sidebar/sidebar.cpp @@ -0,0 +1,6 @@ +#include "sidebar.h" + +SideBar::SideBar(QWidget *parent) : + QDockWidget(parent) +{ +} diff --git a/src/sidebar/sidebar.h b/src/sidebar/sidebar.h new file mode 100644 index 000000000..61e0a18e2 --- /dev/null +++ b/src/sidebar/sidebar.h @@ -0,0 +1,18 @@ +#ifndef SIDEBAR_H +#define SIDEBAR_H + +#include + +class SideBar : public QDockWidget +{ + Q_OBJECT +public: + explicit SideBar(QWidget *parent = 0); + +signals: + +public slots: + +}; + +#endif // SIDEBAR_H diff --git a/src/webview/searchtoolbar.cpp b/src/webview/searchtoolbar.cpp new file mode 100644 index 000000000..f0d2ef1b8 --- /dev/null +++ b/src/webview/searchtoolbar.cpp @@ -0,0 +1,150 @@ +#include "searchtoolbar.h" +#include "qupzilla.h" +#include "webview.h" +#include "lineedit.h" + +SearchToolBar::SearchToolBar(QupZilla* mainClass, QWidget *parent) : + QToolBar(parent) + ,p_QupZilla(mainClass) + ,m_findFlags(0) +{ + setContextMenuPolicy(Qt::CustomContextMenu); + setObjectName("webSearchToolbar"); + setWindowTitle(tr("Search")); + setMovable(false); + + m_searchLine = new LineEdit(this); + m_searchLine->setInactiveText(tr("Search")); + m_searchLine->setMaximumWidth(250); + connect(m_searchLine, SIGNAL(returnPressed()), this, SLOT(findNext())); + + m_closeButton = new QAction(this); +#ifdef Q_WS_X11 + m_closeButton->setIcon(QIcon(style()->standardIcon(QStyle::SP_DialogCloseButton).pixmap(16,16))); +#else + closeButton->setIcon(QIcon(QIcon(":/icons/faenza/close.png").pixmap(16,16))); +#endif + connect(m_closeButton, SIGNAL(triggered()), this, SLOT(hideBar())); + + m_highlightButton = new QAction(tr("Highlight occurrences"),this); + m_highlightButton->setCheckable(true); + connect(m_highlightButton, SIGNAL(triggered(bool)), this, SLOT(refreshFindFlags(bool))); + + m_nextButton = new QAction(tr("Next"),this); +#ifdef Q_WS_X11 + m_nextButton->setIcon(style()->standardIcon(QStyle::SP_ArrowForward)); +#else + nextButton->setIcon(QIcon(":/icons/faenza/forward.png")); +#endif + + connect(m_nextButton, SIGNAL(triggered()), this, SLOT(findNext())); + + m_previousButton = new QAction(tr("Previous"),this); +#ifdef Q_WS_X11 + m_previousButton->setIcon(style()->standardIcon(QStyle::SP_ArrowBack)); +#else + previousButton->setIcon(QIcon(":/icons/faenza/back.png")); +#endif + connect(m_previousButton, SIGNAL(triggered()), this, SLOT(findPrevious())); + + m_caseSensitiveButton = new QAction(tr("Case sensitive"),this); + m_caseSensitiveButton->setCheckable(true); + connect(m_caseSensitiveButton, SIGNAL(triggered(bool)), this, SLOT(refreshFindFlags(bool))); + + m_searchResults = new QLabel(this); + + addAction(m_closeButton); + addWidget(new QLabel(tr("Find:"))); + addWidget(m_searchLine); + addSeparator(); + addAction(m_previousButton); + addAction(m_nextButton); + addAction(m_highlightButton); + addAction(m_caseSensitiveButton); + addWidget(m_searchResults); + + frameChanged(0); + connect(m_searchLine, SIGNAL(textChanged(QString)), this, SLOT(searchText(QString))); + + m_animation = new QTimeLine(300, this); + connect(m_animation, SIGNAL(frameChanged(int)),this, SLOT(frameChanged(int))); +} + +void SearchToolBar::showBar() +{ + setStyleSheet("QLabel, QToolButton {color: "+p_QupZilla->menuTextColor().name()+";}"); + m_animation->setFrameRange(0, 35); + m_animation->setDirection(QTimeLine::Forward); + disconnect(m_animation, SIGNAL(finished()),this, SLOT(hide())); + + m_animation->stop(); + m_animation->start(); + + m_searchLine->setFocus(); + + QToolBar::show(); +} + +void SearchToolBar::hideBar() +{ + m_animation->setDirection(QTimeLine::Backward); + + m_animation->stop(); + m_animation->start(); + connect(m_animation, SIGNAL(finished()), this, SLOT(hide())); + + m_searchLine->clear(); + p_QupZilla->weView()->setFocus(); +} + +void SearchToolBar::frameChanged(int frame) +{ + setMinimumHeight(frame); + setMaximumHeight(frame); +} + +void SearchToolBar::findNext() +{ + refreshFindFlags(true); + m_findFlags+=4; + searchText(m_searchLine->text()); + +} + +void SearchToolBar::findPrevious() +{ + refreshFindFlags(true); + m_findFlags+=5; + searchText(m_searchLine->text()); +} + +void SearchToolBar::refreshFindFlags(bool b) +{ + Q_UNUSED(b); + m_findFlags = 0; + if (m_highlightButton->isChecked()) { + m_findFlags+=8; + searchText(m_searchLine->text()); + }else{ + m_findFlags+=8; + searchText(""); + m_findFlags-=8; + } + if (m_caseSensitiveButton->isChecked()) { + m_findFlags+=2; + searchText(m_searchLine->text()); + } +} + +void SearchToolBar::searchText(const QString &text) +{ + bool found = p_QupZilla->weView()->findText(text, QFlags(m_findFlags)); + if (!found && !m_searchLine->text().isEmpty()) { + m_searchLine->setStyleSheet("background-color: #ff6666;"); + m_searchResults->setText(tr("No results found.")); + } + else{ + m_searchLine->setStyleSheet(""); + m_searchResults->clear(); + } +} diff --git a/src/webview/searchtoolbar.h b/src/webview/searchtoolbar.h new file mode 100644 index 000000000..38302125d --- /dev/null +++ b/src/webview/searchtoolbar.h @@ -0,0 +1,50 @@ +#ifndef SEARCHTOOLBAR_H +#define SEARCHTOOLBAR_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include +#include +#include +#include + +class QupZilla; +class LineEdit; +class SearchToolBar : public QToolBar +{ + Q_OBJECT +public: + explicit SearchToolBar(QupZilla* mainClass, QWidget *parent = 0); + LineEdit* searchLine(){ return m_searchLine; } + +signals: + +public slots: + void showBar(); + void hideBar(); + void searchText(const QString &text); + void refreshFindFlags(bool b); + void findNext(); + void findPrevious(); + void frameChanged(int frame); + +private: + QupZilla* p_QupZilla; + + LineEdit* m_searchLine; + QAction* m_closeButton; + QAction* m_highlightButton; + QAction* m_caseSensitiveButton; + QAction* m_nextButton; + QAction* m_previousButton; + QLabel* m_searchResults; + QTimeLine* m_animation; + int m_findFlags; +}; + +#endif // SEARCHTOOLBAR_H diff --git a/src/webview/siteinfo.cpp b/src/webview/siteinfo.cpp new file mode 100644 index 000000000..3aa947c3c --- /dev/null +++ b/src/webview/siteinfo.cpp @@ -0,0 +1,66 @@ +#include "siteinfo.h" +#include "ui_siteinfo.h" +#include "qupzilla.h" +#include "webview.h" + +SiteInfo::SiteInfo(QupZilla* mainClass, QWidget *parent) : + QDialog(parent) + ,ui(new Ui::SiteInfo) + ,p_QupZilla(mainClass) +{ + ui->setupUi(this); + WebView* view = p_QupZilla->weView(); + QWebFrame* frame = view->page()->mainFrame(); + QString title = view->title(); + if (title.isEmpty()) + title = tr("No Named Page"); + + ui->siteName->setText(title); + ui->siteAddress->setText(frame->baseUrl().toString()); + + QWebElementCollection meta = frame->findAllElements("meta"); + for (int i = 0; itreeTags); + item->setText(0, name); + item->setText(1, content); + ui->treeTags->addTopLevelItem(item); + } + + QWebElementCollection img = frame->findAllElements("img"); + for (int i = 0; itreeImages); + item->setText(0, alt); + item->setText(1, src); + ui->treeImages->addTopLevelItem(item); + } + +} + +SiteInfo::~SiteInfo() +{ + delete ui; +} diff --git a/src/webview/siteinfo.h b/src/webview/siteinfo.h new file mode 100644 index 000000000..3fdf6c6b8 --- /dev/null +++ b/src/webview/siteinfo.h @@ -0,0 +1,28 @@ +#ifndef SITEINFO_H +#define SITEINFO_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include + +namespace Ui { + class SiteInfo; +} + +class QupZilla; +class SiteInfo : public QDialog +{ + Q_OBJECT + +public: + explicit SiteInfo(QupZilla* mainClass, QWidget *parent = 0); + ~SiteInfo(); + +private: + Ui::SiteInfo *ui; + QupZilla* p_QupZilla; +}; + +#endif // SITEINFO_H diff --git a/src/webview/siteinfo.ui b/src/webview/siteinfo.ui new file mode 100644 index 000000000..a69247ce9 --- /dev/null +++ b/src/webview/siteinfo.ui @@ -0,0 +1,159 @@ + + + SiteInfo + + + + 0 + 0 + 727 + 571 + + + + Site Info + + + + :/icons/qupzilla.png:/icons/qupzilla.png + + + + + + 200 + + + + Tag + + + + + Value + + + + + + + + 200 + + + + Image + + + + + Image address + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + + Site address: + + + + + + + + 0 + 0 + + + + Site name: + + + + + + + + + + + + + + + + + + + + + Meta tags of site: + + + + + + + Images on site: + + + + + + + + SqueezeLabel + QLabel +
    squeezelabel.h
    +
    +
    + + + + + + buttonBox + accepted() + SiteInfo + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + SiteInfo + reject() + + + 316 + 260 + + + 286 + 274 + + + + +
    diff --git a/src/webview/siteinfowidget.cpp b/src/webview/siteinfowidget.cpp new file mode 100644 index 000000000..b9f820b7a --- /dev/null +++ b/src/webview/siteinfowidget.cpp @@ -0,0 +1,67 @@ +#include "siteinfowidget.h" +#include "ui_siteinfowidget.h" +#include "qupzilla.h" + +SiteInfoWidget::SiteInfoWidget(QupZilla* mainClass, QWidget *parent) : + QMenu(parent) + ,ui(new Ui::SiteInfoWidget) + ,p_QupZilla(mainClass) +{ + QUrl url = p_QupZilla->weView()->url(); + if (url.isEmpty()) + return; + + this->setAttribute(Qt::WA_DeleteOnClose); + ui->setupUi(this); + + QString scheme = url.scheme(); + if (scheme == "https") { + ui->secureLabel->setText(tr("Your connection to this site is secured.")); + ui->secureIcon->setPixmap(QPixmap(":/icons/locationbar/accept.png")); + } + else { + ui->secureLabel->setText(tr("Your connection to this site is unsecured.")); + ui->secureIcon->setPixmap(QPixmap(":/icons/locationbar/warning.png")); + } + + QSqlQuery query; + QString host = url.host(); + QString host2 = host; + if (host.startsWith("www.")) + host2 = url.host().remove("www."); + + query.exec("SELECT sum(count) FROM history WHERE url LIKE '"+scheme+"://"+host+"%' "); + if (query.next()) { + int count = query.value(0).toInt(); + if (count > 3) { + ui->historyLabel->setText(tr("This is Your %1. visit of this site.").arg(count)); + ui->historyIcon->setPixmap(QPixmap(":/icons/locationbar/accept.png")); + } else if (count == 0) { + ui->historyLabel->setText(tr("You have never visited this site before.")); + ui->historyIcon->setPixmap(QPixmap(":/icons/locationbar/warning.png")); + } else { + ui->historyIcon->setPixmap(QPixmap(":/icons/locationbar/warning.png")); + QString text; + if (count == 1) + text = tr("first"); + else if (count == 2) + text = tr("second"); + else if (count == 3) + text = tr("third"); + ui->historyLabel->setText(tr("This is Your %1 visit of this site.").arg(text)); + } + } + connect(ui->pushButton, SIGNAL(clicked()), p_QupZilla, SLOT(showPageInfo())); +} + +void SiteInfoWidget::showAt(QWidget* _parent) +{ + QPoint p = _parent->mapToGlobal(QPoint(0, 0)); + move(p.x(), p.y() + _parent->height()); + show(); +} + +SiteInfoWidget::~SiteInfoWidget() +{ + delete ui; +} diff --git a/src/webview/siteinfowidget.h b/src/webview/siteinfowidget.h new file mode 100644 index 000000000..b3062f27c --- /dev/null +++ b/src/webview/siteinfowidget.h @@ -0,0 +1,27 @@ +#ifndef SITEINFOWIDGET_H +#define SITEINFOWIDGET_H + +#include +#include + +namespace Ui { + class SiteInfoWidget; +} + +class QupZilla; +class SiteInfoWidget : public QMenu +{ + Q_OBJECT + +public: + explicit SiteInfoWidget(QupZilla* mainClass, QWidget *parent = 0); + ~SiteInfoWidget(); + + void showAt(QWidget* _parent); + +private: + Ui::SiteInfoWidget *ui; + QupZilla* p_QupZilla; +}; + +#endif // SITEINFOWIDGET_H diff --git a/src/webview/siteinfowidget.ui b/src/webview/siteinfowidget.ui new file mode 100644 index 000000000..e392ffa0d --- /dev/null +++ b/src/webview/siteinfowidget.ui @@ -0,0 +1,108 @@ + + + SiteInfoWidget + + + + 0 + 0 + 213 + 140 + + + + Form + + + + 0 + + + + + QFrame::NoFrame + + + + 15 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 6 + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 10 + 10 + + + + + + + + + 0 + 0 + + + + More... + + + + + + + + + + + + + Frame + QFrame +
    frame.h
    + 1 +
    +
    + + +
    diff --git a/src/webview/tabbar.cpp b/src/webview/tabbar.cpp new file mode 100644 index 000000000..23491716a --- /dev/null +++ b/src/webview/tabbar.cpp @@ -0,0 +1,122 @@ +#include "tabbar.h" +#include "tabwidget.h" +#include "qupzilla.h" + +TabBar::TabBar(QupZilla* mainClass, QWidget *parent) : + QTabBar(parent) + ,p_QupZilla(mainClass) + ,m_clickedTab(0) +{ + setContextMenuPolicy(Qt::CustomContextMenu); + setObjectName("tabBar"); + setTabsClosable(true); + setElideMode(Qt::ElideRight); + setDocumentMode(true); + loadSettings(); + + connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(contextMenuRequested(const QPoint &))); + +} + +void TabBar::loadSettings() +{ + QSettings settings(MainApplication::getInstance()->getActiveProfil()+"settings.ini", QSettings::IniFormat); + settings.beginGroup("Browser-Tabs-Settings"); + + setMovable( settings.value("makeTabsMovable",true).toBool() ); + if (settings.value("ActivateLastTabWhenClosingActual", false).toBool()) + setSelectionBehaviorOnRemove(QTabBar::SelectPreviousTab); + + settings.endGroup(); +} + +void TabBar::contextMenuRequested(const QPoint &position) +{ + TabWidget *tabWidget = qobject_cast(parentWidget()); + if (!tabWidget) + return; + int index = tabAt(position); + m_clickedTab = index; + + QMenu menu; + menu.addAction(QIcon(":/icons/menu/popup.png"),tr("New tab"), p_QupZilla, SLOT(addTab())); + menu.addSeparator(); + + if (index!=-1) { + menu.addAction( +#ifdef Q_WS_X11 + style()->standardIcon(QStyle::SP_ArrowBack) +#else + QIcon(":/icons/faenza/back.png") +#endif + ,tr("Back"), this, SLOT(backTab())); + menu.addAction( +#ifdef Q_WS_X11 + style()->standardIcon(QStyle::SP_ArrowForward) +#else + QIcon(":/icons/faenza/forward.png") +#endif + ,tr("Forward"), this, SLOT(forwardTab())); + menu.addAction( +#ifdef Q_WS_X11 + style()->standardIcon(QStyle::SP_BrowserStop) +#else + QIcon(":/icons/faenza/stop.png") +#endif + ,tr("Stop Tab"), this, SLOT(stopTab())); + menu.addAction( +#ifdef Q_WS_X11 + style()->standardIcon(QStyle::SP_BrowserReload) +#else + QIcon(":/icons/faenza/reload.png") +#endif + ,tr("Reload Tab"), this, SLOT(reloadTab())); + menu.addAction(tr("Reload All Tabs"), tabWidget, SLOT(reloadAllTabs())); + menu.addAction(tr("Bookmark This Tab"), this, SLOT(bookmarkTab())); + menu.addAction(tr("Bookmark All Tabs"), p_QupZilla, SLOT(bookmarkAllTabs())); + menu.addSeparator(); + QAction* action = menu.addAction(QIcon::fromTheme("user-trash"),tr("Restore Closed Tab"), tabWidget, SLOT(restoreClosedTab())); + tabWidget->canRestoreTab() ? action->setEnabled(true) : action->setEnabled(false); + menu.addSeparator(); + menu.addAction(tr("Close Other Tabs"), this, SLOT(closeAllButCurrent())); + menu.addAction(QIcon::fromTheme("window-close"),tr("Close"), this, SLOT(closeTab())); + menu.addSeparator(); + + if (!p_QupZilla->weView(m_clickedTab)->history()->canGoBack()) + menu.actions().at(2)->setEnabled(false); + + if (!p_QupZilla->weView(m_clickedTab)->history()->canGoForward()) + menu.actions().at(3)->setEnabled(false); + + if (!p_QupZilla->weView(m_clickedTab)->isLoading()) + menu.actions().at(4)->setEnabled(false); + }else{ + menu.addAction(tr("Reload All Tabs"), tabWidget, SLOT(reloadAllTabs())); + menu.addAction(tr("Bookmark All Tabs"), p_QupZilla, SLOT(bookmarkAllTabs())); + menu.addSeparator(); + QAction* action = menu.addAction(QIcon::fromTheme("user-trash"),tr("Restore Closed Tab"), tabWidget, SLOT(restoreClosedTab())); + tabWidget->canRestoreTab() ? action->setEnabled(true) : action->setEnabled(false); + } + + //Prevent choosing first option with double rightclick + QPoint pos = QCursor::pos(); + QPoint p(pos.x(), pos.y()+1); + menu.exec(p); +} + +void TabBar::bookmarkTab() +{ + p_QupZilla->addBookmark(p_QupZilla->weView(m_clickedTab)->url(), p_QupZilla->weView(m_clickedTab)->title()); +} + +void TabBar::mouseDoubleClickEvent(QMouseEvent *event) +{ + TabWidget *tabWidget = qobject_cast(parentWidget()); + if (!tabWidget) + return; + if (event->button() == Qt::LeftButton && tabAt(event->pos()) == -1) { + tabWidget->addView(QUrl(),tr("New tab"), TabWidget::NewTab, true); + return; + } + QTabBar::mouseDoubleClickEvent(event); +} diff --git a/src/webview/tabbar.h b/src/webview/tabbar.h new file mode 100644 index 000000000..718d2ee8a --- /dev/null +++ b/src/webview/tabbar.h @@ -0,0 +1,55 @@ +#ifndef TABBAR_H +#define TABBAR_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include +#include +#include +#include + +class QupZilla; +class TabBar : public QTabBar +{ + Q_OBJECT +public: + explicit TabBar(QupZilla* mainClass, QWidget *parent = 0); + +signals: + void reloadTab(int index); + void stopTab(int index); + void backTab(int index); + void forwardTab(int index); + void closeAllButCurrent(int index); + void closeTab(int index); + +public slots: + +public: + void loadSettings(); + +private slots: + void contextMenuRequested(const QPoint &position); + void reloadTab() { emit reloadTab(m_clickedTab); } + void stopTab() { emit stopTab(m_clickedTab); } + void backTab() { emit backTab(m_clickedTab); } + void forwardTab() { emit forwardTab(m_clickedTab); } + void closeAllButCurrent() { emit closeAllButCurrent(m_clickedTab); } + void closeTab() { emit closeTab(m_clickedTab); } + void bookmarkTab(); +private: + void mouseDoubleClickEvent(QMouseEvent *event); + + QupZilla* p_QupZilla; + bool m_showCloseButtonWithOneTab; + bool m_showTabBarWithOneTab; + int m_clickedTab; + +}; + +#endif // TABBAR_H diff --git a/src/webview/tabwidget.cpp b/src/webview/tabwidget.cpp new file mode 100644 index 000000000..a9b36777f --- /dev/null +++ b/src/webview/tabwidget.cpp @@ -0,0 +1,328 @@ +#include "webview.h" +#include "webpage.h" +#include "qupzilla.h" +#include "tabwidget.h" +#include "tabbar.h" +#include "locationbar.h" +#include "mainapplication.h" +#include "webtab.h" + +TabWidget::TabWidget(QupZilla* mainClass, QWidget *parent) : + QTabWidget(parent) + ,p_QupZilla(mainClass) + ,m_canRestoreTab(false) + ,m_lastTabIndex(0) + ,m_lastTabUrl(0) + ,m_lastTabHistory(0) +{ + m_tabBar = new TabBar(p_QupZilla); + setTabBar(m_tabBar); + setObjectName("tabWidget"); + setStyleSheet(" QTabBar::tab{max-width:250px; height: 28px;}"); + + loadSettings(); + + connect(this, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int))); + connect(this, SIGNAL(currentChanged(int)), p_QupZilla, SLOT(refreshHistory())); + connect(this, SIGNAL(currentChanged(int)), p_QupZilla->locationBar(), SLOT(checkRss())); + connect(this, SIGNAL(currentChanged(int)), p_QupZilla->locationBar(), SLOT(siteIconChanged())); + + connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int))); + connect(m_tabBar, SIGNAL(backTab(int)), this, SLOT(backTab(int))); + connect(m_tabBar, SIGNAL(forwardTab(int)), this, SLOT(forwardTab(int))); + connect(m_tabBar, SIGNAL(reloadTab(int)), this, SLOT(reloadTab(int))); + connect(m_tabBar, SIGNAL(stopTab(int)), this, SLOT(stopTab(int))); + connect(m_tabBar, SIGNAL(closeTab(int)), this, SLOT(closeTab(int))); + connect(m_tabBar, SIGNAL(closeAllButCurrent(int)), this, SLOT(closeAllButCurrent(int))); + + m_buttonListTabs = new QToolButton(this); + m_menuTabs = new QMenu(); + m_buttonListTabs->setMenu(m_menuTabs); + m_buttonListTabs->setToolButtonStyle(Qt::ToolButtonTextOnly); + m_buttonListTabs->setPopupMode(QToolButton::InstantPopup); + m_buttonListTabs->setAutoRaise(true); + m_buttonListTabs->setToolTip(tr("Show list of opened tabs")); + connect(m_menuTabs, SIGNAL(aboutToShow()), this, SLOT(aboutToShowTabsMenu())); + setCornerWidget(m_buttonListTabs); + + m_buttonAddTab = new QToolButton(this); + m_buttonAddTab->setIcon(QIcon(":/icons/other/plus.png")); + m_buttonAddTab->setToolTip(tr("Add Tab")); + m_buttonAddTab->setAutoRaise(true); + connect(m_buttonAddTab, SIGNAL(clicked()), p_QupZilla, SLOT(addTab())); + setCornerWidget(m_buttonAddTab, Qt::TopLeftCorner); +} + +void TabWidget::loadSettings() +{ + QSettings settings(MainApplication::getInstance()->getActiveProfil()+"settings.ini", QSettings::IniFormat); + settings.beginGroup("Browser-Tabs-Settings"); + m_hideCloseButtonWithOneTab = settings.value("hideCloseButtonWithOneTab",false).toBool(); + m_hideTabBarWithOneTab = settings.value("hideTabsWithOneTab",false).toBool(); + settings.endGroup(); + settings.beginGroup("Web-URL-Settings"); + m_urlOnNewTab = settings.value("newTabUrl","").toUrl(); + settings.endGroup(); + + m_tabBar->loadSettings(); +} + +void TabWidget::aboutToShowTabsMenu() +{ + m_menuTabs->clear(); + WebView* actView = weView(); + if (!actView) + return; + for (int i = 0; isetIcon(QIcon(":/icons/menu/circle.png")); + else + action->setIcon(LocationBar::icon(view->url())); + if (view->title().isEmpty()) { + if (view->isLoading()) { + action->setText(tr("Loading...")); + action->setIcon(QIcon(":/icons/other/progress.gif")); + }else + action->setText(tr("No Named Page")); + } + else{ + QString title = view->title(); + if (title.length()>40) { + title.truncate(40); + title+=".."; + } + action->setText(title); + } + action->setData(i); + connect(action, SIGNAL(triggered()), this, SLOT(actionChangeIndex())); + + m_menuTabs->addAction(action); + } + m_menuTabs->addSeparator(); + m_menuTabs->addAction(tr("Actually You have %1 opened tabs").arg(count()))->setEnabled(false); +} + +void TabWidget::actionChangeIndex() +{ + if (QAction *action = qobject_cast(sender())) { + setCurrentIndex(action->data().toInt()); + } +} + +int TabWidget::addView(QUrl url, QString title, OpenUrlIn openIn, bool selectLine) +{ + if (url.isEmpty()) + url = m_urlOnNewTab; + + int index = addTab(new WebTab(p_QupZilla),""); + setTabText(index, title); + weView(index)->animationLoading(index, true)->movie()->stop(); + weView(index)->animationLoading(index, false)->setPixmap(LocationBar::icon(url).pixmap(16,16)); + + if (openIn == TabWidget::NewSelectedTab) { + setCurrentIndex(index); + p_QupZilla->locationBar()->setText(url.toEncoded()); + p_QupZilla->locationBar()->setCursorPosition(0); + } + if (count() == 1 && m_hideTabBarWithOneTab) + tabBar()->setVisible(false); + else tabBar()->setVisible(true); + + if (count() == 1 && m_hideCloseButtonWithOneTab) + tabBar()->setTabsClosable(false); + else tabBar()->setTabsClosable(true); + + connect(weView(index), SIGNAL(siteIconChanged()), p_QupZilla->locationBar(), SLOT(siteIconChanged())); + connect(weView(index), SIGNAL(showUrl(QUrl)), p_QupZilla->locationBar(), SLOT(showUrl(QUrl))); + connect(weView(index), SIGNAL(checkRss()), p_QupZilla->locationBar(), SLOT(checkRss())); + connect(weView(index), SIGNAL(wantsCloseTab(int)), this, SLOT(closeTab(int))); + connect(weView(index), SIGNAL(changed()), p_QupZilla->getMainApp(), SLOT(setChanged())); + connect(weView(index), SIGNAL(ipChanged(QString)), p_QupZilla->ipLabel(), SLOT(setText(QString))); + + if (url.isValid()) + weView(index)->load(url); + if (selectLine) + p_QupZilla->locationBar()->setFocus(); + + return index; +} + +void TabWidget::setTabText(int index, const QString& text) +{ + QString newtext = text + " "; + QTabWidget::setTabText(index, newtext); +} + +void TabWidget::closeTab(int index) +{ + if (count() == 1) + return; + if (index == -1) + index = currentIndex(); + else m_lastTabIndex-=1; + + if (weView(index)) { + disconnect(weView(index), SIGNAL(siteIconChanged()), p_QupZilla->locationBar(), SLOT(siteIconChanged())); + disconnect(weView(index), SIGNAL(showUrl(QUrl)), p_QupZilla->locationBar(), SLOT(showUrl(QUrl))); + disconnect(weView(index), SIGNAL(checkRss()), p_QupZilla->locationBar(), SLOT(checkRss())); + disconnect(weView(index), SIGNAL(wantsCloseTab(int)), this, SLOT(closeTab(int))); + disconnect(weView(index), SIGNAL(changed()), p_QupZilla->getMainApp(), SLOT(setChanged())); + disconnect(weView(index), SIGNAL(ipChanged(QString)), p_QupZilla->ipLabel(), SLOT(setText(QString))); + //Save last tab url and history + if (!weView(index)->url().isEmpty()) { + m_lastTabUrl = weView(index)->url().toString(); + QDataStream tabHistoryStream(&m_lastTabHistory, QIODevice::WriteOnly); + tabHistoryStream << *weView(index)->history(); + m_canRestoreTab = true; + } + //weView(index)->page()->~QWebPage(); + //weView(index)->~QWebView(); + delete weView(index); + removeTab(index); + + if (count() == 1 && m_hideCloseButtonWithOneTab) + tabBar()->setTabsClosable(false); + if (count() == 1 && m_hideTabBarWithOneTab) + tabBar()->setVisible(false); + } +// if (count() < 1) +// p_QupZilla->close(); +} + +void TabWidget::tabChanged(int index) +{ + if (index<0) + return; + + QString title = p_QupZilla->weView()->title(); + if (title.isEmpty()) + title = tr("No Named Page"); + + p_QupZilla->setWindowTitle(title + " - QupZilla"); + p_QupZilla->locationBar()->showUrl(weView()->url(),false); + p_QupZilla->ipLabel()->setText(weView()->getIp()); + + if (p_QupZilla->inspectorDock() && p_QupZilla->inspectorDock()->isVisible()) + p_QupZilla->showInspector(); + + weView()->setFocus(); + + m_lastTabIndex = index; +} + +void TabWidget::reloadAllTabs() +{ + for (int i = 0;i(widget(index)); + + int cycleCounter = 0; // Only tab count * 1.6 attempts to + int maxCycles = count()*1.6; // close tabs -> it sometimes hangs here + while(count()!=1) { + for (int i = 0;i<=count();i++) { + if (widget(i) == akt) + continue; + closeTab(i); + cycleCounter++; + + if (cycleCounter >= maxCycles) + break; + } + if (cycleCounter >= maxCycles) + break; + } +} + +void TabWidget::restoreClosedTab() +{ + if (m_lastTabUrl.isEmpty()) + return; + int index = addView(QUrl()); + QDataStream historyStream(m_lastTabHistory); + historyStream >> *weView(index)->history(); + weView(index)->load(m_lastTabUrl); + m_canRestoreTab = false; +} + +QByteArray TabWidget::saveState() +{ + QByteArray data; + QDataStream stream(&data, QIODevice::WriteOnly); + + QStringList tabs; + QList tabsHistory; + for (int i = 0; i < count(); ++i) { + if (WebView *tab = weView(i)) { + tabs.append(QString::fromUtf8(tab->url().toEncoded())); + if (tab->history()->count() != 0) { + QByteArray tabHistory; + QDataStream tabHistoryStream(&tabHistory, QIODevice::WriteOnly); + tabHistoryStream << *tab->history(); + tabsHistory.append(tabHistory); + } else { + tabsHistory << QByteArray(); + } + } else { + tabs.append(QString::null); + tabsHistory.append(QByteArray()); + } + } + stream << tabs; + stream << currentIndex(); + stream << tabsHistory; + + return data; +} + +bool TabWidget::restoreState(const QByteArray &state) +{ + QByteArray sd = state; + QDataStream stream(&sd, QIODevice::ReadOnly); + if (stream.atEnd()) + return false; + + QStringList openTabs; + stream >> openTabs; + + int currentTab; + stream >> currentTab; + setCurrentIndex(currentTab); + QList tabHistory; + stream >> tabHistory; + + + for (int i = 0; i < openTabs.count(); ++i) { + QUrl url = QUrl::fromEncoded(openTabs.at(i).toUtf8()); + //TabWidget::OpenUrlIn tab = + + QByteArray historyState = tabHistory.value(i); + if (!historyState.isEmpty()) { + int index = addView(QUrl()); + QDataStream historyStream(historyState); + historyStream >> *weView(index)->history(); + weView(index)->load(url); + } else { + addView(url); + } + } + return true; +} + +TabWidget::~TabWidget() +{ + int index = currentIndex(); + closeAllButCurrent(index); + closeTab(index); + delete m_menuTabs; + delete m_buttonAddTab; + delete m_buttonListTabs; +} diff --git a/src/webview/tabwidget.h b/src/webview/tabwidget.h new file mode 100644 index 000000000..0c13b5608 --- /dev/null +++ b/src/webview/tabwidget.h @@ -0,0 +1,74 @@ +#ifndef TABWIDGET_H +#define TABWIDGET_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include "webview.h" +#include "webtab.h" +#include +#include +#include +#include + +class QupZilla; +class WebView; +class TabBar; +class WebTab; + +class TabWidget : public QTabWidget +{ + Q_OBJECT +public: + explicit TabWidget(QupZilla* mainclass, QWidget *parent = 0); + ~TabWidget(); + enum OpenUrlIn{ CurrentTab, NewSelectedTab, NewNotSelectedTab, NewTab = NewSelectedTab }; + + QByteArray saveState(); + bool restoreState(const QByteArray &state); + void setTabText(int index, const QString& text); + void loadSettings(); + + inline TabBar* getTabBar() { return m_tabBar; } + inline bool canRestoreTab() { return m_canRestoreTab; } + + +public slots: + void closeTab(int index=-1); + int addView(QUrl url = QUrl(), QString title = tr("New tab"), OpenUrlIn openIn = NewTab, bool selectLine = false); + void reloadTab(int index) { weView(index)->reload(); } + void reloadAllTabs(); + void stopTab(int index) { weView(index)->stop(); } + void backTab(int index) { weView(index)->back(); } + void forwardTab(int index) { weView(index)->forward(); } + void closeAllButCurrent(int index); + void restoreClosedTab(); + +private slots: + void tabChanged(int index); + void aboutToShowTabsMenu(); + void actionChangeIndex(); + +private: + inline WebView* weView() { return qobject_cast(widget(currentIndex()))->view(); } + inline WebView* weView(int index) { return qobject_cast(widget(index))->view(); } + + bool m_hideCloseButtonWithOneTab; + bool m_hideTabBarWithOneTab; + QUrl m_urlOnNewTab; + QupZilla* p_QupZilla; + + bool m_canRestoreTab; + int m_lastTabIndex; + QUrl m_lastTabUrl; + QByteArray m_lastTabHistory; + + TabBar* m_tabBar; + + QMenu* m_menuTabs; + QToolButton* m_buttonAddTab; + QToolButton* m_buttonListTabs; +}; + +#endif // TABWIDGET_H diff --git a/src/webview/webpage.cpp b/src/webview/webpage.cpp new file mode 100644 index 000000000..f6d437757 --- /dev/null +++ b/src/webview/webpage.cpp @@ -0,0 +1,172 @@ +#include "webpage.h" +#include "webview.h" +#include "tabwidget.h" +#include "qupzilla.h" +#include "downloadmanager.h" +#include "webpluginfactory.h" +#include "mainapplication.h" + +WebPage::WebPage(WebView *parent, QupZilla* mainClass) + : QWebPage(parent) + ,p_QupZilla(mainClass) + ,m_view(parent) +{ + setForwardUnsupportedContent(true); + setPluginFactory(new WebPluginFactory(this)); + connect(this, SIGNAL(unsupportedContent(QNetworkReply*)), SLOT(handleUnsupportedContent(QNetworkReply*))); +} + +void WebPage::handleUnsupportedContent(QNetworkReply* reply) +{ + if (!reply) + return; + QUrl url = reply->url(); + + switch(reply->error()) { + case QNetworkReply::NoError: + if (reply->header(QNetworkRequest::ContentTypeHeader).isValid()) { + DownloadManager* dManager = MainApplication::getInstance()->downManager(); + dManager->handleUnsupportedContent(reply); + return; + } + break; + case QNetworkReply::ProtocolUnknownError: + qDebug() << url << "ProtocolUnknowError"; + QDesktopServices::openUrl(url); + return; + break; + default: + qDebug() << reply->errorString(); + break; + } + qDebug() << "error" << reply->errorString(); +} + +bool WebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type) +{ + m_lastRequest = request; + m_lastRequestType = type; + QString scheme = request.url().scheme(); + if (scheme == "mailto" || scheme == "ftp") { + QDesktopServices::openUrl(request.url()); + return false; + } + + if (type == QWebPage::NavigationTypeFormResubmitted) { + QMessageBox::StandardButton button = QMessageBox::warning(view(), tr("Confirmation"), + tr("To show this page, QupZilla must resend request witch do it again " + "(like searching on making an shoping, witch has been already done."), QMessageBox::Yes | QMessageBox::No); + if (button != QMessageBox::Yes) + return false; + } + + TabWidget::OpenUrlIn openIn= frame ? TabWidget::CurrentTab: TabWidget::NewTab; + + bool accept = QWebPage::acceptNavigationRequest(frame, request, type); + if (accept && openIn == TabWidget::NewTab) { + //p_QupZilla->tabWidget()->addView(request.url(),tr("New tab"), openIn); + } + return accept; +} + +QString WebPage::userAgentForUrl(const QUrl &url) const +{ + return QWebPage::userAgentForUrl(url); +} + +void WebPage::populateNetworkRequest(QNetworkRequest &request) +{ + QVariant variant = qVariantFromValue((void *) this); + request.setAttribute((QNetworkRequest::Attribute)(QNetworkRequest::User + 100), variant); + request.setAttribute((QNetworkRequest::Attribute)(QNetworkRequest::User + 101), m_lastRequestType); + + variant = qVariantFromValue((void *) m_view); + request.setAttribute((QNetworkRequest::Attribute)(QNetworkRequest::User + 102), variant); +} + +QWebPage* WebPage::createWindow(QWebPage::WebWindowType type) +{ + Q_UNUSED(type); + int index = p_QupZilla->tabWidget()->addView(); + return p_QupZilla->weView(index)->page(); +} + +bool WebPage::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output) +{ + if (extension == ChooseMultipleFilesExtension) + return QWebPage::extension(extension, option, output); + + const ErrorPageExtensionOption* exOption = static_cast(option); + ErrorPageExtensionReturn* exReturn = static_cast(output); + + QString errorString; + if (exOption->domain == QWebPage::QtNetwork) { + switch (exOption->error) { + case QNetworkReply::ConnectionRefusedError: + errorString = tr("Server refused the connection"); + break; + case QNetworkReply::RemoteHostClosedError: + errorString = tr("Server closed the connection"); + break; + case QNetworkReply::HostNotFoundError: + errorString = tr("Server not found"); + break; + case QNetworkReply::TimeoutError: + errorString = tr("Connection timed out"); + break; + case QNetworkReply::SslHandshakeFailedError: + errorString = tr("Untrusted connection"); + break; + default: + //errorString = exOption->error; + if (errorString.isEmpty()) + errorString = tr("Unknown error"); + break; + } + } + else if (exOption->domain == QWebPage::Http) { + errorString = tr("Error code %1").arg(exOption->error); + } + else if (exOption->domain == QWebPage::WebKit) + return false; // Downloads + + QString loadedUrl = exOption->url.toString(); + exReturn->baseUrl = loadedUrl; + + QFile file(":/html/errorPage.html"); + file.open(QFile::ReadOnly); + QString errString = file.readAll(); + errString.replace("%TITLE%", tr("Failed loading page")); + + //QPixmap pixmap = QIcon::fromTheme("dialog-warning").pixmap(45,45); + QPixmap pixmap = MainApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(45,45); + QByteArray bytes; + QBuffer buffer(&bytes); + buffer.open(QIODevice::WriteOnly); + if (pixmap.save(&buffer, "PNG")) + errString.replace("%IMAGE%", buffer.buffer().toBase64()); + + //pixmap = QIcon::fromTheme("dialog-warning").pixmap(16,16); + pixmap = MainApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(16,16); + bytes.clear(); + QBuffer buffer2(&bytes); + buffer2.open(QIODevice::WriteOnly); + if (pixmap.save(&buffer2, "PNG")) + errString.replace("%FAVICON%", buffer.buffer().toBase64()); + + errString.replace("%HEADING%", errorString); + errString.replace("%HEADING2%", tr("QupZilla can't load page at %1.").arg(loadedUrl)); + errString.replace("%LI-1%", tr("Check the address for typing errors such as ww.example.com instead of www.example.com")); + errString.replace("%LI-2%", tr("If you are unable to load any pages, check your computer's network connection.")); + errString.replace("%LI-3%", tr("If your computer or network is protected by a firewall or proxy, make sure that QupZilla is permitted to access the Web.")); + errString.replace("%TRY-AGAIN%", tr("Try Again")); + + exReturn->content = errString.toUtf8(); + return true; +} + +WebPage::~WebPage() +{ + setNetworkAccessManager(0); + mainFrame()->deleteLater(); +} diff --git a/src/webview/webpage.h b/src/webview/webpage.h new file mode 100644 index 000000000..782cf3f5e --- /dev/null +++ b/src/webview/webpage.h @@ -0,0 +1,47 @@ +#ifndef WEBPAGE_H +#define WEBPAGE_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class QupZilla; +class WebView; +class WebPage : public QWebPage +{ + Q_OBJECT +public: + WebPage(WebView *parent, QupZilla* mainClass); + void populateNetworkRequest(QNetworkRequest &request); + ~WebPage(); + + QString userAgentForUrl(const QUrl &url) const; + bool supportsExtension(Extension extension) const { return (extension == ErrorPageExtension); } + bool extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output); + +protected slots: + QWebPage* createWindow(QWebPage::WebWindowType type); + void handleUnsupportedContent(QNetworkReply* url); + +protected: + bool acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type); + + QupZilla* p_QupZilla; + QNetworkRequest m_lastRequest; + QWebPage::NavigationType m_lastRequestType; + WebView* m_view; +}; + +#endif // WEBPAGE_H diff --git a/src/webview/webtab.cpp b/src/webview/webtab.cpp new file mode 100644 index 000000000..3b42f3d88 --- /dev/null +++ b/src/webview/webtab.cpp @@ -0,0 +1,33 @@ +#include "webtab.h" +#include "qupzilla.h" +#include "webview.h" + +WebTab::WebTab(QupZilla* mainClass, QWidget *parent) + :QWidget(parent) + ,p_QupZilla(mainClass) + ,m_view(0) +{ + m_layout = new QVBoxLayout(this); + setLayout(m_layout); + m_layout->setContentsMargins(0,0,0,0); + m_layout->setSpacing(0); + m_view = new WebView(p_QupZilla); + m_layout->addWidget(m_view); + + setAutoFillBackground(true); // We don't want opaque this + + connect(m_view, SIGNAL(showNotification(QWidget*)), this, SLOT(showNotification(QWidget*))); +} + +void WebTab::showNotification(QWidget *notif) +{ + if (m_layout->count() > 1) + delete m_layout->itemAt(0)->widget(); + + m_layout->insertWidget(0, notif); +} + +WebTab::~WebTab() +{ + delete m_view; +} diff --git a/src/webview/webtab.h b/src/webview/webtab.h new file mode 100644 index 000000000..3c02feb9a --- /dev/null +++ b/src/webview/webtab.h @@ -0,0 +1,27 @@ +#ifndef WEBTAB_H +#define WEBTAB_H + +#include +#include +#include +#include "webview.h" + +class QupZilla; +class WebTab : public QWidget +{ + Q_OBJECT +public: + explicit WebTab(QupZilla* mainClass, QWidget *parent = 0); + ~WebTab(); + WebView* view() { return m_view; } + +private slots: + void showNotification(QWidget* notif); + +private: + QupZilla* p_QupZilla; + QPointer m_view; + QVBoxLayout* m_layout; +}; + +#endif // WEBTAB_H diff --git a/src/webview/webview.cpp b/src/webview/webview.cpp new file mode 100644 index 000000000..fe946e9b5 --- /dev/null +++ b/src/webview/webview.cpp @@ -0,0 +1,679 @@ +#include "webview.h" +#include "qupzilla.h" +#include "webpage.h" +#include "tabwidget.h" +#include "historymodel.h" +#include "locationbar.h" +#include "downloadmanager.h" +#include "networkmanager.h" +#include "autofillmodel.h" +#include "networkmanagerproxy.h" +#include "mainapplication.h" +#include "tabbar.h" +#include "pluginproxy.h" +#include "webtab.h" + +WebView::WebView(QupZilla* mainClass, QWidget *parent) + : QWebView(parent) + ,p_QupZilla(mainClass) + ,m_progress(0) + ,m_isLoading(false) + ,m_currentZoom(100) + ,m_aboutToLoadUrl(QUrl()) + ,m_wantsClose(false) + ,m_page(new WebPage(this, p_QupZilla)) + //,m_loadingTimer(0) +{ + m_networkProxy = new NetworkManagerProxy(p_QupZilla); + m_networkProxy->setPrimaryNetworkAccessManager(p_QupZilla->getMainApp()->networkManager()); + m_networkProxy->setPage(m_page); + m_networkProxy->setView(this); + m_page->setNetworkAccessManager(m_networkProxy); + m_page->setView(this); + setPage(m_page); + + + connect(this, SIGNAL(loadStarted()), this, SLOT(loadStarted())); + connect(this, SIGNAL(loadProgress(int)), this, SLOT(setProgress(int))); + connect(this, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool))); + + connect(this, SIGNAL(linkClicked(QUrl)), this, SLOT(linkClicked(QUrl))); + connect(this, SIGNAL(urlChanged(QUrl)), this, SLOT(urlChanged(QUrl))); + connect(this, SIGNAL(titleChanged(QString)), this, SLOT(titleChanged(QString))); + + connect(this, SIGNAL(statusBarMessage(QString)), p_QupZilla->statusBar(), SLOT(showMessage(QString))); + + connect(page(), SIGNAL(linkHovered(QString, QString, QString)), this, SLOT(linkHovered(QString, QString, QString))); + connect(page(), SIGNAL(windowCloseRequested()), this, SLOT(closeTab())); + connect(page(), SIGNAL(downloadRequested(const QNetworkRequest &)), this, SLOT(downloadRequested(const QNetworkRequest &))); + + connect(p_QupZilla->getMainApp()->networkManager(), SIGNAL(finishLoading(bool)), this, SLOT(loadFinished(bool))); + connect(p_QupZilla->getMainApp()->networkManager(), SIGNAL(wantsFocus(QUrl)), this, SLOT(getFocus(QUrl))); + + //Zoom levels same as in firefox + m_zoomLevels << 30 << 50 << 67 << 80 << 90 << 100 << 110 << 120 << 133 << 150 << 170 << 200 << 240 << 300; +} + +WebPage* WebView::getPage() const +{ + return m_page; +} + +bool WebView::isCurrent() +{ + if (!tabWidget()) + return false; + if (qobject_cast(tabWidget()->widget(tabWidget()->currentIndex()))->view() == this) + return true; + + return false; +} + +void WebView::urlChanged(const QUrl &url) +{ + if (isCurrent()) { + emit showUrl(url); + p_QupZilla->refreshHistory(); + } + emit changed(); +} + +void WebView::linkClicked(const QUrl &url) +{ + qDebug() << __FUNCTION__ << "called"; + if (isCurrent()) + emit showUrl(url); +} + +void WebView::setProgress(int prog) +{ + m_progress = prog; + if (isCurrent()) { + emit showUrl(url()); + } +} + +void WebView::loadStarted() +{ + m_progress = 0; + m_isLoading = true; + + animationLoading(tabIndex(),true); + if (title().isNull()) + tabWidget()->setTabText(tabIndex(),tr("Loading...")); + + if (isCurrent()) { + emit showUrl(url()); + } + + m_currentIp.clear(); + +// if (m_loadingTimer) +// delete m_loadingTimer; +// m_loadingTimer = new QTimer(); +// connect(m_loadingTimer, SIGNAL(timeout()), this, SLOT(stopAnimation())); +// m_loadingTimer->start(1000*20); //20 seconds timeout to automatically "stop" loading animation +} + +QLabel *WebView::animationLoading(int index, bool addMovie) +{ + if (-1 == index) + return 0; + + QLabel *loadingAnimation = qobject_cast(tabWidget()->getTabBar()->tabButton(index, QTabBar::LeftSide)); + if (!loadingAnimation) { + loadingAnimation = new QLabel(this); + } + if (addMovie && !loadingAnimation->movie()) { + QMovie *movie = new QMovie(":icons/other/progress.gif", QByteArray(), loadingAnimation); + movie->setSpeed(70); + loadingAnimation->setMovie(movie); + movie->start(); + } + else if (loadingAnimation->movie()) + loadingAnimation->movie()->stop(); + + tabWidget()->getTabBar()->setTabButton(index, QTabBar::LeftSide, 0); + tabWidget()->getTabBar()->setTabButton(index, QTabBar::LeftSide, loadingAnimation); + return loadingAnimation; +} + +void WebView::stopAnimation() +{ + //m_loadingTimer->stop(); + QMovie* mov = animationLoading(tabIndex(), false)->movie(); + if (mov) { + mov->stop(); + iconChanged(); + } +} + +void WebView::setIp(QHostInfo info) +{ + if (info.addresses().isEmpty()) + return; + m_currentIp = info.hostName() + " ("+info.addresses().at(0).toString()+")"; + + if (isCurrent()) + emit ipChanged(m_currentIp); +} + +void WebView::loadFinished(bool state) +{ + Q_UNUSED(state); + if (!animationLoading(tabIndex(), false)) + return; + + if (animationLoading(tabIndex(), false)->movie()) + animationLoading(tabIndex(), false)->movie()->stop(); + if (m_progress>100) qDebug() << "bug"; //cannot be more than 100 + m_isLoading = false; + + p_QupZilla->getMainApp()->history()->addHistoryEntry(this); + if (isCurrent()) { + emit showUrl(url()); + emit checkRss(); + } + + iconChanged(); + + if (!p_QupZilla->locationBar()->hasFocus()) + setFocus(); + + //Fix the bug where sometimes icon is not available at the moment + if (icon().isNull()) + QTimer::singleShot(1000, this, SLOT(iconChanged())); + + titleChanged(title()); + MainApplication::getInstance()->autoFill()->completePage(this); + QHostInfo::lookupHost(url().host(), this, SLOT(setIp(QHostInfo))); +} + +void WebView::titleChanged(QString title) +{ + if (title.isEmpty()) title = url().host(); + if (title.isEmpty()) title = tr("No Named Page"); + QString title2 = title; + tabWidget()->setTabToolTip(tabIndex(),title2); + + title2+=" - QupZilla"; + if (isCurrent()) + p_QupZilla->setWindowTitle(title2); + + tabWidget()->setTabText(tabIndex(),title); +} + +void WebView::iconChanged() +{ + QIcon icon_ = icon(); + if (!icon_.isNull()) + animationLoading(tabIndex(), false)->setPixmap(icon_.pixmap(16,16)); + else + animationLoading(tabIndex(), false)->setPixmap(QIcon(":icons/locationbar/unknownpage.png").pixmap(16,16)); + + if (isCurrent()) + emit siteIconChanged(); +} + +void WebView::linkHovered(const QString &link, const QString &title, const QString &content) +{ + Q_UNUSED(title); + Q_UNUSED(content); + if (isCurrent()) { + if (link!="") { + p_QupZilla->statusBar()->showMessage(link); + }else{ + isLoading() ? p_QupZilla->statusBar()->showMessage(tr("Loading...")) : p_QupZilla->statusBar()->showMessage(tr("Done")); + } + } + m_hoveredLink = link; +} + +TabWidget* WebView::tabWidget() const +{ + QObject *widget = this->parent(); + while (widget) { + if (TabWidget *tw = qobject_cast(widget)) + return tw; + widget = widget->parent(); + } + return 0; +} + +int WebView::tabIndex() const +{ + TabWidget* tabWid = tabWidget(); + if (!tabWid) + return -1; + + int i = 0; + while(qobject_cast(tabWid->widget(i))->view()!=this) { + i++; + } + return i; +} + +QUrl WebView::guessUrlFromString(const QString &string) +{ + QString trimmedString = string.trimmed(); + + // Check the most common case of a valid url with scheme and host first + QUrl url = QUrl::fromEncoded(trimmedString.toUtf8(), QUrl::TolerantMode); + if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) + return url; + + // Absolute files that exists + if (QDir::isAbsolutePath(trimmedString) && QFile::exists(trimmedString)) + return QUrl::fromLocalFile(trimmedString); + + // If the string is missing the scheme or the scheme is not valid prepend a scheme + QString scheme = url.scheme(); + if (scheme.isEmpty() || scheme.contains(QLatin1Char('.')) || scheme == QLatin1String("localhost")) { + // Do not do anything for strings such as "foo", only "foo.com" + int dotIndex = trimmedString.indexOf(QLatin1Char('.')); + if (dotIndex != -1 || trimmedString.startsWith(QLatin1String("localhost"))) { + const QString hostscheme = trimmedString.left(dotIndex).toLower(); + QByteArray scheme = (hostscheme == QLatin1String("ftp")) ? "ftp" : "http"; + trimmedString = QLatin1String(scheme) + QLatin1String("://") + trimmedString; + } + url = QUrl::fromEncoded(trimmedString.toUtf8(), QUrl::TolerantMode); + } + + if (url.isValid()) + return url; + + return QUrl(); +} + +void WebView::mousePressEvent(QMouseEvent *event) +{ + switch (event->button()) { + case Qt::XButton1: + back(); + break; + case Qt::XButton2: + forward(); + break; + case Qt::MiddleButton: + if (isUrlValid(QUrl(m_hoveredLink))) + tabWidget()->addView(QUrl(m_hoveredLink),tr("New tab"), TabWidget::NewNotSelectedTab); + break; + case Qt::LeftButton: + if (event->modifiers() == Qt::ControlModifier && isUrlValid(QUrl(m_hoveredLink))) { + tabWidget()->addView(QUrl(m_hoveredLink),tr("New tab"), TabWidget::NewNotSelectedTab); + return; + } + default: + QWebView::mousePressEvent(event); + break; + } +} + +void WebView::mouseReleaseEvent(QMouseEvent* event) +{ + //Workaround for crash in mouseReleaseEvent when closing tab from javascript :/ + if (!m_wantsClose) + QWebView::mouseReleaseEvent(event); +} + +void WebView::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Back: + back(); + event->accept(); + break; + case Qt::Key_Forward: + forward(); + event->accept(); + break; + case Qt::Key_Stop: + stop(); + event->accept(); + break; + case Qt::Key_Refresh: + reload(); + event->accept(); + break; + default: + QWebView::keyPressEvent(event); + return; + } +} + +void WebView::contextMenuEvent(QContextMenuEvent *event) +{ + QMenu *menu = new QMenu(this); + + QWebHitTestResult r = page()->mainFrame()->hitTestContent(event->pos()); + + if (!r.linkUrl().isEmpty()) { + if (page()->selectedText() == r.linkText()) + findText(""); + menu->addAction(tr("Open link in new window"), this, SLOT(openUrlInNewWindow()))->setData(r.linkUrl()); + menu->addAction(QIcon(":/icons/menu/popup.png"), tr("Open link in new tab"), this, SLOT(openUrlInNewTab()))->setData(r.linkUrl()); + menu->addSeparator(); + menu->addAction(QIcon::fromTheme("user-bookmarks"), tr("Bookmark link"), this, SLOT(bookmarkLink()))->setData(r.linkUrl()); + menu->addAction(QIcon::fromTheme("document-save"), tr("Save link as..."), this, SLOT(downloadLinkToDisk()))->setData(r.linkUrl()); + menu->addAction(tr("Send link..."), this, SLOT(sendLinkByMail()))->setData(r.linkUrl()); + menu->addAction(QIcon::fromTheme("edit-copy"), tr("Copy link address"), this, SLOT(copyLinkToClipboard()))->setData(r.linkUrl()); + menu->addSeparator(); + if (!page()->selectedText().isEmpty()) + menu->addAction(pageAction(QWebPage::Copy)); + } + + if (!r.imageUrl().isEmpty()) { + if (!menu->isEmpty()) + menu->addSeparator(); + menu->addAction(tr("Show image"), this, SLOT(showImage()))->setData(r.imageUrl()); + menu->addAction(tr("Copy image"), this, SLOT(copyImageToClipboard()))->setData(r.imageUrl()); + menu->addAction(QIcon::fromTheme("edit-copy"), tr("Copy image address"), this, SLOT(copyLinkToClipboard()))->setData(r.imageUrl()); + menu->addSeparator(); + menu->addAction(QIcon::fromTheme("document-save"), tr("Save image as..."), this, SLOT(downloadImageToDisk())); + menu->addAction(tr("Send image..."), this, SLOT(sendLinkByMail()))->setData(r.linkUrl()); + menu->addSeparator(); + //menu->addAction(tr("Block image"), this, SLOT(blockImage()))->setData(r.imageUrl().toString()); + if (!page()->selectedText().isEmpty()) + menu->addAction(pageAction(QWebPage::Copy)); + } + + QWebElement element = r.element(); + if (!element.isNull() && (element.tagName().toLower() == "input" || element.tagName().toLower() == "textarea")) { + if (menu->isEmpty()) { + delete menu; + menu = page()->createStandardContextMenu(); + } + } + + if (menu->isEmpty()) { + QAction* action = menu->addAction(tr("Back"), this, SLOT(back())); +#ifdef Q_WS_X11 + action->setIcon(style()->standardIcon(QStyle::SP_ArrowBack)); +#else + action->setIcon(QIcon(":/icons/faenza/back.png")); +#endif + history()->canGoBack() ? action->setEnabled(true) : action->setEnabled(false); + + action = menu->addAction(tr("Forward"), this, SLOT(forward())); +#ifdef Q_WS_X11 + action->setIcon(style()->standardIcon(QStyle::SP_ArrowForward)); +#else + action->setIcon(QIcon(":/icons/faenza/forward.png")); +#endif + history()->canGoForward() ? action->setEnabled(true) : action->setEnabled(false); + + menu->addAction( +#ifdef Q_WS_X11 + style()->standardIcon(QStyle::SP_BrowserReload) +#else + QIcon(":/icons/faenza/reload.png") +#endif + ,tr("Reload"), this, SLOT(slotReload())); + action = menu->addAction( +#ifdef Q_WS_X11 + style()->standardIcon(QStyle::SP_BrowserStop) +#else + QIcon(":/icons/faenza/stop.png") +#endif + ,tr("Stop"), this, SLOT(stop())); + isLoading() ? action->setEnabled(true) : action->setEnabled(false); + + menu->addSeparator(); + menu->addAction(QIcon::fromTheme("user-bookmarks"), tr("Bookmark page"), this, SLOT(bookmarkLink())); + menu->addAction(QIcon::fromTheme("document-save"), tr("Save page as..."), this, SLOT(downloadLinkToDisk()))->setData(url()); + menu->addAction(tr("Send page..."), this, SLOT(sendLinkByMail()))->setData(url()); + menu->addSeparator(); + menu->addAction(QIcon::fromTheme("edit-select-all"), tr("Select all"), this, SLOT(selectAll())); + if (!page()->selectedText().isEmpty()) + menu->addAction(pageAction(QWebPage::Copy)); + + menu->addSeparator(); + menu->addAction(QIcon::fromTheme("text-html"),tr("Show source code"), this, SLOT(showSource())); + menu->addAction(QIcon::fromTheme("dialog-information"),tr("Show info about site"), this, SLOT(showSiteInfo()))->setData(url()); + } + + MainApplication::getInstance()->plugins()->populateWebViewMenu(menu, this, r); + menu->addAction(tr("Show Web Inspector"), this, SLOT(showInspector())); + + if (!page()->selectedText().isEmpty()) { + menu->addSeparator(); + QString selectedText = page()->selectedText(); + selectedText.truncate(20); + menu->addAction(QIcon(":icons/used/google.png"), tr("Search ")+selectedText+tr("... on Google"), this, SLOT(searchOnGoogle()))->setData(page()->selectedText()); + } + + if (!menu->isEmpty()) { + //Prevent choosing first option with double rightclick + QPoint pos = QCursor::pos(); + QPoint p(pos.x(), pos.y()+1); + menu->exec(p); + delete menu; + return; + } + + QWebView::contextMenuEvent(event); +} + +void WebView::addNotification(QWidget *notif) +{ + emit showNotification(notif); +} + +void WebView::openUrlInNewTab() +{ + if (QAction *action = qobject_cast(sender())) { + tabWidget()->addView(action->data().toUrl(), tr("New tab"), TabWidget::NewNotSelectedTab); + } +} + +void WebView::openUrlInNewWindow() +{ + if (QAction *action = qobject_cast(sender())) { + p_QupZilla->getMainApp()->makeNewWindow(false, action->data().toString()); + } +} + +void WebView::sendLinkByMail() +{ + if (QAction *action = qobject_cast(sender())) { + QDesktopServices::openUrl(QUrl("mailto:?body="+action->data().toString())); + } +} + +void WebView::copyLinkToClipboard() +{ + if (QAction *action = qobject_cast(sender())) { + QApplication::clipboard()->setText(action->data().toString()); + } +} + +void WebView::searchOnGoogle() +{ + if (QAction *action = qobject_cast(sender())) { + load(QUrl("http://www.google.com/search?client=qupzilla&q="+action->data().toString())); + } +} + +void WebView::selectAll() +{ + triggerPageAction(QWebPage::SelectAll); +} + +void WebView::downloadImageToDisk() +{ + triggerPageAction(QWebPage::DownloadImageToDisk); +} + +void WebView::copyImageToClipboard() +{ + triggerPageAction(QWebPage::CopyImageToClipboard); +} + +void WebView::showImage() +{ + if (QAction *action = qobject_cast(sender())) { + load(QUrl(action->data().toString())); + } +} + +void WebView::showSource() +{ + p_QupZilla->showSource(); +} + +void WebView::downloadLinkToDisk() +{ + if (QAction *action = qobject_cast(sender())) { + QNetworkRequest request(action->data().toUrl()); + DownloadManager* dManager = MainApplication::getInstance()->downManager(); + dManager->download(request); + } +} + +void WebView::downloadRequested(const QNetworkRequest &request) +{ + DownloadManager* dManager = MainApplication::getInstance()->downManager(); + dManager->download(request); +} + +void WebView::bookmarkLink() +{ + if (QAction *action = qobject_cast(sender())) { + if (action->data().isNull()) + p_QupZilla->bookmarkPage(); + else + p_QupZilla->addBookmark(action->data().toUrl(), action->data().toString()); + } +} + +void WebView::showInspector() +{ + p_QupZilla->showInspector(); +} + +void WebView::showSiteInfo() +{ + p_QupZilla->showPageInfo(); +} + +void WebView::applyZoom() +{ + setZoomFactor(qreal(m_currentZoom) / 100.0); +} + +void WebView::zoomIn() +{ + int i = m_zoomLevels.indexOf(m_currentZoom); + + if (i < m_zoomLevels.count() - 1) + m_currentZoom = m_zoomLevels[i + 1]; + applyZoom(); +} + +void WebView::zoomOut() +{ + int i = m_zoomLevels.indexOf(m_currentZoom); + + if (i > 0) + m_currentZoom = m_zoomLevels[i - 1]; + applyZoom(); +} + +void WebView::zoomReset() +{ + m_currentZoom = 100; + applyZoom(); +} + +void WebView::wheelEvent(QWheelEvent *event) +{ + if (event->modifiers() & Qt::ControlModifier) { + int numDegrees = event->delta() / 8; + int numSteps = numDegrees / 15; + if (numSteps == 1) + zoomIn(); + else + zoomOut(); + event->accept(); + return; + } + QWebView::wheelEvent(event); +} + +void WebView::getFocus(const QUrl &urla) +{ + if (urla == url()) + tabWidget()->setCurrentWidget(this); +} + +void WebView::closeTab() +{ + if (m_wantsClose) + emit wantsCloseTab(tabIndex()); + else { + m_wantsClose = true; + QTimer::singleShot(20, this, SLOT(closeTab())); + } +} + +void WebView::load(QUrl url) +{ + if (url.toString().startsWith("javascript:")) { + page()->mainFrame()->evaluateJavaScript(url.toString()); + return; + } + if (isUrlValid(url)) { + QWebView::load(url); + m_aboutToLoadUrl = url; + return; + } + +#ifdef Q_WS_WIN + if (QFile::exists(url.path().mid(1))) // From QUrl(file:///C:/Bla/ble/foo.html it returns + // /C:/Bla/ble/foo.html ... so we cut first char +#else + if (QFile::exists(url.path())) +#endif + QWebView::load(url); + else + QWebView::load(QUrl("http://www.google.com/search?client=qupzilla&q="+url.toString())); +} + +QUrl WebView::url() const +{ + QUrl ur = QWebView::url(); + if (ur.isEmpty() && !m_aboutToLoadUrl.isEmpty()) + return m_aboutToLoadUrl; + return ur; +} + +QString WebView::title() const +{ + QString title = QWebView::title(); + if (title.isEmpty()) + return tr("No Named Page"); + return title; +} + +void WebView::reload() +{ + if (QWebView::url().isEmpty() && !m_aboutToLoadUrl.isEmpty()) { + qDebug() << "loading about to load"; + load(m_aboutToLoadUrl); + return; + } + QWebView::reload(); +} + +bool WebView::isUrlValid(const QUrl &url) +{ + if (url.isValid() && !url.host().isEmpty() && !url.scheme().isEmpty()) + return true; + return false; +} + +WebView::~WebView() +{ + history()->clear(); + delete m_page; +} diff --git a/src/webview/webview.h b/src/webview/webview.h new file mode 100644 index 000000000..0b59fec89 --- /dev/null +++ b/src/webview/webview.h @@ -0,0 +1,122 @@ +#ifndef WEBVIEW_H +#define WEBVIEW_H + +#if defined(QT_NO_DEBUG) & !defined(QT_NO_DEBUG_OUTPUT) +#define QT_NO_DEBUG_OUTPUT +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class QupZilla; +class TabWidget; +class WebPage; +class NetworkManagerProxy; + +class WebView : public QWebView +{ + Q_OBJECT +public: + explicit WebView(QupZilla* mainClass, QWidget *parent = 0); + ~WebView(); + bool isLoading() { return m_isLoading;} + int getLoading() { return m_progress; } + + void zoomReset(); + void load(QUrl url); + QUrl url() const; + QString title() const; + void reload(); + WebPage* getPage() const; + QString getIp() { return m_currentIp; } + QLabel* animationLoading(int index, bool addMovie); + void addNotification(QWidget* notif); + + static QUrl guessUrlFromString(const QString &string); + static bool isUrlValid(const QUrl &url); + +public slots: + void stop(){ if (page()) {emit ipChanged(m_currentIp); page()->triggerAction(QWebPage::Stop); loadFinished(true);} } + void back(){ if (page()) {emit ipChanged(m_currentIp); page()->triggerAction(QWebPage::Back);} } + void forward(){ if (page()) {emit ipChanged(m_currentIp); page()->triggerAction(QWebPage::Forward);} } + void slotReload(){ if (page()) {emit ipChanged(m_currentIp); page()->triggerAction(QWebPage::Reload);} } + void iconChanged(); + void selectAll(); + + void zoomIn(); + void zoomOut(); + +private slots: + void showImage(); + void copyImageToClipboard(); + void downloadImageToDisk(); + void searchOnGoogle(); + void copyLinkToClipboard(); + void loadStarted(); + void downloadRequested(const QNetworkRequest &request); + void setProgress(int prog); + void loadFinished(bool state); + void linkClicked(const QUrl &url); + void urlChanged(const QUrl &url); + void titleChanged(QString title); + void linkHovered(const QString &link, const QString &title, const QString &content); + void openUrlInNewWindow(); + void openUrlInNewTab(); + void closeTab(); + void downloadLinkToDisk(); + void sendLinkByMail(); + void bookmarkLink(); + void showSource(); + void showSiteInfo(); + void getFocus(const QUrl &urla); + void showInspector(); + void stopAnimation(); + void setIp(QHostInfo info); + +private: + void keyPressEvent(QKeyEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void contextMenuEvent(QContextMenuEvent *event); + void wheelEvent(QWheelEvent *event); + TabWidget* tabWidget() const; + int tabIndex() const; + bool isCurrent(); + void applyZoom(); + + QupZilla* p_QupZilla; + int m_progress; + bool m_isLoading; + QString m_hoveredLink; + QList m_zoomLevels; + int m_currentZoom; + QUrl m_aboutToLoadUrl; + bool m_wantsClose; + QString m_currentIp; + + WebPage* m_page; + NetworkManagerProxy* m_networkProxy; + //QTimer* m_loadingTimer; //Too confusing + +signals: + void showUrl(QUrl url); + void siteIconChanged(); + void setPrivacy(bool state); + void checkRss(); + void wantsCloseTab(int index); + void changed(); + void ipChanged(QString ip); + void showNotification(QWidget* notif); +}; + +#endif // WEBVIEW_H diff --git a/translations/cs_CZ.ts b/translations/cs_CZ.ts new file mode 100644 index 000000000..77b52c125 --- /dev/null +++ b/translations/cs_CZ.ts @@ -0,0 +1,2574 @@ + + + + + AboutDialog + + + About QupZilla + O QupZille + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Ubuntu'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + + Authors + Autoři + + + + + Authors and Contributors + Autoři a Spolupracovníci + + + + + < About QupZilla + < O QupZille + + + + <p><b>Application version %1</b><br/> + <p><b>Verze aplikace %1</b><br/> + + + + <b>WebKit version %1</b></p> + <b>Verze WebKitu %1</b></p> + + + + <p>&copy; %1 %2<br/>All rights reserved.<br/> + <p>&copy; %1 %2<br/>Všechna práva vyhrazena.<br/> + + + + Build time: %1 </p> + Datum sestavení: %1 </p> + + + + <p><b>Main developers:</b><br/>%1 &lt;%2&gt;</p> + <p><b>Hlavní vývojáři:</b><br/>%1 &lt;%2&gt;</p> + + + + <p><b>Other contributors:</b><br/>%1</p> + <p><b>Ostatní spolupracovníci:</b><br/>%1</p> + + + + <p><b>Thanks to:</b><br/>%1</p> + <p><b>Poděkování:</b><br/>%1</p> + + + + AutoFillManager + + + Password Manager + Správce hesel + + + + Passwords + Hesla + + + + + Server + Server + + + + Password + Heslo + + + + + Remove + Odstranit + + + + Edit + Upravit + + + + + Remove All + Odstranit vše + + + + Exceptions + Vyjímky + + + + Confirmation + Potvrzení + + + + Are you sure to delete all passwords on your computer? + Opravdu si přejete smazat všechna hesla? + + + + Edit password + Upravit heslo + + + + Change password: + Změnit heslo: + + + + AutoFillModel + + + <b>Would you like to save this password?</b><br>To show all stored passwords open the Password Manager panel in preferences. + <b>Would you like to save this password?</b><br>To show all stored passwords open the AutoFill panel in preferences. + <b>Přejete si uložit toto heslo?</b><br>K zobrazení všech uložených hesel otevřete panel Správce hesel v předvolbách. + + + + Never for this site + Nikdy pro tuto stránku + + + + Not now + Nyní ne + + + + BookmarksManager + + + Bookmarks + Záložky + + + + Title + Titulek + + + + Url + Adresa + + + + Delete + Odstranit + + + + Del + Del + + + + Add Folder + Přidat složku + + + + Add new folder + Přidat složku + + + + Choose name for new bookmark folder: + Zvolte jméno pro novou složku: + + + + New Tab + Nový panel + + + + + + + + + + + Bookmarks In Menu + Záložky v menu + + + + + + + + + + + Bookmarks In ToolBar + Panel záložek + + + + Open link in actual tab + Otevřít odkaz v aktuálním panelu + + + + Open link in new tab + Otevřít odkaz v novém panelu + + + + Move bookmark to folder + Přesunout záložku do složky + + + + + + + + Unsorted Bookmarks + Nesetříděné záložky + + + + Close + Zavřít + + + + <b>Warning: </b>You already have this page bookmarked! + <b>Upozornění: </b>Tuto stránku již máte v záložkách! + + + + Choose name and location of bookmark. + Zvolte jméno a umístění záložky. + + + + Add New Bookmark + Přidat záložku + + + + Choose folder for bookmarks: + Zvolte složku pro záložky: + + + + Bookmark All Tabs + Přidat všechny panely do záložek + + + + BookmarksToolbar + + + Bookmarks + Záložky + + + + Bookmark Current Page + Přidat stránku do záložek + + + + Bookmark All Tabs + Přidat všechny panely do záložek + + + + Organize Bookmarks + Organizovat záložky + + + + Reload Toolbar + Obnovit panel + + + + Hide Most Visited + Skrýt Nejnavštěvovanější + + + + Show Most Visited + Zobrazit Nejnavštěvovanější + + + + Hide Toolbar + Skrýt panel + + + + Most visited + Nejnavštěvovanější + + + + Sites You visited the most + Nejvíce navštěvované stránky + + + + BookmarksWidget + + + Edit This Bookmark + Upravit tuto záložku + + + + Remove Bookmark + Odstranit záložku + + + + Name: + Název: + + + + Folder: + Složka: + + + + Save + Uložit + + + + Close + Zavřít + + + + Bookmarks In Menu + Záložky v menu + + + + Bookmarks In ToolBar + Panel záložek + + + + Unsorted Bookmarks + Nesetříděné záložky + + + + ClearPrivateData + + + Clear Recent History + Vymazat nedávnou historii + + + + Choose what you want to delete: + Vyberte co chcete smazat: + + + + Clear history + Smazat historii + + + + Clear cookies + Smazat cookies + + + + Clear cache + Vyprázdnit vyrovnávací paměť + + + + Clear icons + Smazat ikony + + + + Clear cookies from Adobe Flash Player + Smazat cookies z Adobe Flash Playeru + + + + ClickToFlash + + + Flash blocked by ClickToFlash + Zablokováno pluginem ClickToFlash + + + + Add %1 to whitelist + Přidat %1 na bílou listinu + + + + CookieManager + + + Cookies + Cookies - QupZilla + Cookies + + + + Find: + Najít: + + + + These cookies are stored on your computer: + Tyto cookies jsou uloženy v počítači: + + + + Server + Server + + + + Cookie name + Název cookies + + + + Name: + Název: + + + + Value: + Obsah: + + + + Server: + Server: + + + + Path: + Cesta: + + + + Secure: + Zasláno pro: + + + + Expiration: + Platnost do: + + + + + + + + + + + + + + + <cookie not selected> + <nebylo zvoleno cookie> + + + + Remove all cookies + Odebrat všechny cookies + + + + + Remove cookie + Odebrat cookie + + + + Del + Del + + + + Search + Vyhledávání + + + + Confirmation + Potvrzení + + + + Are you sure to delete all cookies on your computer? + Opravdu chcete vymazat všechny cookies z počítače? + + + + Remove cookies + Odebrat cookies + + + + Secure only + Zabezpečené připojení + + + + All connections + Libovolný typ připojení + + + + Session cookie + konce relace + + + + DownloadItem + + + Form + Form + + + + A Clockwork Orange.avi + + + + + Remaining 26 minutes - 339MB of 693 MB (350kB/s) + + + + + Remaining time unavailable + Neznámý zbývající čas + + + + Done - %1 + Hotovo - %1 + + + + + Cancelled + Zrušeno + + + + few seconds + několik sekund + + + + seconds + sekund + + + + minutes + minut + + + + hours + hodin + + + + Remaining %1 - %2 of %3 (%4) + Zbývá %1 - %2 z %3 (%4) + + + + Cancelled - %1 + Zrušeno - %1 + + + + Open File + Otevřít soubor + + + + Open Folder + Otevřít složku + + + + Cancel downloading + Zrušit stahování + + + + Clear + Vyčistit + + + + Error + Chyba + + + + Error: Cannot write to file! + Chyba: Nelze zapisovat do souboru! + + + + Error: + Chyba: + + + + DownloadManager + + + %1% of %2 files (%3) %4 remaining + %1% z %2 souborů (%3) %4 zbyvá + + + + % - Download Manager + % - Správce stahování + + + + Save file as... + Uložit soubor jako... + + + + Warning + Varování + + + + Are you sure to quit? All uncompleted downloads will be cancelled! + Jste si jistý že chcete skončit? Všechna nedokončená stahování budou zrušena! + + + + NoNameDownload + BezNazvu + + + + + + Download Manager + Správce stahování + + + + Clear + Vyčistit + + + + DownloadOptionsDialog + + + Opening + Otevírám + + + + which is a: + což je: + + + + from: + z: + + + + You have chosen to open + Zvolili jste otevřít + + + + <b>What should QupZilla do with this file?</b> + <b>Co má QupZilla udělat s tímto souborem?</b> + + + + Open... + Otevřít... + + + + Save File + Uložit soubor + + + + HistoryManager + + + History + Historie + + + + Search in history: + Vyhledávat v historii: + + + + Title + Titulek + + + + Url + Adresa + + + + Delete + Odstranit + + + + Del + Del + + + + Clear All History + Vymazat celou historii + + + + Search + Vyhledávání + + + + New Tab + Nový panel + + + + Open link in actual tab + Otevřít odkaz v aktuálním panelu + + + + Open link in new tab + Otevřít odkaz v novém panelu + + + + Close + Zavřít + + + + Confirmation + Potvrzení + + + + Are you sure to delete all history? + Opravdu chcete vymazat celou historii? + + + + HistoryModel + + + Failed loading page + Chyba při načítání stránky + + + + + No Named Page + Bezejmenná stránka + + + + LocationBar + + + Show informations about this page + Zobrazit informace o stránce + + + + Add RSS from this page... + Přidat RSS kanál ... + + + + + Bookmark this Page + Přidat stránku do záložek + + + + Enter URL address or search on Google.com + Zadejte internetovou adresu nebo vyhledávejte na Google.com + + + + Add RSS channel with title ' + Přidat kanál s titulkem ' + + + + Read RSS news + Číst RSS novinky + + + + Loading... + Načítám... + + + + Done + Hotovo + + + + + Edit this bookmark + Upravit záložku + + + + .co.uk + .cz + Append domain name on ALT key = Should be different for every country + .cz + + + + LocationCompleter + + + Search %1 on Google.com +.......... + Hledat %1 na Google.com +.......... + + + + MainApplication + + + Last session crashed + Poslední relace spadla + + + + <b>QupZilla crashed :-(</b><br/>Oops, last session of QupZilla ends with its crash. We are very sorry. Would you try to restore saved state? + <b>QupZilla spadla :-(</b><br/>Oops, poslední relace QupZilly skončila jejím pádem. Velice se omlouváme. Přejete si obnovit uložený stav? + + + + NetworkManager + + + SSL Certificate Error! + Chyba zabezpečení! + + + + The page you trying to access has following errors in SSL Certificate: + Stránka kterou se snažíte navštívit zaslala SSL Certifikát s těmito chybami: + + + + <b>Organization: </b> + <b>Organizace: </b> + + + + <b>Domain Name: </b> + <b>Doména: </b> + + + + <b>Expiration Date: </b> + <b>Vyprší: </b> + + + + <b>Error: </b> + <b>Chyba: </b> + + + + Would you like to make exception for this certificate? + Chcete udělit vyjímku tomuto certifikátu? + + + + SSL Certificate Error + Chyba zabezpečení + + + + Authorization required + Vyžadována autorizace + + + + Username: + Uživatelské jméno: + + + + Password: + Heslo: + + + + Save username and password on this site + Uložit jméno a heslo pro tuto stránku + + + + A username and password are being requested by %1. The site says: "%2" + Server %1 požaduje vaše uživatelské jméno a heslo s komentářem: "%2" + + + + PluginsList + + + Form + Form + + + + Application Extensions + Doplnky aplikace + + + + Allow Application Extensions to be loaded + Povolit načítání doplňků aplikace + + + + Settings + Nastavení + + + + Load Plugins + Načíst doplňky + + + + WebKit Plugins + WebKit Pluginy + + + + <b>Click To Flash Plugin</b> + <b>Click To Flash Plugin</b> + + + + Click To Flash is a plugin which blocks auto loading of Flash content at page. You can always load it manually by clicking on the Flash play icon. + Click To Flash je plugin který blokuje automatické načítání Flash animací. Avšak vždy je můžete manuálně načíst kliknutím na ikonku Flashe. + + + + Whitelist + Bílá listina + + + + Add + Přidat + + + + Remove + Odstranit + + + + Allow Click To Flash + Povolit Click To Flash + + + + Add site to whitelist + Přidat stránku na bílou listinu + + + + Server without http:// (ex. youtube.com) + Server bez http:// (např. youtube.com) + + + + Preferences + + + Preferences + Předvolby + + + + General + Obecné + + + + 0 + 0 + + + + + 1 + 1 + + + + 2 + 2 + + + + 3 + 3 + + + + Downloads + Stahování + + + + 4 + 4 + + + + 5 + 5 + + + + 6 + 6 + + + + Plugins + Doplňky + + + + 7 + 7 + + + + 8 + 8 + + + + After launch: + Po spuštění: + + + + Open blank page + Otevřít prázdnou stránku + + + + + Open homepage + Otevřít domovskou stránku + + + + Restore session + Obnovit relaci + + + + Homepage: + Domovská stránka: + + + + On new tab: + Při otevření nového panelu: + + + + Open blank tab + Otevřít prázdný panel + + + + Open other page... + Otevřít jinou stránku... + + + + + Use actual + Použít aktuální + + + + <b>Navigation ToolBar</b> + <b>Navigační panel</b> + + + + <b>Background<b/> + <b>Pozadí</b> + + + + Use background image + Použít obrázek na pozadí + + + + Use transparent background + Použít průhledné pozadí + + + + Choose image... + Vyberte obrázek... + + + + Reset default + Obnovit původní + + + + Maximum + Maximálně + + + + 50 MB + 50 MB + + + + <b>Downloads</b> + <b>Stahování</b> + + + + QupZilla + QupZilla + + + + <b>Network Cache</b> + <b>Síťová cache</b> + + + + Allow storing network cache on disk + Povolit ukládání cache na disk + + + + <b>Cookies</b> + <b>Cookies</b> + + + + <b>Web storage</b> + <b>Webové úložiště</b> + + + + <b>Address Bar behaviour</b> + <b>Chování adresního řádku</b> + + + + <b>Language</b> + <b>Jazyk</b> + + + + <b>General</b> + <b>Hlavní</b> + + + + Startup profile: + Startovní profil: + + + + default + default + + + + Create New + Nový profil + + + + Delete + Odstranit + + + + Window + Okno prohlížeče + + + + Show StatusBar on start + Zobrazit StatusBar při startu + + + + <b>Profiles</b> + <b>Profily</b> + + + + Show Bookmarks ToolBar on start + Zobrazit panel záložek při startu + + + + Show Navigation ToolBar on start + Zobrazit navigační panel při startu + + + + Show Home button + Zobrazit tlačítko Domů + + + + Show Back / Forward buttons + Zobrazit tlačítka Zpět / Vpřed + + + + <b>Browser Window</b> + <b>Okno prohlížeče</b> + + + + Tabs + Panely + + + + <b>Launching</b> + <b>Spouštění</b> + + + + This is text color used in Menu + Toto je text používaný v menu + + + + Menu text color + Barva menu textu + + + + <b>Tabs behavior</b> + <b>Chování panelů</b> + + + + Make tabs movable + Přesouvat panely přetažením + + + + Hide close button if there is only one tab + Skrýt zavírací tlačítko při jediném panelu + + + + Hide tabs when if there is only one tab + Skrýt seznam panelů při jediném panelu + + + + Activate last tab when closing active tab + Aktivovat poslední panel při zavírání aktuálního + + + + <b>WebKit</b> + <b>WebKit</b> + + + + Block PopUp windows + Blokovat vyskakovací okna + + + + Allow DNS Prefetch + Povolit DNS Prefetch + + + + JavaScript can access clipboard + Povolit JavaScriptu přístup do schránky + + + + Include links in focus chain + Označovat odkazy tabulátorem + + + + Zoom text only + Přibližovat pouze text + + + + Print element background + Tisknout pozadí objektů + + + + Wheel scrolls + Kolečko posouvá + + + + lines + řádků + + + + Automatically close download dialog after finish + Automaticky zavírat dialog po skončení stahování + + + + Ask everytime for download location + U každého souboru se dotázat kam ho uložit + + + + Use defined location: + Uložit všechny soubory do: + + + + ... + ... + + + + Browsing + Prohlížení + + + + Load images + Nahrát obrázky + + + + Allow JAVA + Povolit JAVA + + + + Allow JavaScript + Povolit JavaScript + + + + Allow Plugins (Flash plugin) + Povolit pluginy (Flash plugin) + + + + Maximum pages in cache: + Maximum stránek v cache: + + + + Password Manager + Správce hesel + + + + <b>AutoFill options</b> + <b>Možnosti doplňování</b> + + + + Allow saving passwords from sites + Povolit ukládání hesel ze stránek + + + + Privacy + Soukromí + + + + Filter Tracking Cookies + Filtrovat sledovací cookies + + + + Allow storing of cookies + Povolit přijímání cookies + + + + Delete cookies on close + Vymazat cookies při zavření prohlížeče + + + + Match domain exactly + Vyžadovat přesnou shodu domény + + + + <b>Warning:</b> Match domain exactly and Filter Tracking Cookies options can lead to deny some cookies from sites. If you have problems with cookies, try to disable this options first! + <b>Upozornění:</b> Možnosti vyžadovat přesnou shodu domény a filtrovat sledovací cookies mohou vést k odmítnutí některých cookies. Pokud máte problémy s cookies, zkuste nejdříve tyto možnosti zakázat! + + + + Cookies Manager + Správce cookies + + + + Allow storing web icons + Povolit ukládání ikon + + + + Allow saving history + Povolit ukládání historie + + + + Delete history on close + Vymazat historii při zavření prohlížeče + + + + Other + Ostatní + + + + Select all text by double clicking in address bar + Select all text by clicking at address bar + Označit vše při dvojitém kliknutí do adresního řádku + + + + Add .com domain by pressing CTRL key + Přidat .com doménu stisknutím CTRL klávesy + + + + Add .co.uk domain by pressing ALT key + Přidat .cz doménu stísknutím ALT klávesy + + + + Available translations: + Dostupné překlady: + + + + In order to change language, you must restart browser. + Ke změně jazyku je nutný restart prohlížeče. + + + + Choose download location... + Vyberte složku pro stahování... + + + + Choose background location... + + + + + QupZilla + + + File + Soubor + + + + Open File + Otevřít soubor + + + + Edit + Úpravy + + + + Tools + Nástroje + + + + Help + Nápověda + + + + View + Zobrazení + + + + Bookmarks + Záložky + + + + History + Historie + + + + Save Page As... + Uložit stránku jako... + + + + Print + Tisk + + + + Quit + Konec + + + + New Tab + Nový panel + + + + Undo + Zpět + + + + Redo + Vpřed + + + + Preferences + Předvolby + + + + About QupZilla + O QupZille + + + + About Qt + O Qt + + + + Close Tab + Zavřít panel + + + + Find + Najít + + + + Cut + Vyjmout + + + + IP Address of current page + IP Adresa aktuální stránky + + + + Copy + Kopírovat + + + + Paste + Vložit + + + + Delete + Odstranit + + + + Select All + Vybrat vše + + + + Navigation Toolbar + Navigační lišta + + + + Status Bar + Status bar + + + + + Stop + Zastavit + + + + + Reload + Obnovit + + + + Zoom In + Zoom + + + + + Zoom Out + Zoom - + + + + Reset + Původní + + + + Page Source + Zdrojový kód stránky + + + + Fullscreen + Celá obrazovka + + + + + Back + Zpět + + + + + Forward + Vpřed + + + + + Home + Domů + + + + Show All History + Zobrazit celou historii + + + + Bookmark This Page + Přidat stránku do záložek + + + + Bookmark All Tabs + Přidat všechny panely do záložek + + + + Organize Bookmarks + Organizovat záložky + + + + New Window + Nové okno + + + + Close Window + Zavřít okno + + + + Open Location + Otevřít adresu + + + + Send Link... + Poslat odkaz... + + + + Report Bug + Nahlásit bug + + + + Web Search + Hledání na webu + + + + Page Info + Informace o stránce + + + + Download Manager + Správce stahování + + + + Clear Recent History + Vymazat nedávnou historii + + + + Private Browsing + Soukromé prohlížení + + + + RSS Reader + RSS čtečka + + + + Start Private Browsing + Spustit anonymní prohlížení + + + + Cookies Manager + Správce cookies + + + + Bookmarks Toolbar + Panel záložek + + + + Navigation + Navigace + + + + Main Menu + Hlavní menu + + + + Exit Fullscreen + Zrušit celou obrazovku + + + + Private Browsing Enabled + Soukromé prohlížení zapnuto + + + + Flash Plugin Enabled + Flash Plugin zapnut + + + + Menu Bar + Menu + + + + Bookmarks In ToolBar + Bookmarks In Toolbar + Panel záložek + + + + + Empty + Prázdný + + + + New tab + Nový panel + + + + Web Inspector + Web Inspektor + + + + Open file... + Otevřít soubor... + + + + Are you sure you want to turn on private browsing? + Jste si jistý že chcete zapnout soukromé prohlížení? + + + + When private browsing is turned on, some actions concerning your privacy will be disabled: + Se zapnutým soukromým prohlížením jsou některé akce týkající se soukromí vypnuty: + + + + Webpages are not added to the history. + Stránky nejsou přidávány do historie. + + + + New cookies are not stored, but current cookies can be accessed. + Nové cookies nejsou přijímány, ale současné cookies jsou zasílány. + + + + Your session won't be stored. + Vaše relace nebude uložena. + + + + Until you close the window, you can still click the Back and Forward buttons to return to the webpages you have opened. + Než zavřete prohlížeč, stále můžete použít tlačítka Zpět a Vpřed k vrácení se na stránky které jste otevřeli. + + + + + There are still open tabs + Stále jsou otevřeny panely + + + + + There are still %1 open tabs and your session won't be stored. Are you sure to quit? + Ještě jsou otevřeny %1 panely a Vaše relace nebude uložena. Opravdu chcete skončit? + + + + RSSManager + + + RSS Reader + RSS čtečka + + + + Empty + Prázdný + + + + You don't have any RSS Feeds.<br/> +Please add some with RSS icon in navigation bar on site which offers feeds. + Nemáte žádný RSS kanál.<br/> +Prosím přidejte si nějaký kliknutím na RSS ikonku v navigačním řádku. + + + + Reload + Obnovit + + + + Edit feed + Upravit kanál + + + + Delete feed + Smazat kanál + + + + News + Novinky + + + + + Loading... + Načítám... + + + + Fill title and URL of a feed: + Vyplňte titulek a adresu kanálu: + + + + Feed title: + Titulek kanálu: + + + + Feed URL: + Adresa kanálu: + + + + Edit RSS Feed + Upravit kanál + + + + Open link in actual tab + Otevřít odkaz v aktuálním panelu + + + + Open link in new tab + Otevřít odkaz v novém panelu + + + + Close + Zavřít + + + + + New Tab + Nový panel + + + + Error in fetching feed + Chyba při stahování kanálu + + + + RSS feed added + RSS kanál přidán + + + + RSS with title '%1' has been successfuly added. + RSS kanál s titulkem '%1' byl úspěšně přidán. + + + + RSS feed duplicated + Duplikovaný kanál + + + + You already have this feed. + Tento kanál již odebíráte. + + + + SearchToolBar + + + + Search + Vyhledávání + + + + Highlight occurrences + Zvýraznit + + + + Next + Další + + + + Previous + Předchozí + + + + Case sensitive + Rozlišovat velikost + + + + Find: + Najít: + + + + No results found. + Nic nenalezeno. + + + + SiteInfo + + + Site Info + Informace o stránce + + + + Tag + Tag + + + + Value + Hodnota + + + + Image + Obrázek + + + + Image address + Adresa obrázku + + + + Site address: + Site address + Adresa stránky: + + + + Site name: + Jméno stránky: + + + + Meta tags of site: + Meta tagy na stránce: + + + + Images on site: + Obrázky na stránce: + + + + No Named Page + Bezejmenná stránka + + + + SiteInfoWidget + + + Form + Form + + + + More... + Více... + + + + Your connection to this site is <b>secured</b>. + Připojení k této stránce je <b>zabezpečené</b>. + + + + Your connection to this site is <b>unsecured</b>. + Připojení k této stránce je <b>nezabezpečené</b>. + + + + This is Your <b>%1.</b> visit of this site. + Toto je Vaše <b>%1.</b> návštěva této stránky. + + + + first + první + + + + second + druhá + + + + third + třetí + + + + This is Your <b>%1</b> visit of this site. + Toto je Vaše <b>%1</b> návštěva této stránky. + + + + You have <b>never</b> visited this site before. + <b>Nikdy</b> dříve jste nenavštívili tuto stránku. + + + + SourceViewer + + + Source of + Zdrojový kód + + + + TabBar + + + + New tab + Nový panel + + + + Back + Zpět + + + + Forward + Vpřed + + + + Stop Tab + Zastavit panel + + + + Reload Tab + Obnovit panel + + + + + Reload All Tabs + Close other tabs + Obnovit všechny panely + + + + Bookmark This Tab + Přidat panel do záložek + + + + + Bookmark All Tabs + Přidat všechny panely do záložek + + + + + Restore Closed Tab + Obnovit zavřený panel + + + + Close Other Tabs + Zavřít ostatní panely + + + + Close + Zavřít + + + + TabWidget + + + Show list of opened tabs + Zobrazit seznam otevřených panelů + + + + Add Tab + Nový panel + + + + Loading... + Načítám... + + + + + No Named Page + Bezejmenná stránka + + + + Actually You have %1 opened tabs + Dohromady máte otevřeno %1 panelů + + + + New tab + Nový panel + + + + Updater + + + Go to download page + Přejít ke stažení + + + + Go to QupZilla website + Přejít na stránku QupZilly + + + + Hide notification + Skrýt upozornění + + + + QupZilla is checking for updates + QupZilla kontroluje aktualizace + + + + QupZilla found a new version! + QupZilla nalezla novou verzi! + + + + New version is available + Nová verze je dostupná + + + + New version of QupZilla %1 is available! + Nová verze QupZilly %1 je dostupná! + + + + + QupZilla Update + QupZilla Update + + + + WebPage + + + Confirmation + Potvrzení + + + + To show this page, QupZilla must resend request witch do it again (like searching on making an shoping, witch has been already done. + Pro zobrazení této stránky musí QupZilla znovu odeslat požadavek, který zopakuje akci (jako např. hledání nebo potvrzení objednávky), která byla provedena již dříve. + + + + Server refused the connection + Server odmítl spojení + + + + Server closed the connection + Serve ukončil spojení + + + + Server not found + Server nenalezen + + + + Connection timed out + Spojení vypršelo + + + + Untrusted connection + Nedůvěryhodné spojení + + + + Unknown error + Neznámá chyba + + + + Error code %1 + Chybový kód %1 + + + + Failed loading page + Chyba při načítání stránky + + + + QupZilla can't load page at %1. + QupZilla nemůže načíst stránku %1. + + + + Check the address for typing errors such as <b>ww.</b>example.com instead of <b>www.</b>example.com + Zkontrolujte, zda je adresa napsána správně a neobsahuje chyby jako <b>ww.</b>server.cz místo <b>www</b>.server.cz + + + + If you are unable to load any pages, check your computer's network connection. + Pokud se vám nezobrazují ani ostatní stránky, zkontrolujte síťové připojení svého počítače. + + + + If your computer or network is protected by a firewall or proxy, make sure that QupZilla is permitted to access the Web. + Pokud je váš počítač chráněn firewallem a nebo proxy serverem, zkontrolujte, zda má QupZilla přístup na Internet. + + + + Try Again + Zkusit znovu + + + + WebView + + + + Loading... + Načítám... + + + + + No Named Page + Bezejmenná stránka + + + + Done + Hotovo + + + + + + New tab + Nový panel + + + + Open link in new window + Otevřít odkaz v novém okně + + + + Open link in new tab + Otevřít odkaz v novém panelu + + + + Bookmark link + Přidat odkaz do záložek + + + + Save link as... + Uložit odkaz jako... + + + + Send link... + Odeslat odkaz... + + + + Copy link address + Kopírovat adresu odkazu + + + + Show image + Zobrazit obrázek + + + + Copy image + Kopírovat obrázek + + + + Copy image address + Coyp image address + Kopírovat adresu obrázku + + + + Save image as... + Uložit obrázek jako... + + + + Send image... + Odeslat obrázek... + + + + Back + Zpět + + + + Forward + Vpřed + + + + Reload + Obnovit + + + + Stop + Zastavit + + + + Bookmark page + Přidat stránku do záložek + + + + Save page as... + Uložit stránku jako... + + + + Send page... + Odeslat stránku... + + + + Select all + Vybrat vše + + + + Show source code + Zobrazit zdrojový kód + + + + Show info about site + Zobrazit informace o stránce + + + + Show Web Inspector + Zobrazit Web Inspektor + + + + Search + Hledat + + + + ... on Google + ... na Googlu + + + diff --git a/translations/sk_SK.ts b/translations/sk_SK.ts new file mode 100644 index 000000000..422483e8b --- /dev/null +++ b/translations/sk_SK.ts @@ -0,0 +1,2572 @@ + + + + + AboutDialog + + + About QupZilla + O QupZille + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Ubuntu'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Ubuntu'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + Authors + Autori + + + + + Authors and Contributors + Autori a prispievatelia + + + + + < About QupZilla + < O QupZille + + + + <p><b>Application version %1</b><br/> + <p><b>Verzia aplikácie %1</b><br/> + + + + <b>WebKit version %1</b></p> + <b>Verzia WebKitu %1</b></p> + + + + <p>&copy; %1 %2<br/>All rights reserved.<br/> + <p>&copy; %1 %2<br/>Všetky práva vyhradené.<br/> + + + + Build time: %1 </p> + Čas vytvorenia: %1 </p> + + + + <p><b>Main developers:</b><br/>%1 &lt;%2&gt;</p> + <p><b>Hlavní vývojári:</b><br/>%1 &lt;%2&gt;</p> + + + + <p><b>Other contributors:</b><br/>%1</p> + <p><b>Ostatní prispievatelia:</b><br/>%1</p> + + + + <p><b>Thanks to:</b><br/>%1</p> + <p><b>Poďakovanie:</b><br/>%1</p> + + + + AutoFillManager + + + Password Manager + Správca hesiel + + + + Passwords + Heslá + + + + + Server + Server + + + + Password + Heslo + + + + + Remove + Odstrániť + + + + Edit + Upraviť + + + + + Remove All + Odstrániť všetko + + + + Exceptions + Výnimky + + + + Confirmation + Potvrdenie + + + + Are you sure to delete all passwords on your computer? + Ste si istý, že chcete vymazať všetky heslá vo Vašom počítači? + + + + Edit password + Upraviť heslo + + + + Change password: + Zmeniť heslo: + + + + AutoFillModel + + + <b>Would you like to save this password?</b><br>To show all stored passwords open the Password Manager panel in preferences. + <b>Prajete si uložiť toto heslo?</b><br>Na zobrazenie všetkých uložených hesiel si otvorte panel Správca hesiel v predvoľbách. + + + + Never for this site + Nikdy pre túto stránku + + + + Not now + Nie teraz + + + + BookmarksManager + + + Bookmarks + Záložky + + + + Title + Nadpis + + + + Url + Adresa + + + + Delete + Odstrániť + + + + Del + Del + + + + Add Folder + Pridať zložku + + + + Add new folder + Pridať novú zložku + + + + Choose name for new bookmark folder: + Zvoľte meno pre novú zložku: + + + + New Tab + Nový panel + + + + + + + + + + + Bookmarks In Menu + Záložky v menu + + + + + + + + + + + Bookmarks In ToolBar + Panel záložiek + + + + Open link in actual tab + Otvoriť odkaz v aktuálnom panely + + + + Open link in new tab + Otvoriť odkaz na novom panely + + + + Move bookmark to folder + Presunúť záložku do zložky + + + + + + + + Unsorted Bookmarks + Netriedené záložky + + + + Close + Zavrieť + + + + <b>Warning: </b>You already have this page bookmarked! + <b>Upozornenie: </b>Túto stránku máte už v záložkách! + + + + Choose name and location of bookmark. + Zvoľte meno a umiestnenie záložky. + + + + Add New Bookmark + Pridať záložku + + + + Choose folder for bookmarks: + Zvoľte zložku pre záložku: + + + + Bookmark All Tabs + Pridať všetky panely do záložiek + + + + BookmarksToolbar + + + Bookmarks + Záložky + + + + Bookmark Current Page + Pridať stránku do záložiek + + + + Bookmark All Tabs + Pridať všetky panely do záložiek + + + + Organize Bookmarks + Organizovať záložky + + + + Reload Toolbar + Obnoviť panel + + + + Hide Most Visited + Skryť Najnavštevovanejšie + + + + Show Most Visited + Zobraziť Najnavštevovanejšie + + + + Hide Toolbar + Skryť panel + + + + Most visited + Najnavštevovanejšie + + + + Sites You visited the most + Najnavštívenejšie stránky + + + + BookmarksWidget + + + Edit This Bookmark + Upraviť túto záložku + + + + Remove Bookmark + Odstrániť záložku + + + + Name: + Názov: + + + + Folder: + Zložka: + + + + Save + Uložiť + + + + Close + Zavrieť + + + + Bookmarks In Menu + Záložky v menu + + + + Bookmarks In ToolBar + Panel záložiek + + + + Unsorted Bookmarks + Nezotriedené záložky + + + + ClearPrivateData + + + Clear Recent History + Vymazať nedávnu históriu + + + + Choose what you want to delete: + Vyberte, čo chcete zmazať: + + + + Clear history + Zmazať históriu + + + + Clear cookies + Zmazať cookies + + + + Clear cache + Zmazať vyrovnávaciu pamäť + + + + Clear icons + Zmazať ikony + + + + Clear cookies from Adobe Flash Player + Zmazať cookies z Adobe Flash Playeru + + + + ClickToFlash + + + Flash blocked by ClickToFlash + + + + + Add %1 to whitelist + + + + + CookieManager + + + Cookies + Cookies + + + + Find: + Hľadať: + + + + These cookies are stored on your computer: + Tieto cookies sú uložené v počítači: + + + + Server + Server + + + + Cookie name + Názov cookies + + + + Name: + Názov: + + + + Value: + Hodnota: + + + + Server: + Server: + + + + Path: + Cesta: + + + + Secure: + Zasielane pre: + + + + Expiration: + Platnosť do: + + + + + + + + + + + + + + + <cookie not selected> + <nebolo zvolene cookie> + + + + Remove all cookies + Odstrániť všetky cookies + + + + + Remove cookie + Odstrániť cookie + + + + Del + Del + + + + Search + Hľadať + + + + Confirmation + Potvrdenie + + + + Are you sure to delete all cookies on your computer? + Skutočne chcete vymazať všetky cookies z počítača? + + + + Remove cookies + Odstrániť cookies + + + + Secure only + Zabezpečené pripojenie + + + + All connections + Všetky pripojenia + + + + Session cookie + Konca relácie + + + + DownloadItem + + + Form + Form + + + + A Clockwork Orange.avi + + + + + Remaining 26 minutes - 339MB of 693 MB (350kB/s) + + + + + Remaining time unavailable + + + + + Done - %1 + + + + + + Cancelled + + + + + few seconds + + + + + seconds + sekúnd + + + + minutes + minút + + + + hours + hodín + + + + Remaining %1 - %2 of %3 (%4) + + + + + Cancelled - %1 + + + + + Open File + Otvoriť súbor + + + + Open Folder + + + + + Cancel downloading + + + + + Clear + + + + + Error + + + + + Error: Cannot write to file! + Chyba: Nejde zapisovať do súboru! + + + + Error: + Chyba: + + + + DownloadManager + + + %1% of %2 files (%3) %4 remaining + + + + + % - Download Manager + + + + + Save file as... + Uložiť súbor ako... + + + + Warning + + + + + Are you sure to quit? All uncompleted downloads will be cancelled! + + + + + NoNameDownload + BezNázvu + + + + + + Download Manager + + + + + Clear + + + + + DownloadOptionsDialog + + + Opening + Otváram + + + + which is a: + čo je: + + + + from: + z: + + + + You have chosen to open + Zvolili ste si otvoriť + + + + <b>What should QupZilla do with this file?</b> + <b>Čo má QupZilla urobiť s týmto súborom?</b> + + + + Open... + Otvoriť... + + + + Save File + Uložiť súbor + + + + HistoryManager + + + History + História + + + + Search in history: + Hľadať v histórii: + + + + Title + Názov + + + + Url + Adresa + + + + Delete + Vymazať + + + + Del + Del + + + + Clear All History + Vymazať celú históriu + + + + Search + Hľadať + + + + New Tab + Nový panel + + + + Open link in actual tab + Otvoriť odkaz v aktuálnom panely + + + + Open link in new tab + Otvoriť odkaz na novom panely + + + + Close + Zavrieť + + + + Confirmation + Potvrdenie + + + + Are you sure to delete all history? + Skutočne chcete vymazať celú históriu? + + + + HistoryModel + + + Failed loading page + Chyba pri načítaní stránky + + + + + No Named Page + Stránka bez mena + + + + LocationBar + + + Show informations about this page + Zobraziť informácie o tejto stránke + + + + Add RSS from this page... + Pridať RSS kanál... + + + + + Bookmark this Page + Pridať stránku do záložiek + + + + Enter URL address or search on Google.com + Zadajte URL adresu alebo vyhľadajte na Google.com + + + + Add RSS channel with title ' + Pridať RSS kanál s názvom + + + + Read RSS news + Čítať RSS novinky + + + + Loading... + Nahrávam... + + + + Done + Hotovo + + + + + Edit this bookmark + Upraviť záložku + + + + .co.uk + Append domain name on ALT key = Should be different for every country + .sk + + + + LocationCompleter + + + Search %1 on Google.com +.......... + Vyhľadajte %1 na Google.com +.......... + + + + MainApplication + + + Last session crashed + Posledná relácia spadla + + + + <b>QupZilla crashed :-(</b><br/>Oops, last session of QupZilla ends with its crash. We are very sorry. Would you try to restore saved state? + <b>QupZilla spadla :-(</b><br/>Oops, posledná relácia QupZilly skončila chybou. Prepáčte. Chcete obnoviť uložený stav? + + + + NetworkManager + + + SSL Certificate Error! + Chyba zabezpečenia! + + + + The page you trying to access has following errors in SSL Certificate: + Stránka na ktorú sa pokušáte pripojiť obsahuje následujúce chyby v SSL Certifikáte: + + + + <b>Organization: </b> + <b>Organizácia: </b> + + + + <b>Domain Name: </b> + <b>Doména: </b> + + + + <b>Expiration Date: </b> + <b>Platnosť do: </b> + + + + <b>Error: </b> + <b>Chyba: </b> + + + + Would you like to make exception for this certificate? + Chcete urobiť vynímku pre tento certifikát? + + + + SSL Certificate Error + Chyba zabezpečenia + + + + Authorization required + Požadovaná autorizácia + + + + Username: + Uživateľské meno: + + + + Password: + Heslo: + + + + Save username and password on this site + Uložiť meno a heslo pre túto sieť + + + + A username and password are being requested by %1. The site says: "%2" + Server %1 požaduje vaše uživateľské meno a heslo s komentárom: "%2" + + + + PluginsList + + + Form + Form + + + + Application Extensions + + + + + Allow Application Extensions to be loaded + + + + + Settings + Nastavenia + + + + Load Plugins + Načítať doplnky + + + + WebKit Plugins + + + + + <b>Click To Flash Plugin</b> + + + + + Click To Flash is a plugin which blocks auto loading of Flash content at page. You can always load it manually by clicking on the Flash play icon. + + + + + Whitelist + + + + + Add + + + + + Remove + Odstrániť + + + + Allow Click To Flash + + + + + Add site to whitelist + + + + + Server without http:// (ex. youtube.com) + + + + + Preferences + + + Preferences + Predvoľby + + + + General + Hlavné + + + + 0 + 0 + + + + + 1 + 1 + + + + 2 + 2 + + + + 3 + 3 + + + + Downloads + Sťahovanie + + + + 4 + 4 + + + + 5 + 5 + + + + 6 + 6 + + + + Plugins + Doplnky + + + + 7 + 7 + + + + 8 + 8 + + + + After launch: + Po spustení: + + + + Open blank page + Otvoriť prádznu stránku + + + + + Open homepage + Otvoriť domovskú stránku + + + + Restore session + Obnoviť reláciu + + + + Homepage: + Domovská stránka: + + + + On new tab: + Pri otvorení nového panelu: + + + + Open blank tab + Otvoriť prádzny panel + + + + Open other page... + Otvoriť inú stránku... + + + + <b>Profiles</b> + <b>Profily</b> + + + + Startup profile: + Štartovný profil: + + + + default + default + + + + Create New + Nový profil + + + + Delete + Vymazať + + + + <b>Launching</b> + <b>Spustení</b> + + + + QupZilla + QupZilla + + + + <b>General</b> + <b>Hlavné</b> + + + + Window + Okno prehliadača + + + + Show StatusBar on start + Zobraziť StatusBar pri štarte + + + + Show Bookmarks ToolBar on start + Zobraziť panel záložiek pri štarte + + + + Show Navigation ToolBar on start + Zobraziť navigačný panel pri štarte + + + + <b>Navigation ToolBar</b> + <b>Navigačný panel</b> + + + + <b>Downloads</b> + <b>Sťahovanie</b> + + + + <b>Network Cache</b> + <b>Sieťová cache</b> + + + + Allow storing network cache on disk + Povoliť ukladanie sieťovej cache na disk + + + + <b>Cookies</b> + <b>Cookies</b> + + + + <b>Web storage</b> + <b>Webové úložisko</b> + + + + <b>Address Bar behaviour</b> + <b>Chovanie adresového riadku</b> + + + + <b>Language</b> + <b>Jazyk</b> + + + + Show Home button + Zobraziť tlačidlo domov + + + + Show Back / Forward buttons + Zobraziť tlačidlo Späť / Dopredu + + + + <b>Browser Window</b> + <b>Okno prehliadača</b> + + + + Tabs + Panely + + + + + Use actual + Použiť aktuálny + + + + <b>Background<b/> + <b>Pozadie<b/> + + + + Use background image + Použiť pozadie + + + + Use transparent background + Použiť priehľadné pozadie + + + + Choose image... + Zvoľte obrázok... + + + + Reset default + Obnoviť povodné + + + + <b>Tabs behavior</b> + <b>Chovanie panelov</b> + + + + Make tabs movable + Presunúť panely pretiahnutím + + + + Hide close button if there is only one tab + Skryť zavieracie tlačidlo pri jednom panely + + + + Hide tabs when if there is only one tab + Skryť zoznam panelov pri jednom panely + + + + Maximum + Maximálne + + + + 50 MB + 50 MB + + + + Automatically close download dialog after finish + Automaticky zatvárať dialóg po skončení sťahovania + + + + Ask everytime for download location + Pri každom súbore sa spýtať kde ho uložiť + + + + Use defined location: + Uložiť všetky súbory do: + + + + ... + ... + + + + Browsing + Prehliadanie + + + + Load images + Nahrať obrázky + + + + Allow JAVA + Povoliť JAVA + + + + Allow JavaScript + Povoliť JavaScript + + + + Allow Plugins (Flash plugin) + Povoliť pluginy (Flash plugin) + + + + Maximum pages in cache: + Maximum stránok v cache: + + + + Password Manager + Správca hesiel + + + + <b>AutoFill options</b> + <b>Možnosťi doplňovania</b> + + + + Allow saving passwords from sites + Povoliť ukladanie hesiel zo stránok + + + + Privacy + Súkromie + + + + This is text color used in Menu + Toto je text používaný v menu + + + + Menu text color + Farba menu textu + + + + Activate last tab when closing active tab + Aktivovať posledný panel pri zatváraní aktuálneho + + + + <b>WebKit</b> + <b>WebKit</b> + + + + Block PopUp windows + Blokovať vyskakovacie okna + + + + Allow DNS Prefetch + Povoliť DNS Prefetch + + + + JavaScript can access clipboard + Povoliť JavaScriptu prístup do schránky + + + + Include links in focus chain + Označovať odkazy tabulátorom + + + + Zoom text only + Približovať len text + + + + Print element background + Tlačiť pozadie objektu + + + + Wheel scrolls + Koliesko posúva + + + + lines + riadky + + + + Filter Tracking Cookies + Filtrovať sledovacie cookies + + + + Allow storing of cookies + Povoliť prijímanie cookies + + + + Delete cookies on close + Vymazať cookies pri zavrení prehliadača + + + + Match domain exactly + Požadovať presnú zhodu domény + + + + <b>Warning:</b> Match domain exactly and Filter Tracking Cookies options can lead to deny some cookies from sites. If you have problems with cookies, try to disable this options first! + <b>Upozornenie:</b> Možnosti požadovanie presnej zhody domény a filtrovať sledovacie cookies môžú viesť k odmietnutiu niektorých cookies zo stránok. Ak máte problémy s cookies, skuste tieto možnosti najskôr zakázať! + + + + Cookies Manager + Správca cookies + + + + Allow storing web icons + Povoliť ukládanie ikon + + + + Allow saving history + Povoliť ukladanie histórie + + + + Delete history on close + Vymazať históriu pri zavretí prehliadača + + + + Other + Ostatné + + + + Select all text by double clicking in address bar + Select all text by clicking at address bar + Označiť všetko pri dvojtom kliknutí do adresného riadku + + + + Add .com domain by pressing CTRL key + Pridať .com doménu stlačením CTRL klávesy + + + + Add .co.uk domain by pressing ALT key + Pridať .sk doménu stlačením ALT klávesy + + + + Available translations: + Dostupné preklady: + + + + In order to change language, you must restart browser. + K zmene jazyku je potrebný reštart prehliadača. + + + + Choose download location... + Vyberte zložku pre sťahovanie... + + + + Choose background location... + Zvoľte lokáciu pozadia... + + + + QupZilla + + + File + Súbor + + + + Edit + Upraviť + + + + Tools + Nástroje + + + + Help + Pomocník + + + + Open File + Otvoriť súbor + + + + View + Zobraziť + + + + Bookmarks + Záložky + + + + History + História + + + + Save Page As... + Uložiť stránku ako... + + + + Print + Tlačiť + + + + Quit + Koniec + + + + New Tab + Nový panel + + + + Undo + Späť + + + + Redo + Dopredu + + + + Preferences + Predvoľby + + + + About QupZilla + O QupZille + + + + About Qt + O Qt + + + + Close Tab + Zavriet panel + + + + Find + Hľadať + + + + IP Address of current page + IP Adresa aktuálnej stránky + + + + Cut + Vystrihnúť + + + + Copy + Kopírovať + + + + Paste + Prilepiť + + + + Delete + Vymazať + + + + Select All + Vybrať všetko + + + + Navigation Toolbar + Navigačná lišta + + + + Status Bar + Status bar + + + + + Stop + Zastaviť + + + + + Reload + Obnoviť + + + + Zoom In + Priblížiť + + + + Zoom Out + Oddialiť + + + + Reset + Resetovať + + + + Page Source + Zdrojový kód stránky + + + + Fullscreen + Celá obrazovka + + + + + Back + Späť + + + + + Forward + Dopredu + + + + + Home + Domov + + + + Show All History + Zobraziť celú hstóriu + + + + Bookmark This Page + Pridať stránku do záložiek + + + + Bookmark All Tabs + Pridať všetky panely do záložiek + + + + Organize Bookmarks + Organizovať záložky + + + + New Window + Nové okno + + + + Close Window + Zavrieť okno + + + + Open Location + Otvoriť adresu + + + + Send Link... + Poslať odkaz... + + + + Report Bug + Nahlásiť chybu + + + + Web Search + Hladať na webu + + + + Page Info + Informácie o stránke + + + + Download Manager + + + + + Clear Recent History + Vymazať nedávnu históriu + + + + Private Browsing + Súkromné prehliadanie + + + + RSS Reader + RSS čítač + + + + Start Private Browsing + Spustiť anonymné prehliadanie + + + + Cookies Manager + Správca cookies + + + + Bookmarks Toolbar + Panel záložiek + + + + Navigation + Navigácia + + + + Main Menu + Hlavné menu + + + + Exit Fullscreen + Ukončiť režím Fullscreen + + + + Private Browsing Enabled + Súkromné prehliadanie je zapnuté + + + + Flash Plugin Enabled + Flash Plugin zapnutý + + + + Menu Bar + Menu + + + + Bookmarks In ToolBar + Panel záložiek + + + + + Empty + Prázdny + + + + New tab + Nový panel + + + + Web Inspector + Web inšpektor + + + + Open file... + Otvoriť súbor... + + + + Are you sure you want to turn on private browsing? + Ste si istý, že chcete zapnúť súkromné prehliadanie? + + + + When private browsing is turned on, some actions concerning your privacy will be disabled: + So zapnutým súkromným prehliadaním sú niektoré akcie týkajúce sa súkromia vypnuté: + + + + Webpages are not added to the history. + Stránky nie sú pridávané do histórie. + + + + New cookies are not stored, but current cookies can be accessed. + Nové cookies nie sú prijímané, ale súčasné cookies sú zasielané. + + + + Your session won't be stored. + Vaša relácia nebude uložená. + + + + Until you close the window, you can still click the Back and Forward buttons to return to the webpages you have opened. + Dokiaľ nezavriete prehliadač, tak stále môžete používať tlačidla Späť a Dopredu k vráteniu sa na stránky, ktoré ste mali otvorené. + + + + + There are still open tabs + Stále sú otvorené panely + + + + + There are still %1 open tabs and your session won't be stored. Are you sure to quit? + Stále sú otvorené %1 panely a Vaša relácia nebude uložená. Skutočne chcete skončiť? + + + + RSSManager + + + RSS Reader + RSS čítačka + + + + Empty + Prázdny + + + + You don't have any RSS Feeds.<br/> +Please add some with RSS icon in navigation bar on site which offers feeds. + Nemáte žiadny RSS kanál.<br/> +Prosím pridajte si nejaký kliknutím na RSS ikonku v navigačnom riadku. + + + + Reload + Obnoviť + + + + Edit feed + Upraviť kanál + + + + Delete feed + Zmazať kanál + + + + News + Novinky + + + + + Loading... + Nahrávam... + + + + Fill title and URL of a feed: + Vyplnte názov a adresu kanálu: + + + + Feed title: + Názov kanálu: + + + + Feed URL: + Adresa kanálu: + + + + Edit RSS Feed + Upraviť RSS + + + + Open link in actual tab + Otvoriť odkaz v aktuálnom panely + + + + Open link in new tab + Otvoriť odkaz na novom panely + + + + Close + Zavrieť + + + + + New Tab + Nový panel + + + + Error in fetching feed + Chyba pri sťahovaní kanálu + + + + RSS feed added + RSS kanál pridaný + + + + RSS with title '%1' has been successfuly added. + RSS kanál s názvom '%1' bol úspešne pridaný. + + + + RSS feed duplicated + Duplikovaný kanál + + + + You already have this feed. + Tento kanál už odoberáte. + + + + SearchToolBar + + + + Search + Hľadať + + + + Highlight occurrences + Zvýrazniť + + + + Next + Ďalší + + + + Previous + Predchádzajúci + + + + Case sensitive + Rozlišovať veľkosť + + + + Find: + Nájsť: + + + + No results found. + Žiadny výsledok. + + + + SiteInfo + + + Site Info + Informácie o stránke + + + + Tag + Tag + + + + Value + Hodnota + + + + Image + Obrázok + + + + Image address + Adresa obrázku + + + + Site address: + Adresa stránky: + + + + Site name: + Méno stránky: + + + + Meta tags of site: + Meta tágy na stránke: + + + + Images on site: + Orázky na stránke: + + + + No Named Page + Stránka bez mena + + + + SiteInfoWidget + + + Form + Form + + + + More... + Viac... + + + + Your connection to this site is <b>secured</b>. + Vaše pripojenie na túto sieť je <b>chránené</b>. + + + + Your connection to this site is <b>unsecured</b>. + Vaše pripojenie na túto sieť je <b>nechránené</b>. + + + + This is Your <b>%1.</b> visit of this site. + Toto je Vaša <b>%1.</b> návšteva tejto siete. + + + + first + prvá + + + + second + druhá + + + + third + tretia + + + + This is Your <b>%1</b> visit of this site. + Toto je Vaša <b>%1</b> návšteva tejto siete. + + + + You have <b>never</b> visited this site before. + Túto sieť ste <b>nikdy</b> nenavštívili. + + + + SourceViewer + + + Source of + Zdrojový kód + + + + TabBar + + + + New tab + Nový panel + + + + Back + Späť + + + + Forward + Dopredu + + + + Stop Tab + Zastaviť panel + + + + Reload Tab + Obnoviť panel + + + + Bookmark This Tab + Založiť tento panel + + + + + Bookmark All Tabs + Založiť všetky panely + + + + + Restore Closed Tab + Obnoviť zavretý panel + + + + Close Other Tabs + Zavrieť ostatné panely + + + + + Reload All Tabs + Restore closed tab + Obnoviť všetky panely + + + + Close + Zavrieť + + + + TabWidget + + + Show list of opened tabs + Zobraziť zoznam otvorených panelov + + + + Add Tab + Pridať panel + + + + Loading... + Nahrávam... + + + + + No Named Page + Stránka bez mena + + + + Actually You have %1 opened tabs + Momentálne otvorených %1 panelov + + + + New tab + Nový panel + + + + Updater + + + Go to download page + Prejsť k sťahovaniu + + + + Go to QupZilla website + Ísť na stránku QupZilly + + + + Hide notification + Skryť upozornenia + + + + QupZilla is checking for updates + QupZilla kontroluje aktualizácie + + + + QupZilla found a new version! + QupZilla našla novú verziu! + + + + New version is available + Dostupná nová verzia + + + + New version of QupZilla %1 is available! + Nová verzia QupZily %1 je dostupná! + + + + + QupZilla Update + QupZilla Update + + + + WebPage + + + Confirmation + Potvrdenie + + + + To show this page, QupZilla must resend request witch do it again (like searching on making an shoping, witch has been already done. + Na zobrazenie tejto stránky musí QuipZilla znovu odoslať požiadavok, ktorý zopakuje akciu (napr. hľadanie alebo potvrdenie objednávky), ktorá bola vykonaná už skorej. + + + + Server refused the connection + Server odmietol spojenie + + + + Server closed the connection + Server ukončil spojenie + + + + Server not found + Server nebol nájdený + + + + Connection timed out + Spojenie vypršalo + + + + Untrusted connection + Nedôveryhodné spojenie + + + + Unknown error + Neznáma chyba + + + + Error code %1 + Chybový kód %1 + + + + Failed loading page + Chyba pri načítaní stránky + + + + QupZilla can't load page at %1. + QupZilla nemôže načítať stránku %1. + + + + Check the address for typing errors such as <b>ww.</b>example.com instead of <b>www.</b>example.com + Skontrolujte, či je adresa napísaná správne a neobsahuje chyby ako <b>ww.</b>server.sk miesto <b>www.</b>server.sk + + + + If you are unable to load any pages, check your computer's network connection. + Pokiaľ sa vám nezobrazujú ani ostatné stránky, tak skontrolujte sieťové pripojenie svojho počítača. + + + + If your computer or network is protected by a firewall or proxy, make sure that QupZilla is permitted to access the Web. + Pokiaľ je váš počítač chránený firewallom alebo proxy severom, tak skontrolujte či má QupZilla prístup na internet. + + + + Try Again + Skúsiť znova + + + + WebView + + + + Loading... + Načítavam... + + + + + No Named Page + Stránka bez mena + + + + Done + Hotovo + + + + + + New tab + Nový panel + + + + Open link in new window + Otvoriť odkaz v novom okne + + + + Open link in new tab + Otvoriť odkaz na novom panely + + + + Bookmark link + Pridať odkaz do záložiek + + + + Save link as... + Odoslať odkaz... + + + + Send link... + Odoslať odkaz... + + + + Copy link address + Kopírovať adresu odkazu + + + + Show image + Zobraziť obrázok + + + + Copy image + Kopírovať obrázok + + + + Copy image address + Kopírovať adresu obrázku + + + + Save image as... + Uložiť obrázok ako... + + + + Send image... + Odoslať obrázok... + + + + Back + Späť + + + + Forward + Dopredu + + + + Reload + Obnoviť + + + + Stop + Zastaviť + + + + Bookmark page + Pridať stránku do záložiek + + + + Save page as... + Uložiť stránku ako... + + + + Send page... + Odoslať stránku... + + + + Select all + Vybrať všetko + + + + Show source code + Zobraziť zdrojový kód + + + + Show info about site + Zobraziť informácie o stránke + + + + Show Web Inspector + Zobraziť Web inšpektora + + + + Search + Hľadať + + + + ... on Google + ... na Googlu + + + diff --git a/windows/FileAssociation.nsh b/windows/FileAssociation.nsh new file mode 100644 index 000000000..71a9162ef --- /dev/null +++ b/windows/FileAssociation.nsh @@ -0,0 +1,190 @@ +/* +_____________________________________________________________________________ + + File Association +_____________________________________________________________________________ + + Based on code taken from http://nsis.sourceforge.net/File_Association + + Usage in script: + 1. !include "FileAssociation.nsh" + 2. [Section|Function] + ${FileAssociationFunction} "Param1" "Param2" "..." $var + [SectionEnd|FunctionEnd] + + FileAssociationFunction=[RegisterExtension|UnRegisterExtension] + +_____________________________________________________________________________ + + ${RegisterExtension} "[executable]" "[extension]" "[description]" + +"[executable]" ; executable which opens the file format + ; +"[extension]" ; extension, which represents the file format to open + ; +"[description]" ; description for the extension. This will be display in Windows Explorer. + ; + + + ${UnRegisterExtension} "[extension]" "[description]" + +"[extension]" ; extension, which represents the file format to open + ; +"[description]" ; description for the extension. This will be display in Windows Explorer. + ; + +_____________________________________________________________________________ + + Macros +_____________________________________________________________________________ + + Change log window verbosity (default: 3=no script) + + Example: + !include "FileAssociation.nsh" + !insertmacro RegisterExtension + ${FileAssociation_VERBOSE} 4 # all verbosity + !insertmacro UnRegisterExtension + ${FileAssociation_VERBOSE} 3 # no script +*/ + + +!ifndef FileAssociation_INCLUDED +!define FileAssociation_INCLUDED + +!include Util.nsh + +!verbose push +!verbose 3 +!ifndef _FileAssociation_VERBOSE + !define _FileAssociation_VERBOSE 3 +!endif +!verbose ${_FileAssociation_VERBOSE} +!define FileAssociation_VERBOSE `!insertmacro FileAssociation_VERBOSE` +!verbose pop + +!macro FileAssociation_VERBOSE _VERBOSE + !verbose push + !verbose 3 + !undef _FileAssociation_VERBOSE + !define _FileAssociation_VERBOSE ${_VERBOSE} + !verbose pop +!macroend + + + +!macro RegisterExtensionCall _EXECUTABLE _EXTENSION _DESCRIPTION + !verbose push + !verbose ${_FileAssociation_VERBOSE} + Push `${_DESCRIPTION}` + Push `${_EXTENSION}` + Push `${_EXECUTABLE}` + ${CallArtificialFunction} RegisterExtension_ + !verbose pop +!macroend + +!macro UnRegisterExtensionCall _EXTENSION _DESCRIPTION + !verbose push + !verbose ${_FileAssociation_VERBOSE} + Push `${_EXTENSION}` + Push `${_DESCRIPTION}` + ${CallArtificialFunction} UnRegisterExtension_ + !verbose pop +!macroend + + + +!define RegisterExtension `!insertmacro RegisterExtensionCall` +!define un.RegisterExtension `!insertmacro RegisterExtensionCall` + +!macro RegisterExtension +!macroend + +!macro un.RegisterExtension +!macroend + +!macro RegisterExtension_ + !verbose push + !verbose ${_FileAssociation_VERBOSE} + + Exch $R2 ;exe + Exch + Exch $R1 ;ext + Exch + Exch 2 + Exch $R0 ;desc + Exch 2 + Push $0 + Push $1 + + ReadRegStr $1 HKCR $R1 "" ; read current file association + StrCmp "$1" "" NoBackup ; is it empty + StrCmp "$1" "$R0" NoBackup ; is it our own + WriteRegStr HKCR $R1 "backup_val" "$1" ; backup current value +NoBackup: + WriteRegStr HKCR $R1 "" "$R0" ; set our file association + + ReadRegStr $0 HKCR $R0 "" + StrCmp $0 "" 0 Skip + WriteRegStr HKCR "$R0" "" "$R0" + WriteRegStr HKCR "$R0\shell" "" "open" + WriteRegStr HKCR "$R0\DefaultIcon" "" "$R2,0" +Skip: + WriteRegStr HKCR "$R0\shell\open\command" "" '"$R2" "%1"' + WriteRegStr HKCR "$R0\shell\edit" "" "Edit $R0" + WriteRegStr HKCR "$R0\shell\edit\command" "" '"$R2" "%1"' + + Pop $1 + Pop $0 + Pop $R2 + Pop $R1 + Pop $R0 + + !verbose pop +!macroend + + + +!define UnRegisterExtension `!insertmacro UnRegisterExtensionCall` +!define un.UnRegisterExtension `!insertmacro UnRegisterExtensionCall` + +!macro UnRegisterExtension +!macroend + +!macro un.UnRegisterExtension +!macroend + +!macro UnRegisterExtension_ + !verbose push + !verbose ${_FileAssociation_VERBOSE} + + Exch $R1 ;desc + Exch + Exch $R0 ;ext + Exch + Push $0 + Push $1 + + ReadRegStr $1 HKCR $R0 "" + StrCmp $1 $R1 0 NoOwn ; only do this if we own it + ReadRegStr $1 HKCR $R0 "backup_val" + StrCmp $1 "" 0 Restore ; if backup="" then delete the whole key + DeleteRegKey HKCR $R0 + Goto NoOwn + +Restore: + WriteRegStr HKCR $R0 "" $1 + DeleteRegValue HKCR $R0 "backup_val" + DeleteRegKey HKCR $R1 ;Delete key with association name settings + +NoOwn: + + Pop $1 + Pop $0 + Pop $R1 + Pop $R0 + + !verbose pop +!macroend + +!endif # !FileAssociation_INCLUDED diff --git a/windows/install.ico b/windows/install.ico new file mode 100644 index 000000000..0520a17e8 Binary files /dev/null and b/windows/install.ico differ diff --git a/windows/installer.nsi b/windows/installer.nsi new file mode 100644 index 000000000..8e821c040 --- /dev/null +++ b/windows/installer.nsi @@ -0,0 +1,169 @@ +!include "FileAssociation.nsh" + +SetCompressor /SOLID /FINAL lzma + +!define PRODUCT_NAME "QupZilla" +!define /date PRODUCT_VERSION "0.9.7" +!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\qupzilla.exe" +!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" +!define PRODUCT_UNINST_ROOT_KEY "HKLM" + +!include "MUI.nsh" +!define MUI_ABORTWARNING +!define MUI_ICON "wininstall\install.ico" +!define MUI_UNICON "wininstall\uninstall.ico" +!define MUI_WELCOMEFINISHPAGE_BITMAP "wininstall\welcome.bmp" +!define MUI_UNWELCOMEFINISHPAGE_BITMAP "wininstall\welcome.bmp" + +!insertmacro MUI_PAGE_WELCOME +!insertmacro MUI_PAGE_DIRECTORY +!insertmacro MUI_PAGE_INSTFILES + +!define MUI_FINISHPAGE_RUN "$INSTDIR\qupzilla.exe" +!insertmacro MUI_PAGE_FINISH + +!insertmacro MUI_UNPAGE_WELCOME +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES +!insertmacro MUI_UNPAGE_FINISH + +!insertmacro MUI_LANGUAGE "English" +!insertmacro MUI_LANGUAGE "Czech" +!insertmacro MUI_LANGUAGE "Slovak" +!insertmacro MUI_LANGUAGE "Dutch" +!insertmacro MUI_LANGUAGE "French" +!insertmacro MUI_LANGUAGE "German" +!insertmacro MUI_LANGUAGE "Korean" +!insertmacro MUI_LANGUAGE "Russian" +!insertmacro MUI_LANGUAGE "Spanish" +!insertmacro MUI_LANGUAGE "Swedish" +!insertmacro MUI_LANGUAGE "Tradchinese" +!insertmacro MUI_LANGUAGE "Simpchinese" + +Name "${PRODUCT_NAME} ${PRODUCT_VERSION}" +OutFile "${PRODUCT_NAME} ${PRODUCT_VERSION} Installer.exe" +InstallDir "$PROGRAMFILES\${PRODUCT_NAME}\" +InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" "" +ShowInstDetails show +ShowUnInstDetails show + +Section "Main Components" + KillProcDLL::KillProc "qupzilla.exe" + Sleep 100 + SetOverwrite on + + SetOutPath "$INSTDIR" + File "qupzilla.exe" + File "AUTHORS" + File "COPYRIGHT" + File "GPLv3" + File "README" + File "libeay32.dll" + File "ssleay32.dll" + File "libgcc_s_dw2-1.dll" + File "libssl32.dll" + File "mingwm10.dll" + File "phonon4.dll" + File "QtCore4.dll" + File "QtGui4.dll" + File "QtNetwork4.dll" + File "QtSql4.dll" + File "QtWebKit4.dll" + + SetOutPath "$INSTDIR\data\default\profiles" + File "data\default\profiles\profiles.ini" + + SetOutPath "$INSTDIR\data\default\profiles\default" + File "data\default\profiles\default\background.png" + File "data\default\profiles\default\browsedata.db" + + SetOutPath "$INSTDIR\imageformats" + File "imageformats\qico4.dll" + File "imageformats\qsvg4.dll" + File "imageformats\qgif4.dll" + File "imageformats\qjpeg4.dll" + File "imageformats\qtiff4.dll" + File "imageformats\qmng4.dll" + + SetOutPath "$INSTDIR\locale" + File "locale\cs_CZ.qm" + File "locale\qt_cs.qm" + File "locale\sk_SK.qm" + File "locale\qt_sk.qm" + + SetOutPath "$INSTDIR\plugins" + File "plugins\ExamplePlugin.dll" + + SetOutPath "$INSTDIR\sqldrivers" + File "sqldrivers\qsqlite4.dll" + File "sqldrivers\qsqlodbc4.dll" + +SectionEnd + +Section Icons + SetOutPath "$INSTDIR" + CreateShortCut "$SMPROGRAMS\QupZilla.lnk" "$INSTDIR\qupzilla.exe" "" + CreateShortCut "$DESKTOP\QupZilla.lnk" "$INSTDIR\qupzilla.exe" "" + ${registerExtension} "$INSTDIR\qupzilla.exe" ".htm" "HTM_FILE" + ${registerExtension} "$INSTDIR\qupzilla.exe" ".html" "HTML_FILE" +SectionEnd + +Section Uninstaller + WriteUninstaller "$INSTDIR\uninstall.exe" + WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\qupzilla.exe" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninstall.exe" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\qupzilla.exe" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}" +SectionEnd + +Section Uninstall + KillProcDLL::KillProc "qupzilla.exe" + Sleep 100 + Delete "$SMPROGRAMS\QupZilla.lnk" + Delete "$DESKTOP\QupZilla.lnk" + RMDir /r "$INSTDIR" + DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" + DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}" + ${unregisterExtension} ".htm" "HTM_FILE" + ${unregisterExtension} ".html" "HTML_FILE" +SectionEnd + +BrandingText "${PRODUCT_NAME} ${PRODUCT_VERSION} Installer" + +Function .onInit + ;Language selection dialog + + Push "" + Push ${LANG_ENGLISH} + Push English + Push ${LANG_CZECH} + Push Czech + Push ${LANG_DUTCH} + Push Dutch + Push ${LANG_FRENCH} + Push French + Push ${LANG_GERMAN} + Push German + Push ${LANG_KOREAN} + Push Korean + Push ${LANG_RUSSIAN} + Push Russian + Push ${LANG_SPANISH} + Push Spanish + Push ${LANG_SWEDISH} + Push Swedish + Push ${LANG_TRADCHINESE} + Push "Traditional Chinese" + Push ${LANG_SIMPCHINESE} + Push "Simplified Chinese" + Push ${LANG_SLOVAK} + Push Slovak + Push A ; A means auto count languages + ; for the auto count to work the first empty push (Push "") must remain + LangDLL::LangDialog "Installer Language" "Please select the language of the installer" + + Pop $LANGUAGE + StrCmp $LANGUAGE "cancel" 0 +2 + Abort +FunctionEnd diff --git a/windows/uninstall.ico b/windows/uninstall.ico new file mode 100644 index 000000000..f31b71786 Binary files /dev/null and b/windows/uninstall.ico differ diff --git a/windows/welcome.bmp b/windows/welcome.bmp new file mode 100644 index 000000000..eb9f2c64d Binary files /dev/null and b/windows/welcome.bmp differ