Import Upstream version 1.1.0.47

This commit is contained in:
谢炜 2022-06-22 18:42:43 +08:00
commit 7b816a626a
394 changed files with 1442771 additions and 0 deletions

3
.gitigonre Normal file
View File

@ -0,0 +1,3 @@
moc_*.cpp
*.o
*.user

674
LICENSE Normal file
View File

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
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.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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 <https://www.gnu.org/licenses/>.
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:
<program> Copyright (C) <year> <name of author>
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
<https://www.gnu.org/licenses/>.
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
<https://www.gnu.org/licenses/why-not-lgpl.html>.

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# kylin-music
kylin-music

342
UI/base/allpupwindow.cpp Normal file
View File

@ -0,0 +1,342 @@
/*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* 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 <https://www.gnu.org/licenses/>.
*/
#include "allpupwindow.h"
#include "widgetstyle.h"
#include "UI/mainwidget.h"
#include "xatom-helper.h"
#include <ukui-log4qt.h>
#define PT_12 12
#define PT_11 11
QRegExp gInvalidName("[\\\\/:\\*\\?\\\"&<>\\|]");/* 文件名或文件夹名中不能出现以下字符:\、/、:、*、?、"、&、<、>、| */
AllPupWindow::AllPupWindow(QWidget *parent) : QDialog(parent)
{
inpupdialog();
dlgcolor();
}
void AllPupWindow::closeDialog()
{
this->close();
enterLineEdit->clear();
}
void AllPupWindow::slotTextChanged(QString text)
{
KyInfo() << "text = " << text;
if (!nameIsValid(text) && text != "") {
QMessageBox::warning(Widget::mutual,tr("Prompt information"),tr("Could not contain characters: \ / : * ? \" & < > |"), QMessageBox::Ok);
enterLineEdit->cursorBackward(true, 1);
enterLineEdit->del();
}
enterLineEdit->setLabelNumber(15 - enterLineEdit->text().length());
if (text.length() == 15) {
tips->setText(tr("Reached upper character limit"));
tips->setStyleSheet("QLabel{color:#F44E50;}");
} else {
tips->setText("");
}
}
void AllPupWindow::inpupdialog()
{
this->setWindowTitle(tr("Music Player"));
this->setFixedSize(376, 222);
// this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
// MotifWmHints hints;
// hints.flags = MWM_HINTS_FUNCTIONS|MWM_HINTS_DECORATIONS;
// hints.functions = MWM_FUNC_ALL;
// hints.decorations = MWM_DECOR_BORDER;
// XAtomHelper::getInstance()->setWindowMotifHint(this->winId(), hints);
this->setWindowModality(Qt::ApplicationModal); //弹出自定义对话框时主界面不可操作
// pupDialog->setModal(true);
testLayout = new QVBoxLayout();
this->setLayout(testLayout);
titleLayout = new QHBoxLayout();
titleLab = new QLabel(this);
closeBtn = new QToolButton(this);
closeBtn->setFixedSize(30,30);
closeBtn->setIcon(QIcon::fromTheme("window-close-symbolic"));
closeBtn->setProperty("isWindowButton", 0x2);
closeBtn->setProperty("useIconHighlightEffect", 0x8);
closeBtn->setAutoRaise(true);
closeBtn->hide();
// titleLab->setText("提示信息");
titleLab->setText(tr("Prompt information"));
titleLab->setFixedHeight(28);
titleLayout->addWidget(titleLab,Qt::AlignLeft);
titleLayout->addWidget(closeBtn,0,Qt::AlignRight);
titleLayout->setMargin(0);
titleLayout->setSpacing(0);
enterLineEdit = new LabEdit;
enterLineEdit->setFixedSize(312, 40);
enterLineEdit->setMaxLength(15);
tips = new QLabel(this);
tips->setFixedHeight(28);
confirmBtn = new QPushButton(this);
cancelBtn = new QPushButton(this);
btnLayout = new QHBoxLayout();
stackWid = new QStackedWidget();
stackWid->addWidget(enterLineEdit);
stackWid->setFixedSize(312,40);
// confirmBtn->setText("确认");
confirmBtn->setText(tr("Confirm"));
confirmBtn->setFixedSize(105,36);
confirmBtn->setProperty("isImportant", true);
// cancelBtn->setText("取消");
cancelBtn->setText(tr("Cancel"));
cancelBtn->setFixedSize(105,36);
btnLayout->addWidget(cancelBtn, 0, Qt::AlignRight);
btnLayout->addWidget(confirmBtn, Qt::AlignRight);
btnLayout->setSpacing(20);
btnLayout->setMargin(0);
enterLineEdit->setPlaceholderText("请输入歌单标题:");
enterLineEdit->setPlaceholderText(tr("Please input playlist name:"));
testLayout->setMargin(0);
testLayout->setSpacing(0);
testLayout->addLayout(titleLayout);
testLayout->addSpacing(16);
testLayout->addWidget(stackWid);
testLayout->addSpacing(2);
testLayout->addWidget(tips);
testLayout->addSpacing(14);
testLayout->addLayout(btnLayout);
testLayout->setContentsMargins(32, 16, 32, 24);
this->setAutoFillBackground(true);
this->setBackgroundRole(QPalette::Base);
// connect(addSongListBtn, SIGNAL(clicked(bool)), this, SLOT(addSongList()));
connect(enterLineEdit,SIGNAL(textChanged(QString)),this,SLOT(slotTextChanged(QString)));
connect(closeBtn,SIGNAL(clicked(bool)),this,SLOT(closeDialog()));
connect(cancelBtn,SIGNAL(clicked(bool)),this,SLOT(closeDialog()));
//限制应用内字体固定大小
// QFont sizeFont;
// sizeFont.setPixelSize(14);
// confirmBtn->setFont(sizeFont);
// cancelBtn->setFont(sizeFont);
// titleLab->setFont(sizeFont);
// enterLineEdit->setFont(sizeFont);
}
void AllPupWindow::slotLableSetFontSize(int size)
{
//默认大小12px,换算成pt为9
double lableBaseFontSize = PT_11;//魔鬼数字,自行处理
double nowFontSize = lableBaseFontSize * double(size) / 11;//11为系统默认大小魔鬼数字自行处理
QFont font;
font.setPointSizeF(nowFontSize);
tips->setFont(font);
}
void AllPupWindow::dlgcolor()
{
if(WidgetStyle::themeColor == 1 )
{
// cancelBtn->setStyleSheet("PushButton{border-radius:4px;border:1px solid #DDDFE7;color:#606265;}"
// "QPushButton::hover{background:#4D4D4D;}");
// cancelBtn->setStyleSheet("QPushButton{border-radius:4px;border:1px solid #DDDFE7;color:#606265;}"
// "QPushButton::hover{background:#4D4D4D;}");
// enterLineEdit->setStyleSheet("width:392px;height:32px;border-radius:4px;\
// border: 1px solid #606265;color:#F9F9F9;background:#3D3D41;");
// pupDialog->setStyleSheet("background-color:#3D3D41;");
// confirmBtn->setStyleSheet("QPushButton{background:#3790FA;border-radius:4px;color:#FFFFFF;}"
// "QPushButton::hover{background:#40A9FB;}"
// "QPushButton::pressed{background:#296CD9;}"
// );
// titleLab->setStyleSheet("width:80px;height:14px;\
// font-weight: 600;\
// border:none;\
// color: #F9F9F9;\
// line-height:14px;");
}
else if(WidgetStyle::themeColor == 0)
{
// cancelBtn->setStyleSheet("QPushButton{border-radius:4px;border:1px solid #DDDFE7;color:#8F9399;}"
// "QPushButton::hover{background:#F2F6FD;}");
// enterLineEdit->setStyleSheet("width:392px;height:32px;border-radius:4px;border:1px solid #DDDFE7;");
// pupDialog->setStyleSheet("background-color:#FFFFFF;");
// confirmBtn->setStyleSheet("QPushButton{background:#3790FA;border-radius:4px;color:#FFFFFF;}"
// "QPushButton::hover{background:#40A9FB;}"
// "QPushButton::pressed{background:#296CD9;}"
// );
// titleLab->setStyleSheet("width:80px;height:14px;\
// font-weight: 600;\
// border:none;\
// color: #1B1B1B;\
// line-height:14px;");
}
}
bool AllPupWindow::nameIsValid(QString textName)
{
if (nullptr == textName) {
return false;
}
return !textName.contains(gInvalidName);
}
MusicInfoDialog::MusicInfoDialog(musicDataStruct date)
{
this->setAutoFillBackground(true);
this->setBackgroundRole(QPalette::Base);
this->setWindowTitle(tr("Music Player"));
musicDate = date;
initStyle();
}
MusicInfoDialog::~MusicInfoDialog()
{
}
void MusicInfoDialog::initStyle()
{
mainVLayout = new QVBoxLayout(this);
this->setLayout(mainVLayout);
songNameLabel = new MyLabel(this);
singerLabel = new MyLabel(this);
albumLabel = new MyLabel(this);
filePathLabel = new MyLabel(this);
fileTypeLabel = new MyLabel(this);
fileTimeLabel = new MyLabel(this);
fileSizeLable = new MyLabel(this);
musicInfoLabel = new QLabel(this);
musicInfoLabel->setText(tr("Music Information"));
musicInfoLabel->setFixedHeight(24);
songNameLabel->setFixedHeight(28);
singerLabel->setFixedHeight(28);
albumLabel->setFixedHeight(28);
fileTypeLabel->setFixedHeight(28);
fileSizeLable->setFixedHeight(28);
fileTimeLabel->setFixedHeight(28);
filePathLabel->setFixedHeight(28);
buttonLayout = new QHBoxLayout();
cancelBtn = new QPushButton(this);
confirmBtn = new QPushButton(this);
btnWidget = new QWidget(this);
connect(cancelBtn,&QPushButton::clicked,this,&MusicInfoDialog::close);
connect(confirmBtn,&QPushButton::clicked,this,&MusicInfoDialog::close);
btnWidget->setLayout(buttonLayout);
buttonLayout->setAlignment(Qt::AlignRight);
buttonLayout->addWidget(cancelBtn);
buttonLayout->addWidget(confirmBtn);
buttonLayout->setMargin(0);
buttonLayout->setSpacing(16);
confirmBtn->setText(tr("Confirm"));
confirmBtn->setFixedSize(105,36);
// cancelBtn->setText("取消");s
cancelBtn->setText(tr("Cancel"));
cancelBtn->setFixedSize(105,36);
// confirmBtn->setStyleSheet("background: #3790FA;color:#FFFFFF");
confirmBtn->setProperty("isImportant", true);
mainVLayout->setAlignment(Qt::AlignTop);
mainVLayout->addWidget(musicInfoLabel);
mainVLayout->addSpacing(10);
mainVLayout->addWidget(songNameLabel);
mainVLayout->addWidget(singerLabel);
mainVLayout->addWidget(albumLabel);
mainVLayout->addWidget(fileTypeLabel);
mainVLayout->addWidget(fileSizeLable);
mainVLayout->addWidget(fileTimeLabel);
mainVLayout->addWidget(filePathLabel);
mainVLayout->addSpacing(20);
mainVLayout->addWidget(btnWidget);
mainVLayout->setSpacing(6);
mainVLayout->setContentsMargins(32,20,32,0);
if(musicDate.title != "")
{
songNameLabel->setText(tr("Song Name : ") + musicDate.title);
singerLabel ->setText(tr("Singer : ") + musicDate.singer);
albumLabel ->setText(tr("Album : ") + musicDate.album);
fileTypeLabel->setText(tr("File Type : ") + musicDate.filetype);
fileSizeLable->setText(tr("File Size : ") + musicDate.size);
fileTimeLabel->setText(tr("File Time : ") + musicDate.time);
filePathLabel->setText(tr("File Path : ") + musicDate.filepath);
}
this->setFixedSize(376,370);
//限制应用内字体固定大小
// QFont sizeFont;
// sizeFont.setPixelSize(14);
// QFont titleFont;
// titleFont.setPixelSize(16);
// titleFont.setBold(true);
// songNameLabel->setFont(sizeFont);
// singerLabel->setFont(sizeFont);
// albumLabel->setFont(sizeFont);
// fileTypeLabel->setFont(sizeFont);
// fileSizeLable->setFont(sizeFont);
// fileTimeLabel->setFont(sizeFont);
// filePathLabel->setFont(sizeFont);
// musicInfoLabel->setFont(titleFont);
}
void MusicInfoDialog::slotLableSetFontSize(int size)
{
//默认大小12px,换算成pt为9
double lableBaseFontSize = PT_12;//魔鬼数字,自行处理
double nowFontSize = lableBaseFontSize * double(size) / 11;//11为系统默认大小魔鬼数字自行处理
QFont font;
font.setPointSizeF(nowFontSize);
musicInfoLabel->setFont(font);
}

106
UI/base/allpupwindow.h Normal file
View File

@ -0,0 +1,106 @@
/*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* 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 <https://www.gnu.org/licenses/>.
*/
#ifndef ALLPUPWINDOW_H
#define ALLPUPWINDOW_H
#include <QMessageBox>
#include <QRegExp>
#include <QFrame>
#include <QLabel>
#include <QVBoxLayout>
#include <QPushButton>
#include <QToolButton>
#include <QStackedWidget>
#include <QListWidget>
#include <QListWidgetItem>
#include <QDialog>
#include <QPainter>
#include <QTextEdit>
#include <QLineEdit>
#include <QApplication>
#include <QScreen>
#include <QDesktopWidget>
#include <QDebug>
#include <QMessageBox>
#include "UIControl/base/musicDataBase.h"
#include "UI/base/mylabel.h"
#include "UI/base/labedit.h"
class AllPupWindow :public QDialog
{
Q_OBJECT
public:
explicit AllPupWindow(QWidget *parent = nullptr);
QPushButton *confirmBtn = nullptr;
QPushButton *cancelBtn = nullptr;
QToolButton *closeBtn = nullptr;
QLabel *titleLab = nullptr;
QLabel *tips = nullptr;
LabEdit *enterLineEdit = nullptr;
QVBoxLayout *testLayout = nullptr;
QHBoxLayout *titleLayout = nullptr;
QHBoxLayout *btnLayout = nullptr;
QStackedWidget *stackWid = nullptr;
void dlgcolor();
bool nameIsValid(QString textName);
public Q_SLOTS:
void closeDialog();
void slotTextChanged(QString text);
void slotLableSetFontSize(int size);
private:
void inpupdialog();
};
class MusicInfoDialog : public QDialog
{
Q_OBJECT
public:
explicit MusicInfoDialog(musicDataStruct date);
~MusicInfoDialog();
musicDataStruct musicDate;
public Q_SLOTS:
//字体
void slotLableSetFontSize(int size);
private:
MyLabel *songNameLabel = nullptr;
MyLabel *singerLabel = nullptr;
MyLabel *albumLabel = nullptr;
MyLabel *filePathLabel = nullptr;
MyLabel *fileTypeLabel = nullptr;
MyLabel *fileTimeLabel = nullptr;
MyLabel *fileSizeLable = nullptr;
QLabel *musicInfoLabel = nullptr;
QVBoxLayout *mainVLayout = nullptr;
QHBoxLayout *buttonLayout = nullptr;
QWidget *btnWidget = nullptr;
QPushButton *cancelBtn = nullptr;
QPushButton *confirmBtn = nullptr;
void initStyle();
};
#endif // ALLPUPWINDOW_H

42
UI/base/labedit.cpp Normal file
View File

@ -0,0 +1,42 @@
#include "labedit.h"
#include <QRegExpValidator>
LabEdit::LabEdit()
{
init();
}
void LabEdit::init()
{
QHBoxLayout* mainLayout = new QHBoxLayout();
lab = new QLabel(this);
lab->setText(QString("%1").arg(leng));
mainLayout->addWidget(lab);
mainLayout->setAlignment(Qt::AlignRight);
this->setLayout(mainLayout);
// QRegExp rx = QRegExp("[^\\\\/:*?\"&<>|]*"); //限制以下特殊符号在lineEdit中的输入
// QRegExpValidator* validator = new QRegExpValidator(rx);
// this->setValidator(validator);
}
void LabEdit::setLabelNumber(int num)
{
lab->setText(QString("%1").arg(num));
if (num == 0) {
lab->setStyleSheet("QLabel{color:#F44E50;}");
} else {
lab->setStyleSheet("QLabel{color:#000000;}");
}
}
void LabEdit::slotLableSetFontSize(int size)
{
//默认大小12px,换算成pt为9
double lableBaseFontSize = PT_11;//魔鬼数字,自行处理
double nowFontSize = lableBaseFontSize * double(size) / 11;//11为系统默认大小魔鬼数字自行处理
QFont font;
font.setPointSizeF(nowFontSize);
lab->setFont(font);
}

26
UI/base/labedit.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef LABEDIT_H
#define LABEDIT_H
#include <QLineEdit>
#include <QLabel>
#include <QHBoxLayout>
#include <QDebug>
#define PT_11 11
class LabEdit : public QLineEdit
{
Q_OBJECT
public:
LabEdit();
void setLabelNumber(int num);
public Q_SLOTS:
void slotLableSetFontSize(int size);
private:
void init();
private:
QLabel *lab = nullptr;
int leng = 15;
};
#endif // LABEDIT_H

89
UI/base/mylabel.cpp Normal file
View File

@ -0,0 +1,89 @@
#include "mylabel.h"
#include <QtWidgets>
MyLabel::MyLabel(QWidget *parent, Qt::WindowFlags f)
: QLabel(parent, f)
{
this->setMinimumWidth(minSize);
setTextFormat(Qt::PlainText);
}
MyLabel::MyLabel(const QString &text, QWidget *parent, Qt::WindowFlags f)
: QLabel(text, parent, f), m_fullText(text)
{
this->setMinimumWidth(minSize);
setTextFormat(Qt::PlainText);
}
void MyLabel::setText(const QString &text)
{
setFullText(text);
}
void MyLabel::setFullText(const QString &text)
{
m_fullText = text;
update();
}
void MyLabel::setTextLimitShrink(const QString &text, int width)
{
this->setMinimumWidth(qMin(this->fontMetrics().width(text), width));
// this->setMinimumSize(200);
setFullText(text);
}
void MyLabel::setTextLimitExpand(const QString &text)
{
int textWidth = this->fontMetrics().width(text);
this->setMaximumWidth(textWidth);
setFullText(text);
}
QString MyLabel::fullText() const
{
return m_fullText;
}
void MyLabel::paintEvent(QPaintEvent *event)
{
QLabel::paintEvent(event);
elideText();
}
void MyLabel::elideText()
{
QFontMetrics fm = this->fontMetrics();
int dif = fm.width(m_fullText) - this->width();
if (dif > 0) {
QString showText = fm.elidedText(m_fullText, Qt::ElideRight, this->width());
QLabel::setText(showText);
if (showText != m_fullText) {
// QString str = dealMessage(m_fullText);
this->setToolTip(m_fullText);
} else {
this->setToolTip("");
}
} else {
QLabel::setText(m_fullText);
this->setToolTip("");
}
}
//QString MyLabel::dealMessage(QString msg)
//{
// if(msg.size() > fontSize)
// {
// QString str;
// int time = msg.size()/fontSize;
// for(int i = 0; i <= time-1; i++)
// {
// str = QString(str + msg.mid(i*fontSize,fontSize)+"\r\n");
// }
// str = QString(str+msg.mid(time*fontSize,fontSize));
// return str;
// }
// else
// return msg;
//}

28
UI/base/mylabel.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef MYLABEL_H
#define MYLABEL_H
#include <QLabel>
class MyLabel : public QLabel
{
Q_OBJECT
public:
explicit MyLabel(QWidget *parent=0, Qt::WindowFlags f=0);
explicit MyLabel(const QString &text, QWidget *parent=0, Qt::WindowFlags f=0);
void setText(const QString &text);
void setFullText(const QString &text);
void setTextLimitShrink(const QString &text, int width);
void setTextLimitExpand(const QString &text);
QString fullText() const;
// QString dealMessage(QString msg);
int fontSize = 24;
int minSize = 120;
protected:
void paintEvent(QPaintEvent *);
private:
void elideText();
private:
QString m_fullText;
};
#endif // MYLABEL_H

22
UI/base/widgetstyle.cpp Normal file
View File

@ -0,0 +1,22 @@
/*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* 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 <https://www.gnu.org/licenses/>.
*/
#include "widgetstyle.h"
int WidgetStyle::themeColor = 0;
//const QColor highlightTextColor = QColor(55,144,250);

42
UI/base/widgetstyle.h Normal file
View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* 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 <https://www.gnu.org/licenses/>.
*/
#ifndef WIDGETSTYLE_H
#define WIDGETSTYLE_H
#include <QGSettings>
#define KYLINMUSIC "org.kylin-music-data.settings"
#define FITTHEMEWINDOWS "org.ukui.style"
//static int themeColor = 0; //test 主题颜色适配--浅色
//int WidgetStyle::themeColor = 1; //test 主题颜色适配--深色
class WidgetStyle
{
public:
WidgetStyle() {}
static int themeColor; //test 主题颜色适配--浅色
// const QColor highlightTextColor;
};
#endif // WIDGETSTYLE_H

210
UI/base/xatom-helper.cpp Normal file
View File

@ -0,0 +1,210 @@
/*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* 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 <https://www.gnu.org/licenses/>.
*/
#include "xatom-helper.h"
#include <limits.h>
#include <QX11Info>
#include <X11/X.h>
#include <X11/Xatom.h>
#include <NETWM>
static XAtomHelper *global_instance = nullptr;
XAtomHelper *XAtomHelper::getInstance()
{
if (!global_instance)
global_instance = new XAtomHelper;
return global_instance;
}
bool XAtomHelper::isFrameLessWindow(int winId)
{
auto hints = getInstance()->getWindowMotifHint(winId);
if (hints.flags == MWM_HINTS_DECORATIONS && hints.functions == 1) {
return true;
}
return false;
}
bool XAtomHelper::isWindowDecorateBorderOnly(int winId)
{
return isWindowMotifHintDecorateBorderOnly(getInstance()->getWindowMotifHint(winId));
}
bool XAtomHelper::isWindowMotifHintDecorateBorderOnly(const MotifWmHints &hint)
{
bool isDeco = false;
if (hint.flags & MWM_HINTS_DECORATIONS && hint.flags != MWM_HINTS_DECORATIONS) {
if (hint.decorations == MWM_DECOR_BORDER)
isDeco = true;
}
return isDeco;
}
bool XAtomHelper::isUKUICsdSupported()
{
// fixme:
return false;
}
bool XAtomHelper::isUKUIDecorationWindow(int winId)
{
if (m_ukuiDecorationAtion == None)
return false;
Atom type;
int format;
ulong nitems;
ulong bytes_after;
uchar *data;
bool isUKUIDecoration = false;
XGetWindowProperty(QX11Info::display(), winId, m_ukuiDecorationAtion,
0, LONG_MAX, false,
m_ukuiDecorationAtion, &type,
&format, &nitems,
&bytes_after, &data);
if (type == m_ukuiDecorationAtion) {
if (nitems == 1) {
isUKUIDecoration = data[0];
}
}
return isUKUIDecoration;
}
UnityCorners XAtomHelper::getWindowBorderRadius(int winId)
{
UnityCorners corners;
Atom type;
int format;
ulong nitems;
ulong bytes_after;
uchar *data;
if (m_unityBorderRadiusAtom != None) {
XGetWindowProperty(QX11Info::display(), winId, m_unityBorderRadiusAtom,
0, LONG_MAX, false,
XA_CARDINAL, &type,
&format, &nitems,
&bytes_after, &data);
if (type == XA_CARDINAL) {
if (nitems == 4) {
corners.topLeft = static_cast<ulong>(data[0]);
corners.topRight = static_cast<ulong>(data[1*sizeof (ulong)]);
corners.bottomLeft = static_cast<ulong>(data[2*sizeof (ulong)]);
corners.bottomRight = static_cast<ulong>(data[3*sizeof (ulong)]);
}
XFree(data);
}
}
return corners;
}
void XAtomHelper::setWindowBorderRadius(int winId, const UnityCorners &data)
{
if (m_unityBorderRadiusAtom == None)
return;
ulong corners[4] = {data.topLeft, data.topRight, data.bottomLeft, data.bottomRight};
XChangeProperty(QX11Info::display(), winId, m_unityBorderRadiusAtom, XA_CARDINAL,
32, XCB_PROP_MODE_REPLACE, (const unsigned char *) &corners, sizeof (corners)/sizeof (corners[0]));
}
void XAtomHelper::setWindowBorderRadius(int winId, int topLeft, int topRight, int bottomLeft, int bottomRight)
{
if (m_unityBorderRadiusAtom == None)
return;
ulong corners[4] = {(ulong)topLeft, (ulong)topRight, (ulong)bottomLeft, (ulong)bottomRight};
XChangeProperty(QX11Info::display(), winId, m_unityBorderRadiusAtom, XA_CARDINAL,
32, XCB_PROP_MODE_REPLACE, (const unsigned char *) &corners, sizeof (corners)/sizeof (corners[0]));
}
void XAtomHelper::setUKUIDecoraiontHint(int winId, bool set)
{
if (m_ukuiDecorationAtion == None)
return;
XChangeProperty(QX11Info::display(), winId, m_ukuiDecorationAtion, m_ukuiDecorationAtion, 32, XCB_PROP_MODE_REPLACE, (const unsigned char *) &set, 1);
}
void XAtomHelper::setWindowMotifHint(int winId, const MotifWmHints &hints)
{
if (m_unityBorderRadiusAtom == None)
return;
XChangeProperty(QX11Info::display(), winId, m_motifWMHintsAtom, m_motifWMHintsAtom,
32, XCB_PROP_MODE_REPLACE, (const unsigned char *)&hints, sizeof (MotifWmHints)/ sizeof (ulong));
}
MotifWmHints XAtomHelper::getWindowMotifHint(int winId)
{
MotifWmHints hints;
if (m_unityBorderRadiusAtom == None)
return hints;
uchar *data;
Atom type;
int format;
ulong nitems;
ulong bytes_after;
XGetWindowProperty(QX11Info::display(), winId, m_motifWMHintsAtom,
0, sizeof (MotifWmHints)/sizeof (long), false, AnyPropertyType, &type,
&format, &nitems, &bytes_after, &data);
if (type == None) {
return hints;
} else {
hints = *(MotifWmHints *)data;
XFree(data);
}
return hints;
}
XAtomHelper::XAtomHelper(QObject *parent) : QObject(parent)
{
if (!QX11Info::isPlatformX11())
return;
m_motifWMHintsAtom = XInternAtom(QX11Info::display(), "_MOTIF_WM_HINTS", true);
m_unityBorderRadiusAtom = XInternAtom(QX11Info::display(), "_UNITY_GTK_BORDER_RADIUS", false);
m_ukuiDecorationAtion = XInternAtom(QX11Info::display(), "_KWIN_UKUI_DECORAION", false);
}
Atom XAtomHelper::registerUKUICsdNetWmSupportAtom()
{
// fixme:
return None;
}
void XAtomHelper::unregisterUKUICsdNetWmSupportAtom()
{
// fixme:
}

106
UI/base/xatom-helper.h Normal file
View File

@ -0,0 +1,106 @@
/*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* 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 <https://www.gnu.org/licenses/>.
*/
#ifndef XATOMHELPER_H
#define XATOMHELPER_H
#include <QObject>
#include <X11/Xlib.h>
#include <NETWM>
struct UnityCorners {
ulong topLeft = 0;
ulong topRight = 0;
ulong bottomLeft = 0;
ulong bottomRight = 0;
};
typedef struct {
ulong flags = 0;
ulong functions = 0;
ulong decorations = 0;
long input_mode = 0;
ulong status = 0;
} MotifWmHints, MwmHints;
#define MWM_HINTS_FUNCTIONS (1L << 0)
#define MWM_HINTS_DECORATIONS (1L << 1)
#define MWM_HINTS_INPUT_MODE (1L << 2)
#define MWM_HINTS_STATUS (1L << 3)
#define MWM_FUNC_ALL (1L << 0)
#define MWM_FUNC_RESIZE (1L << 1)
#define MWM_FUNC_MOVE (1L << 2)
#define MWM_FUNC_MINIMIZE (1L << 3)
#define MWM_FUNC_MAXIMIZE (1L << 4)
#define MWM_FUNC_CLOSE (1L << 5)
#define MWM_DECOR_ALL (1L << 0)
#define MWM_DECOR_BORDER (1L << 1)
#define MWM_DECOR_RESIZEH (1L << 2)
#define MWM_DECOR_TITLE (1L << 3)
#define MWM_DECOR_MENU (1L << 4)
#define MWM_DECOR_MINIMIZE (1L << 5)
#define MWM_DECOR_MAXIMIZE (1L << 6)
#define MWM_INPUT_MODELESS 0
#define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1
#define MWM_INPUT_SYSTEM_MODAL 2
#define MWM_INPUT_FULL_APPLICATION_MODAL 3
#define MWM_INPUT_APPLICATION_MODAL MWM_INPUT_PRIMARY_APPLICATION_MODAL
#define MWM_TEAROFF_WINDOW (1L<<0)
namespace UKUI {
class Decoration;
}
class XAtomHelper : public QObject
{
// friend class UKUI::Decoration;
Q_OBJECT
public:
static XAtomHelper *getInstance();
static bool isFrameLessWindow(int winId);
static bool isWindowDecorateBorderOnly(int winId);
static bool isWindowMotifHintDecorateBorderOnly(const MotifWmHints &hint);
bool isUKUICsdSupported();
bool isUKUIDecorationWindow(int winId);
UnityCorners getWindowBorderRadius(int winId);
void setWindowBorderRadius(int winId, const UnityCorners &data);
void setWindowBorderRadius(int winId, int topLeft, int topRight, int bottomLeft, int bottomRight);
void setUKUIDecoraiontHint(int winId, bool set = true);
void setWindowMotifHint(int winId, const MotifWmHints &hints);
MotifWmHints getWindowMotifHint(int winId);
private:
explicit XAtomHelper(QObject *parent = nullptr);
Atom registerUKUICsdNetWmSupportAtom();
void unregisterUKUICsdNetWmSupportAtom();
Atom m_motifWMHintsAtom = None;
Atom m_unityBorderRadiusAtom = None;
Atom m_ukuiDecorationAtion = None;
};
#endif // XATOMHELPER_H

58
UI/dbusadapter.cpp Normal file
View File

@ -0,0 +1,58 @@
#include "dbusadapter.h"
DbusAdapter::DbusAdapter(QObject *parent) : QObject(parent)
{
QDBusConnection::sessionBus().unregisterService("org.mpris.MediaPlayer2.KylinMusic");
QDBusConnection::sessionBus().registerService("org.mpris.MediaPlayer2.KylinMusic");
QDBusConnection::sessionBus().registerObject("/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", this, QDBusConnection::ExportNonScriptableSlots);
}
void DbusAdapter::Stop() const
{
Widget::mutual->Stop();
}
void DbusAdapter::Next() const
{
Widget::mutual->Next();
}
void DbusAdapter::Play() const
{
Widget::mutual->Play();
}
void DbusAdapter::Pause() const
{
Widget::mutual->Pause();
}
void DbusAdapter::PlayPause() const
{
Widget::mutual->PlayPause();
}
void DbusAdapter::Previous() const
{
Widget::mutual->Previous();
}
void DbusAdapter::VolumeUp() const
{
Widget::mutual->VolumeUp();
}
void DbusAdapter::VolumeDown() const
{
Widget::mutual->VolumeDown();
}
void DbusAdapter::FullScreen() const
{
Widget::mutual->slotShowMaximized();
}
void DbusAdapter::Exit() const
{
Widget::mutual->slotClose();
}

32
UI/dbusadapter.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef DBUSADAPTER_H
#define DBUSADAPTER_H
#include <QObject>
#include <QDBusConnection>
//#include "UIControl/player/player.h"
#include "mainwidget.h"
class DbusAdapter : public QObject
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.mpris.MediaPlayer2.Player")
public:
explicit DbusAdapter(QObject *parent = nullptr);
public Q_SLOTS:
// mpris 使用
void Stop() const;
void Next() const;
void Play() const;
void Pause() const;
void PlayPause() const;
void Previous() const;
void VolumeUp() const;
void VolumeDown() const;
void FullScreen() const;
void Exit() const;
};
#endif // DBUSADAPTER_H

1205
UI/mainwidget.cpp Normal file

File diff suppressed because it is too large Load Diff

193
UI/mainwidget.h Normal file
View File

@ -0,0 +1,193 @@
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QToolButton>
#include <QStackedWidget>
#include <QResizeEvent>
#include <QMouseEvent>
#include <QPropertyAnimation>
#include <QShortcut>
#include <QPainter>
#include <QPainterPath>
#include <QBrush>
#include <QColor>
#include <QStyleOption>
#include <QPaintEvent>
//DBus
#include <QDBusInterface>
#include <QDBusConnection>
//窗口显示在屏幕中心
#include <QApplication>
#include <QScreen>
//单例需要的头文件
#include <fcntl.h>
//窗体拉起
#include <KWindowSystem>
#include <QProcess>
#include "./dbusadapter.h"
#include "UIControl/base/musicDataBase.h"
#include "UI/tableview/tableone.h"
#include "UIControl/tableview/musiclistmodel.h"
#include "UI/tableview/tablebaseview.h"
#include "UI/base/widgetstyle.h"
#include "UI/sidebar/sidebarwidget.h"
#include "UI/player/playsongarea.h"
#include "UI/tableview/tablehistory.h"
#include "UI/titlebar/titlebar.h"
#include "UI/player/miniwidget.h"
#include "UIControl/base/daemonipcdbus.h"
class Widget : public QWidget
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.ukui.kylin_music.play")
public:
Widget(QStringList str, QWidget *parent = nullptr);
~Widget();
//计算播放历史
void movePlayHistoryWid();
// 毛玻璃
// void paintEvent(QPaintEvent *event);
void transparencyChange();
static Widget *mutual; //指针类型静态成员变量
QProcess *process;
QGSettings *m_transparencyGSettings = nullptr; // 控制面板透明度
double m_transparency = 1.0; // 透明度
public Q_SLOTS:
//mini窗口
void slotShowMiniWidget();
//关闭主窗体
void slotClose();
//最小化
void slotShowMinimized();
//最大化
void slotShowMaximized();
////////// mpris
// 停止播放
void Stop() const;
// 增加音量
void VolumeUp() const;
// 降低音量
void VolumeDown() const;
// 下一首
void Next() const;
// 上一首
void Previous() const;
// 播放
void Play() const;
// 暂停
void Pause() const;
// 播放暂停
void PlayPause() const;
//mini
void slotRecoverNormalWidget();
//mini 关闭窗体
void slotCloseMiniWidget();
//获取当前播放歌曲的名称
void slotPlayingTitle(QString title);
//当前播放歌曲的名称
QString getTitle();
//获取当前播放歌曲的状态
QString getState();
//命令参数
int kylin_music_play_request(QString cmd1, QString cmd2 = "", QString cmd3 = "");
//判断当前点击的按钮是否为歌曲列表(歌单名)
void slotText(QString btnText);
//
void slotReturnPressed();
//构造完成之后的流程事件函数
void creartFinish();
//构造完成后需要弹窗
void setCreatFinishMsg(QString msg);
//如果正在播放,阻止锁屏
void slotStateChanged(playController::PlayState state);
private Q_SLOTS:
void onScreenLock();
void onScreenUnlock();
void onPrepareForShutdown(bool Shutdown);
void onPrepareForSleep(bool isSleep);
void client_get(QString str);
void inputDevice_get(QString str);
void slotPrepareForSwitchuser();
protected:
void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE;
void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
Q_SIGNALS:
//空格键控制播放暂停
void signalSpaceKey();
private:
//初始化dbus
void initDbus();
void initStyle();
//单例
void Single(QStringList path);
//处理双击文件打开时间
void stateMusicFile(QStringList args);
void initAllComponent();
void allConnect();
void initGSettings();
void moveWidget(QString newWidth, QString newHeight);
void changeDarkTheme();
void changeLightTheme();
void importFile(QStringList list);
QStringList getPath(QString playListName);
//初始化音乐
void initMusic();
private:
QDBusInterface *interface;
quint32 m_inhibitValue = 0; // 阻止锁屏cookie
QVBoxLayout *mainVBoxLayout = nullptr;
QHBoxLayout *mainHBoxLayout = nullptr;
TableOne *musicListTable = nullptr;
TableHistory *historyListTable = nullptr;
QGSettings *themeData = nullptr;
SideBarWidget *sideBarWid = nullptr;
PlaySongArea *playSongArea = nullptr;
TitleBar *m_titleBar = nullptr;
miniWidget *m_miniWidget = nullptr;
QWidget *rightVWidget = nullptr;
bool Minimize = false; //最大化和还原俩个状态
//判断是否为第一个实例
bool isFirstObject = false;
QStringList argName;
//歌单名
QString listName;
//正在播放歌曲的title
QString m_playTitle;
//避免初始化流程中触发点击事件
bool m_initFinish = false;
//主界面初始化完成后执行的操作
enum CreatFinishEnum{NONE=0,MESSAGE,OTHER} m_creatFinishEnum = NONE;
QString m_creatFinishMsg;
// ctrl+q 退出窗口快捷键
QShortcut *m_quitWindow;
Q_SIGNALS:
void signalShowGuide();
//刷新歌曲列表界面
void signalRefreshList(QString listName);
//字体
void signalSetFontSize(int);
};
#endif // WIDGET_H

728
UI/player/miniwidget.cpp Normal file
View File

@ -0,0 +1,728 @@
/*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* 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 <https://www.gnu.org/licenses/>.
*/
#include "miniwidget.h"
#include "UI/base/widgetstyle.h"
#include "UI/mainwidget.h"
#include <QDebug>
#define PT_9 9
miniWidget::miniWidget(QWidget *parent) : QFrame(parent)
{
setFixedSize(300,60);
this->setObjectName("miniWidget");
m_mouseState = false;
setWindowFlags(Qt::WindowStaysOnTopHint);
// setWindowFlags(Qt::FramelessWindowHint|Qt::Tool|Qt::WindowStaysOnTopHint);
this->setAttribute(Qt::WA_TranslucentBackground, true); //窗体透明
// this->setWindowTitle(tr("音乐"));
this->setWindowTitle(tr("Music Player"));
setMouseTracking(true);
init_miniWidget();
this->setLayout(m_HMainLayout);
minicolor();
initAction();
initConnect();
initStyle();
}
void miniWidget::initAction()
{
playModeMenu = new QMenu(tr("列表循环"),this);
playMode_Loop_Action = new QAction(QIcon(":/img/default/listloop.png"), tr("列表循环"), playModeMenu);
playMode_Random_Action = new QAction(QIcon(":/img/default/random.png"), tr("随机播放"), playModeMenu);
playMode_Sequential_Action = new QAction(QIcon(":/img/default/sequence.png"), tr("顺序播放"), playModeMenu);
playMode_CurrentItemInLoop_Action = new QAction(QIcon(":/img/default/oneloop.png"), tr("单曲循环"), playModeMenu);
playModeMenu->addAction(playMode_Loop_Action);
playModeMenu->addAction(playMode_Random_Action);
playModeMenu->addAction(playMode_Sequential_Action);
playModeMenu->addAction(playMode_CurrentItemInLoop_Action);
playModeMenu->addMenu(playModeMenu);
}
void miniWidget::mousePressEvent(QMouseEvent *event)
{
m_WindowPos = this->pos();
if(QRect(0,0,width(),height()).contains(event->pos()) && event->button() == Qt::LeftButton)
{
m_MousePos = event->globalPos();
m_mouseState = true;
}
}
void miniWidget::mouseMoveEvent(QMouseEvent *event)
{
if (m_mouseState)
{
move(m_WindowPos + (event->globalPos() - m_MousePos));
}
}
void miniWidget::mouseReleaseEvent(QMouseEvent *)
{
m_mouseState = false;
}
void miniWidget::enterEvent(QEvent *)
{
m_songNameLab->setVisible(false);
m_timeLab->setVisible(false);
m_palyFrame->setVisible(true);
coverWid->setVisible(true);
this->setFixedWidth(328);
}
void miniWidget::leaveEvent(QEvent *)
{
m_songNameLab->setVisible(true);
m_timeLab->setVisible(true);
m_palyFrame->setVisible(false);
coverWid->setVisible(false);
this->setFixedWidth(300);
}
void miniWidget::keyPressEvent(QKeyEvent *event)
{
if(event->key() == Qt::Key_Space)
{
Q_EMIT signalSpaceKey();
}
else if(event->key() == Qt::Key_Right)
{
return;
}
else if(event->key() == Qt::Key_Left)
{
return;
}
QWidget::keyPressEvent(event);
}
void miniWidget::minicolor()
{
if(WidgetStyle::themeColor == 1)
{
m_mainFrame->setStyleSheet("#mainFrame{border-radius:6px;background-color:#252526;}");
m_timeLab->setStyleSheet("QLabel{line-height:12px;color:#8F9399;}");
// m_coverLabel->setPixmap(QPixmap(":/img/fengmian.png").scaled(48,48));
m_coverLabel->setStyleSheet("border-image:url(:/img/fengmian.png);");
m_songNameLab->setStyleSheet("color:#F9F9F9;");
m_preBtn->setStyleSheet("QPushButton{background:transparent;border-radius:15px;border-image:url(:/img/dark/lastsong.png);}"
"QPushButton::hover{border-image:url(:/img/hover/lastsong.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/lastsong.png);}");
// m_playStateBtn->setStyleSheet("QPushButton{border-radius:17px;border-image:url(:/img/default/play2.png);}"
// "QPushButton::hover{border-image:url(:/img/hover/play2.png);}"
// "QPushButton::pressed{border-image:url(:/img/clicked/play2.png);}");
if(playController::getInstance().getState() == playController::PlayState::PLAY_STATE)
{
m_playStateBtn->setStyleSheet("QPushButton{border-radius:17px;border-image:url(:/img/default/pause2.png);}"
"QPushButton::hover{border-image:url(:/img/hover/pause2.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/pause2.png);}");
}
else if(playController::getInstance().getState() == playController::PlayState::PAUSED_STATE)
{
m_playStateBtn->setStyleSheet("QPushButton{border-radius:17px;border-image:url(:/img/default/play2.png);}"
"QPushButton::hover{border-image:url(:/img/hover/play2.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/play2.png);}");
}
else if(playController::getInstance().getState() == playController::PlayState::STOP_STATE)
{
m_playStateBtn->setStyleSheet("QPushButton{border-radius:17px;border-image:url(:/img/default/play2.png);}"
"QPushButton::hover{border-image:url(:/img/hover/play2.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/play2.png);}");
}
slotFavExixtsDark();
m_nextBtn->setStyleSheet("QPushButton{background:transparent;border-radius:15px;border-image:url(:/img/dark/nextsong.png);}"
"QPushButton::hover{border-image:url(:/img/hover/nextsong.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/nextsong.png);}");
coverWid->setStyleSheet("background-color:rgba(0,0,0,0.4);\
border-top-right-radius:6px;border-bottom-right-radius:6px;\
border-top-left-radius:0px;border-bottom-left-radius:0px");
}
else if(WidgetStyle::themeColor == 0)
{
m_mainFrame->setStyleSheet("#mainFrame{border-radius:6px;background-color:#FFFFFF;}");
m_timeLab->setStyleSheet("QLabel{line-height:12px;color:#8F9399;}");
m_coverLabel->setStyleSheet("border-image:url(:/img/fengmian.png);");
// coverPhotoLabel->setStyleSheet("background:transparent;border-image:url(:/img/fengmian.png);");
m_songNameLab->setStyleSheet("color:#303133;");
m_preBtn->setStyleSheet("QPushButton{background:transparent;border-radius:15px;border-image:url(:/img/default/lastsong.png);}"
"QPushButton::hover{border-image:url(:/img/hover/lastsong.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/lastsong.png);}");
// m_playStateBtn->setStyleSheet("QPushButton{border-radius:17px;border-image:url(:/img/default/play2.png);}"
// "QPushButton::hover{border-image:url(:/img/hover/play2.png);}"
// "QPushButton::pressed{border-image:url(:/img/clicked/play2.png);}");
if(playController::getInstance().getState() == playController::PlayState::PLAY_STATE)
{
m_playStateBtn->setStyleSheet("QPushButton{border-radius:17px;border-image:url(:/img/default/pause2.png);}"
"QPushButton::hover{border-image:url(:/img/hover/pause2.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/pause2.png);}");
}
else if(playController::getInstance().getState() == playController::PlayState::PAUSED_STATE)
{
m_playStateBtn->setStyleSheet("QPushButton{border-radius:17px;border-image:url(:/img/default/play2.png);}"
"QPushButton::hover{border-image:url(:/img/hover/play2.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/play2.png);}");
}
else if(playController::getInstance().getState() == playController::PlayState::STOP_STATE)
{
m_playStateBtn->setStyleSheet("QPushButton{border-radius:17px;border-image:url(:/img/default/play2.png);}"
"QPushButton::hover{border-image:url(:/img/hover/play2.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/play2.png);}");
}
slotFavExixts();
m_nextBtn->setStyleSheet("QPushButton{background:transparent;border-radius:15px;border-image:url(:/img/default/nextsong.png);}"
"QPushButton::hover{border-image:url(:/img/hover/nextsong.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/nextsong.png);}");
coverWid->setStyleSheet("background-color:rgba(0,0,0,0.4);\
border-top-right-radius:6px;border-bottom-right-radius:6px;\
border-top-left-radius:0px;border-bottom-left-radius:0px");
}
}
void miniWidget::init_miniWidget()
{
this->setAutoFillBackground(true);
this->setBackgroundRole(QPalette::Base);
m_HMainLayout = new QHBoxLayout();
m_hLayout = new QHBoxLayout();
m_mainFrame = new QFrame;
m_mainFrame->setFixedSize(300,60);
m_mainFrame->setObjectName("mainFrame");
m_hMainLayout = new QHBoxLayout(m_mainFrame);
/*******************************************/
m_coverLabel = new QLabel;
m_coverLabel->setFixedSize(40,40);
m_coverLabel->setCursor(Qt::PointingHandCursor);
/************************************/
m_vInfoLayout = new QVBoxLayout;
m_songNameLab = new MyLabel;
m_songNameLab->setFixedSize(170,28);
// m_songNameLab->setAlignment(Qt::AlignLeft);
m_timeLab = new QLabel;
// m_timeLab->setAlignment(Qt::AlignLeft);
QString playPath = playController::getInstance().getPath();
if(playPath != "")
{
songInfo(playPath);
//根据保存的路径设置我喜欢按钮图标样式
filePath = playPath;
slotPositionChanged(0);
}
else
{
m_songNameLab->setText(tr("Music Player"));
m_timeLab->setText(tr("00:00/00:00"));
}
// m_vInfoLayout->setMargin(3);
// m_vInfoLayout->setSpacing(3);
QWidget *vWidget = new QWidget(this);
vWidget->setFixedHeight(44);
m_vInfoLayout->addStretch();
m_vInfoLayout->addWidget(m_songNameLab,0,Qt::AlignVCenter);
// m_vInfoLayout->addSpacing(6);
m_vInfoLayout->addWidget(m_timeLab,0,Qt::AlignVCenter);
m_vInfoLayout->addStretch();
m_vInfoLayout->setContentsMargins(8,3,0,3);
m_vInfoLayout->setMargin(0);
vWidget->setLayout(m_vInfoLayout);
// m_vInfoLayout->setAlignment(Qt::AlignVCenter);
/******************************************/
m_palyFrame = new QFrame;
m_palyFrame->setFixedWidth(120);
m_palyFrame->setVisible(false);
m_hPlayLayout = new QHBoxLayout(m_palyFrame);
m_preBtn = new QPushButton;
m_preBtn->setFixedSize(16,16);
m_preBtn->setCursor(Qt::PointingHandCursor);
m_playStateBtn = new QPushButton;
m_playStateBtn->setFixedSize(36,36);
m_playStateBtn->setCursor(Qt::PointingHandCursor);
m_nextBtn = new QPushButton;
m_nextBtn->setFixedSize(16,16);
m_nextBtn->setCursor(Qt::PointingHandCursor);
m_hPlayLayout->setMargin(0);
m_hPlayLayout->setSpacing(9);
m_hPlayLayout->addWidget(m_preBtn);
m_hPlayLayout->addWidget(m_playStateBtn);
m_hPlayLayout->addWidget(m_nextBtn);
/****************************************************/
m_loveBtn = new QPushButton;
m_loveBtn->setFixedSize(36, 36);
m_loveBtn->setCursor(Qt::PointingHandCursor);
// m_loveBtn->setFocusPolicy(Qt::NoFocus);
m_loveBtn->setProperty("isWindowButton", 0x1);
m_loveBtn->setProperty("useIconHighlightEffect", 0x2);
m_loveBtn->setFlat(true);
m_orderBtn = new QPushButton;
m_orderBtn->setFixedSize(36, 36);
m_orderBtn->setCursor(Qt::PointingHandCursor);
switch (playController::getInstance().mode()) {
case 1:
m_orderBtn->setIcon(QIcon::fromTheme("media-playlist-repeat-one-symbolic"));
m_orderBtn->setProperty("isWindowButton", 0x1);
m_orderBtn->setProperty("useIconHighlightEffect", 0x2);
m_orderBtn->setFlat(true);
m_orderBtn->setToolTip(tr("CurrentItemInLoop"));
playController::getInstance().setPlaymode(playController::CurrentItemInLoop);
break;
case 3:
m_orderBtn->setIcon(QIcon::fromTheme("media-playlist-repeat-symbolic"));
m_orderBtn->setProperty("isWindowButton", 0x1);
m_orderBtn->setProperty("useIconHighlightEffect", 0x2);
m_orderBtn->setFlat(true);
m_orderBtn->setToolTip(tr("Loop"));
playController::getInstance().setPlaymode(playController::Loop);
break;
case 4:
m_orderBtn->setIcon(QIcon::fromTheme("media-playlist-shuffle-symbolic"));
m_orderBtn->setProperty("isWindowButton", 0x1);
m_orderBtn->setProperty("useIconHighlightEffect", 0x2);
m_orderBtn->setFlat(true);
m_orderBtn->setToolTip(tr("Random"));
playController::getInstance().setPlaymode(playController::Random);
break;
default:
break;
}
/***************************************/
m_vSysLayout = new QVBoxLayout;
coverWid = new QWidget(this);
// coverWid->setAttribute(Qt::WA_TranslucentBackground, true); //窗体透明
m_closeBtn = new QPushButton;
m_closeBtn->setFixedSize(30,30);
m_closeBtn->setCursor(Qt::PointingHandCursor);
m_closeBtn->setIcon(QIcon(":/img/lightshow/close.svg"));
m_closeBtn->setIconSize(QSize(18, 18));
m_closeBtn->setStyleSheet("QPushButton{background:transparent;}");
connect(m_closeBtn,&QPushButton::clicked,this,&miniWidget::close);
//just hide not close
m_recoveryWinBtn = new QPushButton;
m_recoveryWinBtn->setFixedSize(30,30);
m_recoveryWinBtn->setCursor(Qt::PointingHandCursor);
m_recoveryWinBtn->setIcon(QIcon(":/img/lightshow/maximize.svg"));
m_recoveryWinBtn->setIconSize(QSize(14, 14));
m_recoveryWinBtn->setStyleSheet("QPushButton{background-color:transparent;}");
m_vSysLayout->setSpacing(0);
m_vSysLayout->setMargin(0);
m_vSysLayout->addWidget(m_closeBtn);
m_vSysLayout->addWidget(m_recoveryWinBtn);
// m_vSysLayout->addStretch();
coverWid->setLayout(m_vSysLayout);
/********************************************/
// m_hMainLayout->setMargin(10);
m_hMainLayout->addWidget(m_coverLabel);
m_hMainLayout->addWidget(vWidget);
m_hMainLayout->addStretch();
m_hMainLayout->addWidget(m_palyFrame);
m_hMainLayout->addStretch();
m_hMainLayout->addWidget(m_loveBtn);
m_hMainLayout->addWidget(m_orderBtn);
// m_hMainLayout->addLayout(m_vSysLayout);
m_mainFrame->setLayout(m_hMainLayout);
m_HMainLayout->setMargin(0);
m_HMainLayout->addWidget(m_mainFrame);
m_HMainLayout->addWidget(coverWid);
//限制应用字体不随着主题变化
// QFont sizeFont;
// sizeFont.setPixelSize(14);
// m_songNameLab->setFont(sizeFont);
// m_timeLab->setFont(sizeFont);
// QFrame *controlFrame = new QFrame(this);
// controlFrame->setLayout(m_vSysLayout);
// m_hLayout->addWidget(m_mainFrame);
// m_hLayout->addWidget(controlFrame);
// m_mainFrame->setStyleSheet("border-radius:12px;");
}
void miniWidget::slotLableSetFontSize(int size)
{
//默认大小12px,换算成pt为9
double lableBaseFontSize = PT_9;//魔鬼数字,自行处理
double nowFontSize = lableBaseFontSize * double(size) / 11;//11为系统默认大小魔鬼数字自行处理
QFont font;
font.setPointSizeF(nowFontSize);
m_timeLab->setFont(font);
}
//初始化样式
void miniWidget::initStyle()
{
//不接受焦点高亮。解决点击后有蓝框的问题
QList<QPushButton*> list = this->findChildren<QPushButton*>();
for(QPushButton *btn :list)
btn->setFocusPolicy(Qt::NoFocus);
}
void miniWidget::initConnect()
{
connect(&playController::getInstance(),&playController::playerStateChange,this,&miniWidget::playerStateChange);
connect(&playController::getInstance(),&playController::singalChangePath,this,&miniWidget::slotSongInfo);
connect(m_loveBtn,&QPushButton::clicked,this,&miniWidget::slotFav);
connect(m_orderBtn,&QPushButton::clicked,this,&miniWidget::slotPlayModeClicked);
connect(&playController::getInstance(),&playController::signalPlayMode,this,&miniWidget::setPlayMode);
connect(&playController::getInstance(),&playController::signalNotPlaying,this,&miniWidget::slotNotPlaying);
}
void miniWidget::playerStateChange(playController::PlayState newState)
{
if(newState == playController::PlayState::PLAY_STATE)
{
m_playStateBtn->setStyleSheet("QPushButton{border-radius:17px;border-image:url(:/img/default/pause2.png);}"
"QPushButton::hover{border-image:url(:/img/hover/pause2.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/pause2.png);}");
}
else if(newState == playController::PlayState::PAUSED_STATE)
{
m_playStateBtn->setStyleSheet("QPushButton{border-radius:17px;border-image:url(:/img/default/play2.png);}"
"QPushButton::hover{border-image:url(:/img/hover/play2.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/play2.png);}");
}
else if(newState == playController::PlayState::STOP_STATE)
{
m_playStateBtn->setStyleSheet("QPushButton{border-radius:17px;border-image:url(:/img/default/play2.png);}"
"QPushButton::hover{border-image:url(:/img/hover/play2.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/play2.png);}");
}
}
void miniWidget::slotSongInfo(QString path)
{
filePath = path.remove("file://");
QPixmap pix = MusicFileInformation::getInstance().getCoverPhotoPixmap(filePath);
if(pix.isNull())
{
pix = QIcon(":/img/fengmian.png").pixmap(QSize(40,40));
}
else
{
pix = pix.scaled(QSize(40,40),Qt::KeepAspectRatio,Qt::SmoothTransformation);
}
m_coverLabel->setPixmap(pix);
slotFavExixts();
}
void miniWidget::slotText(QString btnText)
{
listName = btnText;
}
void miniWidget::slotFav()
{
if(g_db->checkSongIsInFav(filePath))
{
QList<musicDataStruct> resList;
int ref = g_db->getSongInfoListFromDB(resList, FAV);
int ret = g_db->delMusicFromPlayList(filePath,FAV);
if(ref == DB_OP_SUCC)
{
//根据歌单名title值查询对应歌单列表
// int ref = g_db->getSongInfoListFromDB(resList, "我喜欢");
if(ret == DB_OP_SUCC)
{
for(int i = 0; i < resList.size(); i++)
{
if(resList.at(i).filepath == filePath)
{
playController::getInstance().removeSongFromCurList(FAV, i);
//当前为我喜欢界面才刷新
if(listName == tr("I Love"))
{
Q_EMIT signalRefreshFav(FAV);
}
break;
}
}
}
}
}
else
{
int ref = g_db->addMusicToPlayList(filePath,FAV);
if(ref == DB_OP_SUCC)
{
playController::getInstance().addSongToCurList(FAV, filePath);
if(listName == tr("I Love"))
{
Q_EMIT signalRefreshFav(FAV);
}
}
}
slotFavExixts();
}
void miniWidget::slotFavExixts()
{
if (g_db->checkSongIsInFav(filePath)) {
m_loveBtn->setIcon(QIcon::fromTheme("favorite-new-symbolic"));
m_loveBtn->setProperty("useIconHighlightEffect", 0x4);
} else {
m_loveBtn->setIcon(QIcon::fromTheme("ukui-love-symbolic"));
m_loveBtn->setProperty("useIconHighlightEffect", 0x2);
}
Q_EMIT signalFavBtnChange(filePath);
}
void miniWidget::slotFavExixtsDark()
{
if(g_db->checkSongIsInFav(filePath))
{
m_loveBtn->setIcon(QIcon::fromTheme("favorite-new-symbolic"));
m_loveBtn->setProperty("useIconHighlightEffect", 0x4);
}
else
{
m_loveBtn->setIcon(QIcon::fromTheme("ukui-love-symbolic"));
m_loveBtn->setProperty("useIconHighlightEffect", 0x2);
}
Q_EMIT signalFavBtnChange(filePath);
}
void miniWidget::slotFavIsExixts(QString filePaths)
{
if(g_db->checkSongIsInFav(filePaths))
{
//由于mini歌曲title是播放区传送故判断 ""
if(m_songNameLab->text() == "")
{
return;
}
if(filePath != filePaths)
{
return;
}
m_loveBtn->setIcon(QIcon::fromTheme("favorite-new-symbolic"));
m_loveBtn->setProperty("useIconHighlightEffect", 0x4);
}
else
{
if(filePath != filePaths)
{
return;
}
m_loveBtn->setIcon(QIcon::fromTheme("ukui-love-symbolic"));
m_loveBtn->setProperty("useIconHighlightEffect", 0x2);
}
}
void miniWidget::slotFavBtnChange(QString filePath)
{
if(g_db->checkSongIsInFav(filePath))
{
m_loveBtn->setIcon(QIcon::fromTheme("favorite-new-symbolic"));
m_loveBtn->setProperty("useIconHighlightEffect", 0x4);
}
else
{
m_loveBtn->setIcon(QIcon::fromTheme("ukui-love-symbolic"));
m_loveBtn->setProperty("useIconHighlightEffect", 0x2);
}
}
void miniWidget::songInfo(QString path)
{
QString filepath = path.remove("file://");
musicDataStruct musicStruct;
g_db->getSongInfoFromDB(filepath, musicStruct);
//使用库解析总时间
m_time = musicStruct.time;
if(musicStruct.title == "")
{
m_songNameLab->setText(tr("Music Player"));
m_coverLabel->setPixmap(QIcon(":/img/fengmian.png").pixmap(QSize(40,40)));
}
else
{
m_songNameLab->setText(musicStruct.title);
QPixmap pix = MusicFileInformation::getInstance().getCoverPhotoPixmap(filepath);
if(pix.isNull())
{
pix = QIcon(":/img/fengmian.png").pixmap(QSize(40,40));
}
else
{
pix = pix.scaled(QSize(40,40),Qt::KeepAspectRatio,Qt::SmoothTransformation);
}
m_coverLabel->setPixmap(pix);
}
}
void miniWidget::slotPositionChanged(qint64 position)
{
QString str_time;
int pos = position / 1000;
int hour = static_cast<int>(pos / 3600);
int minutes = static_cast<int>(pos % 3600 / 60);
int seconds = static_cast<int>(pos % 60);
QTime duration(hour, minutes, seconds);
QStringList s = m_time.split(":");
if(s.size() == 3) {
str_time = duration.toString("hh:mm:ss");
}
else {
str_time = duration.toString("mm:ss");
}
QString length = str_time + "/" + m_time;
if(m_time == "")
{
m_timeLab->setText("00:00/00:00");
}
else
{
m_timeLab->setText(length);
}
}
void miniWidget::slotPlayingLab(QString playing)
{
m_songNameLab->setText(playing);
}
void miniWidget::slotTimeLab(QString time)
{
m_timeLab->setText(time);
}
void miniWidget::slotPlayModeClicked()
{
int playMode = playController::getInstance().playmode();
switch (playMode)
{
case 1:
++playMode;
++playMode;
break;
case 3:
++playMode;
break;
case 4:
playMode = 1;
default:
break;
}
setPlayMode(playMode);
playController::getInstance().setMode(static_cast<playController::PlayMode>(playMode));
}
void miniWidget::setPlayMode(int playModel)
{
switch (playModel) {
case 1:
m_orderBtn->setIcon(QIcon::fromTheme("media-playlist-repeat-one-symbolic"));
m_orderBtn->setToolTip(tr("CurrentItemInLoop"));
playController::getInstance().setPlaymode(playController::CurrentItemInLoop);
break;
case 3:
m_orderBtn->setIcon(QIcon::fromTheme("media-playlist-repeat-symbolic"));
m_orderBtn->setToolTip(tr("Loop"));
playController::getInstance().setPlaymode(playController::Loop);
break;
case 4:
m_orderBtn->setIcon(QIcon::fromTheme("media-playlist-shuffle-symbolic"));
m_orderBtn->setToolTip(tr("Random"));
playController::getInstance().setPlaymode(playController::Random);
break;
default:
break;
}
playController::getInstance().setMode(static_cast<playController::PlayMode>(playModel));
}
void miniWidget::slotNotPlaying()
{
m_songNameLab->setText(tr("Music Player"));
m_timeLab->setText("00:00/00:00");
}
void miniWidget::songText(QString songName)
{
QString show_songName = "";
if(songName.length() > 10)
{
show_songName = songName.mid(0,9);
show_songName.append("...");
m_songNameLab->setText(show_songName);
m_songNameLab->setToolTip(songName);
}
else
{
m_songNameLab->setText(songName);
m_songNameLab->setToolTip(songName);
}
}

150
UI/player/miniwidget.h Normal file
View File

@ -0,0 +1,150 @@
/*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* 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 <https://www.gnu.org/licenses/>.
*/
#ifndef MINIWIDGET_H
#define MINIWIDGET_H
#include <QFrame>
#include <QPushButton>
#include <QLabel>
#include <QEvent>
#include <QMouseEvent>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QMenu>
#include <QAction>
#include "UIControl/player/player.h"
#include "UIControl/base/musicDataBase.h"
#include "UI/base/mylabel.h"
#include "UIControl/base/musicfileinformation.h"
const QString miniMainColor = "QFrame{background:#FFFFFF;}";
#pragma pack(push)
#pragma pack(1)
class miniWidget : public QFrame
{
Q_OBJECT
public:
explicit miniWidget(QWidget *parent = nullptr);
void mousePressEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
void enterEvent(QEvent*);
void leaveEvent(QEvent*);
void songText(QString songName); //mini 正在播放
protected:
void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
Q_SIGNALS:
//发送信号mini窗口我喜欢按钮改变
void signalFavBtnChange(QString filePath);
//刷新我喜欢列表
void signalRefreshFav(QString listName);
//空格键控制播放暂停
void signalSpaceKey();
private:
void initAction();
void initConnect();
//初始化样式
void initStyle();
//通过路径查询歌曲的title和时长
void songInfo(QString path);
//显示时长
void slotPositionChanged(qint64 position);
public Q_SLOTS:
void playerStateChange(playController::PlayState newState);
void slotFavExixts();
void slotFavExixtsDark();
void slotFavIsExixts(QString filePaths);
void slotSongInfo(QString path);
void slotFav();
//接收播放区我喜欢按钮改变
void slotFavBtnChange(QString filePath);
//获取正在播放的title
void slotPlayingLab(QString playing);
//获取正在播放的时长
void slotTimeLab(QString time);
//设置播放模式
void slotPlayModeClicked();
//设置图标
void setPlayMode(int playModel);
//没有歌曲在播放
void slotNotPlaying();
//判断当前点击的按钮是否为我喜欢(歌单名)
void slotText(QString btnText);
//字体
void slotLableSetFontSize(int size);
public:
QFrame *m_mainFrame = nullptr;
QLabel *m_coverLabel = nullptr;
QPushButton *m_loveBtn = nullptr;
QPushButton *m_volBtn = nullptr;
QPushButton *m_orderBtn = nullptr;
QPushButton *m_closeBtn = nullptr;
QPushButton *m_recoveryWinBtn = nullptr;
QPushButton *m_preBtn = nullptr;
QPushButton *m_playStateBtn = nullptr;
QPushButton *m_nextBtn = nullptr;
MyLabel *m_songNameLab = nullptr;
QLabel *m_timeLab = nullptr;
void minicolor();
QMenu *playModeMenu = nullptr;
QAction *playMode_Sequential_Action = nullptr;
QAction *playMode_Loop_Action = nullptr;
QAction *playMode_CurrentItemInLoop_Action = nullptr;
QAction *playMode_Random_Action = nullptr;
private:
void init_miniWidget();
bool m_mouseState;
QPoint m_WindowPos;
QPoint m_MousePos;
QHBoxLayout *m_hMainLayout = nullptr;
QHBoxLayout *m_hPlayLayout = nullptr;
QHBoxLayout *m_hLayout = nullptr;
QFrame *m_palyFrame = nullptr;
QWidget *coverWid = nullptr;
QHBoxLayout *m_HMainLayout = nullptr;
QVBoxLayout *m_vInfoLayout = nullptr;
QVBoxLayout *m_vSysLayout = nullptr;
QString filePath;
//歌单名
QString listName;
//正在播放歌曲的歌曲名
QString m_title;
//正在播放歌曲的时长
QString m_time;
};
#pragma pack(pop)
#endif // MINIWIDGET_H

138
UI/player/musicslider.cpp Normal file
View File

@ -0,0 +1,138 @@
#include "musicslider.h"
#include "UI/base/widgetstyle.h"
#include "UIControl/player/player.h"
MusicSlider::MusicSlider(QWidget *parent):QSlider(parent),m_isPlaying(false)
{
//现在进度条样式已基本符合要求,但是两端稍微有点瑕疵,暂搁置
//逻辑也稍微有点问题,如果不选择歌曲,进度条应该禁止操作
//所以将音乐播放进度条独立出来,方便协作和扩展
// this->installEventFilter(this);
initStyle();//初始化样式
}
void MusicSlider::initStyle()
{
this->setFixedHeight(22);
this->setOrientation(Qt::Horizontal);
// this->setMinimum(0);
// this->setMaximum(1000);
if(WidgetStyle::themeColor == 1) {
this->setStyleSheet("QSlider::groove:horizontal{left:0px;right:0px;height: 2px;background: transparent;}"
"QSlider::sub-page:horizontal{background:#3790FA;}"
"QSlider::add-page:horizontal{background:#4D4D4D;}"
);
}
else if(WidgetStyle::themeColor == 0) {
this->setStyleSheet("QSlider::groove:horizontal{left:0px;right:0px;height: 2px;background: transparent;}"
"QSlider::sub-page:horizontal{background:#3790FA;}"
"QSlider::add-page:horizontal{background:#ECEEF5;}"
);
}
}
void MusicSlider::isPlaying(bool isPlaying)
{
m_isPlaying = isPlaying;
}
void MusicSlider::mousePressEvent(QMouseEvent *event)
{
if(m_isPlaying == false)
{
return QSlider::mousePressEvent(event);
}
this->blockSignals(true);
if (event->button() == Qt::LeftButton) //判断左键
{
int value = this->minimum() + ((this->maximum() - this->minimum()) * ((double)event->x())) / (this->width());
setValue(value);
}
}
void MusicSlider::mouseMoveEvent(QMouseEvent *event)
{
if(m_isPlaying == false)
{
return QSlider::mousePressEvent(event);
}
auto rang = this->width();
if(rang == 0)
{
return;
}
auto value = this->minimum() + ((this->maximum() - this->minimum()) * ((double)event->x())) / (this->width());
setValue(value);
}
void MusicSlider::mouseReleaseEvent(QMouseEvent *event)
{
if(m_isPlaying == false)
{
return QSlider::mousePressEvent(event);
}
this->blockSignals(false);
QSlider::mouseReleaseEvent(event);
int range = this->maximum() - minimum();
Q_ASSERT(range != 0);
if(value() <= range)
{
int position = value() * playController::getInstance().getPlayer()->duration() / range;
playController::getInstance().getPlayer()->setPosition(position);
}
}
void MusicSlider::enterEvent(QEvent *event)
{
if(WidgetStyle::themeColor == 1)
{
this->setStyleSheet(
"QSlider::groove:horizontal{left:0px;right:0px;position: absolute;height: 2px;background: transparent;}"
"QSlider::sub-page:horizontal{background:#3790FA;}"
"QSlider::add-page:horizontal{background:#4D4D4D;}"
"QSlider::handle:horizontal {\
width:12px;\
height:12px;\
margin-top: -5px;\
margin-left: 0px;\
margin-bottom: -5px;\
margin-right: 0px;\
border-image:url(:/img/default/point.png);\
}");
} else if (WidgetStyle::themeColor == 0){
this->setStyleSheet(
"QSlider::groove:horizontal{left:0px;right:0px;position: absolute;height: 2px;background: transparent;}"
"QSlider::sub-page:horizontal{background:#3790FA;}"
"QSlider::add-page:horizontal{background:#ECEEF5;}"
"QSlider::handle:horizontal {\
width:12px;\
height:12px;\
margin-top: -5px;\
margin-left: 0px;\
margin-bottom: -5px;\
margin-right: 0px;\
border-image:url(:/img/default/point.png);\
}"
);
}
// QSlider::enterEvent(event);
}
void MusicSlider::leaveEvent(QEvent *event)
{
initStyle();
QSlider::leaveEvent(event);
}
void MusicSlider::wheelEvent(QWheelEvent *e)
{
QWidget::wheelEvent(e);
}

31
UI/player/musicslider.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef MUSICSLIDER_H
#define MUSICSLIDER_H
#include <QObject>
#include <QSlider>
#include <QDebug>
#include <QEvent>
#include <QMouseEvent>
#include <QWheelEvent>
class MusicSlider : public QSlider
{
Q_OBJECT
public:
MusicSlider(QWidget *parent);
void isPlaying(bool isPlaying);
void initStyle();
protected:
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void enterEvent(QEvent *event) Q_DECL_OVERRIDE;
void leaveEvent(QEvent *event) Q_DECL_OVERRIDE;
void wheelEvent(QWheelEvent *e) Q_DECL_OVERRIDE;
private:
private:
bool m_isPlaying;
};
#endif // MUSICSLIDER_H

View File

@ -0,0 +1,178 @@
#include "playbackmodewidget.h"
#include "UI/base/widgetstyle.h"
PlayBackModeWidget::PlayBackModeWidget(QWidget *parent) : QDialog(parent)
{
installEventFilter(this);
setAttribute(Qt::WA_StyledBackground,true);
initWidget();
playModecolor();
// this->setAutoFillBackground(true);
// this->setBackgroundRole(QPalette::Base);
}
void PlayBackModeWidget::initWidget()
{
setFixedSize(118,90);
QVBoxLayout *vLayout = new QVBoxLayout;
vLayout->setAlignment(Qt::AlignTop);
QHBoxLayout *loopLayout = new QHBoxLayout();
loopBtn = new QToolButton(this);
loopBtn->setFixedSize(118,30);
loopBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
loopBtn->setIcon(QIcon::fromTheme("media-playlist-repeat-symbolic"));
loopBtn->setProperty("useIconHighlightEffect", 0x8);
// loopBtn->setProperty("useIconHighlightEffect", 0x2);
// loopBtn->setFocusPolicy(Qt::NoFocus);
// loopBtn->setProperty("isImportant",true);
loopBtn->setIconSize(QSize(16,16));
loopBtn->setText(tr("Loop"));
loopLayout->addWidget(loopBtn);
loopLayout->setMargin(0);
loopLayout->setSpacing(0);
QHBoxLayout *randomLayout = new QHBoxLayout();
randomBtn = new QToolButton(this);
randomBtn->setFixedSize(118,30);
randomBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
randomBtn->setIcon(QIcon::fromTheme("media-playlist-shuffle-symbolic"));
randomBtn->setProperty("useIconHighlightEffect", 0x8);
// randomBtn->setProperty("useIconHighlightEffect", 0x2);
// randomBtn->setFocusPolicy(Qt::NoFocus);
// randomBtn->setProperty("isImportant",true);
randomBtn->setIconSize(QSize(16,16));
randomBtn->setText(tr("Random"));
randomLayout->addWidget(randomBtn);
randomLayout->setMargin(0);
randomLayout->setSpacing(0);
QHBoxLayout *sequentialLayout = new QHBoxLayout();
sequentialBtn = new QToolButton(this);
sequentialBtn->hide();
sequentialBtn->setFixedSize(118,30);
sequentialBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
sequentialBtn->setIcon(QIcon::fromTheme("media-playlist-repeat-symbolic"));
sequentialBtn->setProperty("useIconHighlightEffect", 0x8);
// sequentialBtn->setProperty("useIconHighlightEffect", 0x2);
// sequentialBtn->setFocusPolicy(Qt::NoFocus);
// sequentialBtn->setProperty("isImportant",true);
sequentialBtn->setIconSize(QSize(16,16));
sequentialBtn->setText(tr("Sequential"));
sequentialLayout->addWidget(sequentialBtn);
sequentialLayout->setMargin(0);
sequentialLayout->setSpacing(0);
QHBoxLayout *currentItemInLoopLayout = new QHBoxLayout();
currentItemInLoopBtn = new QToolButton(this);
currentItemInLoopBtn->setFixedSize(118,30);
currentItemInLoopBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
currentItemInLoopBtn->setIcon(QIcon::fromTheme("media-playlist-repeat-one-symbolic"));
currentItemInLoopBtn->setProperty("useIconHighlightEffect", 0x8);
// currentItemInLoopBtn->setProperty("useIconHighlightEffect", 0x2);
// currentItemInLoopBtn->setFocusPolicy(Qt::NoFocus);
// currentItemInLoopBtn->setProperty("isImportant",true);
currentItemInLoopBtn->setIconSize(QSize(16,16));
currentItemInLoopBtn->setText(tr("CurrentItemInLoop"));
currentItemInLoopLayout->addWidget(currentItemInLoopBtn);
currentItemInLoopLayout->setMargin(0);
currentItemInLoopLayout->setSpacing(0);
vLayout->addLayout(loopLayout,Qt::AlignTop);
vLayout->addLayout(randomLayout,Qt::AlignVCenter);
// vLayout->addLayout(sequentialLayout,Qt::AlignVCenter);
vLayout->addLayout(currentItemInLoopLayout,Qt::AlignBottom);
vLayout->setMargin(0);
vLayout->setSpacing(0);
this->setLayout(vLayout);
//限制应用字体不随着主题变化
// QFont sizeFont;
// sizeFont.setPixelSize(14);
// loopBtn->setFont(sizeFont);
// randomBtn->setFont(sizeFont);
// sequentialBtn->setFont(sizeFont);
// currentItemInLoopBtn->setFont(sizeFont);
}
bool PlayBackModeWidget::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
Q_UNUSED(result);
if(eventType != "xcb_generic_event_t")
{
return false;
}
xcb_generic_event_t *event = (xcb_generic_event_t*)message;
switch (event->response_type & ~0x80)
{
case XCB_FOCUS_OUT:
QRect rect(playModePosX, playModePosY, playModePosWidth, playModePosHeight);
if(rect.contains(QCursor::pos(), false))
{
return 0;
}
else
{
this->hide();
break;
}
}
return false;
}
void PlayBackModeWidget::changePlayModePos(int posX, int posY, int width, int height)
{
playModePosX = posX;
playModePosY = posY;
playModePosWidth = width;
playModePosHeight = height;
}
void PlayBackModeWidget::playModecolor()
{
//
// loopBtn->setAutoRaise(true);
// randomBtn->setAutoRaise(true);
// sequentialBtn->setAutoRaise(true);
// currentItemInLoopBtn->setAutoRaise(true);
// if(WidgetStyle::themeColor == 1)
// {
// loopBtn->setStyleSheet("QToolButton{padding-left:7px;background-color:#1F2022;color:#F9F9F9;border-radius:4px;}"
// "QToolButton::hover{background-color:#303032;border-radius:4px;}");
// randomBtn->setStyleSheet("QToolButton{padding-left:7px;background-color:#1F2022;color:#F9F9F9;border-radius:4px;}"
// "QToolButton::hover{background-color:#303032;border-radius:4px;}");
// sequentialBtn->setStyleSheet("QToolButton{padding-left:7px;background-color:#1F2022;color:#F9F9F9;border-radius:4px;}"
// "QToolButton::hover{background-color:#303032;border-radius:4px;}");
// currentItemInLoopBtn->setStyleSheet("QToolButton{padding-left:7px;background-color:#1F2022;color:#F9F9F9;border-radius:4px;}"
// "QToolButton::hover{background-color:#303032;border-radius:4px;}");
// }
// else if(WidgetStyle::themeColor == 0)
// {
// loopBtn->setStyleSheet("QToolButton{padding-left:7px;\
// background-color:#FFFFFF;color:#303133;border-radius:4px;}"
// "QToolButton::hover{background-color:#EEEEEE;border-radius:4px;}");
// randomBtn->setStyleSheet("QToolButton{padding-left:7px;\
// background-color:#FFFFFF;color:#303133;border-radius:4px;}"
// "QToolButton::hover{background-color:#EEEEEE;border-radius:4px;}");
// sequentialBtn->setStyleSheet("QToolButton{padding-left:7px;\
// background-color:#FFFFFF;color:#303133;border-radius:4px;}"
// "QToolButton::hover{background-color:#EEEEEE;border-radius:4px;}");
// currentItemInLoopBtn->setStyleSheet("QToolButton{padding-left:7px;\
// background-color:#FFFFFF;color:#303133;border-radius:4px;}"
// "QToolButton::hover{background-color:#EEEEEE;border-radius:4px;}");
// }
if(WidgetStyle::themeColor == 1)
{
this->setStyleSheet("background-color:#252526;");
}
else if(WidgetStyle::themeColor == 0)
{
this->setStyleSheet("background-color:#FFFFFF;");
}
}

View File

@ -0,0 +1,42 @@
#ifndef PLAYBACKMODEWIDGET_H
#define PLAYBACKMODEWIDGET_H
#include <QWidget>
#include <QDialog>
#include <QVBoxLayout>
#include <QPushButton>
#include <QToolButton>
#include <QIcon>
#include <QMouseEvent>
#include <QFocusEvent>
#include <QEvent>
#include <QDebug>
#include <QX11Info>
class PlayBackModeWidget : public QDialog
{
Q_OBJECT
public:
explicit PlayBackModeWidget(QWidget *parent = nullptr);
public:
void changePlayModePos(int posX, int posY, int width, int height);
void playModecolor();
public:
QToolButton *loopBtn = nullptr;
QToolButton *randomBtn = nullptr;
QToolButton *sequentialBtn = nullptr;
QToolButton *currentItemInLoopBtn = nullptr;
protected:
bool nativeEvent(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;
Q_SIGNALS:
private:
void initWidget();
private:
int playModePosX;
int playModePosY;
int playModePosWidth;
int playModePosHeight;
};
#endif // PLAYBACKMODEWIDGET_H

996
UI/player/playsongarea.cpp Normal file
View File

@ -0,0 +1,996 @@
#include <ukui-log4qt.h>
#include "playsongarea.h"
#include "UI/base/widgetstyle.h"
#include "UI/base/xatom-helper.h"
#include "UIControl/base/musicDataBase.h"
#define VOLUME 5
#define PT_9 9
PlaySongArea::PlaySongArea(QWidget *parent) : QWidget(parent)
{
resize(750,88);
setAttribute(Qt::WA_StyledBackground,true);
this->setObjectName("PlaySongArea");
initWidget();
initConnect();
playcolor();
}
void PlaySongArea::initWidget()
{
QVBoxLayout *m_vmainLayout = new QVBoxLayout(this);
QHBoxLayout *m_hmainLayout = new QHBoxLayout();
m_mainLayout = new QHBoxLayout();
preBtn = new QPushButton;
preBtn->setFixedSize(18,18);
preBtn->setCursor(Qt::PointingHandCursor);
preBtn->setToolTip(tr("Previous"));
playBtn = new QPushButton(this);
playBtn->setFixedSize(36,36);
playBtn->setCursor(Qt::PointingHandCursor);
// playBtn->setToolTip("播放");
// playBtn->setToolTip(tr("play"));
nextBtn = new QPushButton;
nextBtn->setFixedSize(18,18);
nextBtn->setCursor(Qt::PointingHandCursor);
// nextBtn->setToolTip("下一首");
nextBtn->setToolTip(tr("Next"));
volumeBtn = new QPushButton(this);
volumeBtn->setFixedSize(36, 36);
volumeBtn->setCursor(Qt::PointingHandCursor);
volumeBtn->setToolTip(tr("Volume")); //音量
int volume = playController::getInstance().getVolume();
if(volume == 0)
{
volumeBtn->setIcon(QIcon::fromTheme("audio-volume-muted-symbolic"));
volumeBtn->setProperty("isWindowButton", 0x1);
volumeBtn->setProperty("useIconHighlightEffect", 0x2);
volumeBtn->setFlat(true);
}
else if(volume > 0 && volume <= 33)
{
volumeBtn->setIcon(QIcon::fromTheme("audio-volume-low-symbolic"));
volumeBtn->setProperty("isWindowButton", 0x1);
volumeBtn->setProperty("useIconHighlightEffect", 0x2);
volumeBtn->setFlat(true);
}
else if(volume > 33 && volume <= 77)
{
volumeBtn->setIcon(QIcon::fromTheme("audio-volume-medium-symbolic"));
volumeBtn->setProperty("isWindowButton", 0x1);
volumeBtn->setProperty("useIconHighlightEffect", 0x2);
volumeBtn->setFlat(true);
}
else
{
volumeBtn->setIcon(QIcon::fromTheme("audio-volume-high-symbolic"));
volumeBtn->setProperty("isWindowButton", 0x1);
volumeBtn->setProperty("useIconHighlightEffect", 0x2);
volumeBtn->setFlat(true);
}
m_volSliderWid = new SliderWidget(this);
MotifWmHints hint;
hint.flags = MWM_HINTS_FUNCTIONS|MWM_HINTS_DECORATIONS;
hint.functions = MWM_FUNC_ALL;
hint.decorations = MWM_DECOR_BORDER;
XAtomHelper::getInstance()->setWindowMotifHint(m_volSliderWid->winId(), hint);
m_volSliderWid->hide();
m_playBackModeWid = new PlayBackModeWidget(this);
MotifWmHints hints;
hints.flags = MWM_HINTS_FUNCTIONS|MWM_HINTS_DECORATIONS;
hints.functions = MWM_FUNC_ALL;
hints.decorations = MWM_DECOR_BORDER;
XAtomHelper::getInstance()->setWindowMotifHint(m_playBackModeWid->winId(), hints);
m_playBackModeWid->hide();
hSlider = new MusicSlider(this);
hSlider->setValue(0);
hSlider->setDisabled(true);
favBtn = new QPushButton;
favBtn->setFixedSize(36, 36);
// favBtn->setCheckable(true); //按钮是否是可点击状态,默认不点击
// favBtn->setChecked(false);
favBtn->setCursor(Qt::PointingHandCursor);
favBtn->setFocusPolicy(Qt::NoFocus);
favBtn->setToolTip(tr("Favourite"));
favBtn->setProperty("isWindowButton", 0x1);
favBtn->setProperty("useIconHighlightEffect", 0x2);
favBtn->setFlat(true);
//播放模式
playModeBtn = new QToolButton;
playModeBtn->setFixedSize(36, 36);
playModeBtn->setCursor(Qt::PointingHandCursor);
playModeBtn->setPopupMode(QToolButton::InstantPopup);
playModeBtn->setProperty("isWindowButton", 0x1);
playModeBtn->setProperty("useIconHighlightEffect", 0x2);
playModeBtn->setAutoRaise(true);
switch (playController::getInstance().mode()) {
case 1:
playModeBtn->setIcon(QIcon::fromTheme("media-playlist-repeat-one-symbolic"));
//playModeBtn->setProperty("isWindowButton", 0x1);
//playModeBtn->setProperty("useIconHighlightEffect", 0x2);
//playModeBtn->setFlat(true);
playModeBtn->setToolTip(tr("CurrentItemInLoop"));
playController::getInstance().setPlaymode(playController::CurrentItemInLoop);
break;
case 3:
playModeBtn->setIcon(QIcon::fromTheme("media-playlist-repeat-symbolic"));
//playModeBtn->setProperty("isWindowButton", 0x1);
//playModeBtn->setProperty("useIconHighlightEffect", 0x2);
//playModeBtn->setFlat(true);
playModeBtn->setToolTip(tr("Loop"));
playController::getInstance().setPlaymode(playController::Loop);
break;
case 4:
playModeBtn->setIcon(QIcon::fromTheme("media-playlist-shuffle-symbolic"));
//playModeBtn->setProperty("isWindowButton", 0x1);
//playModeBtn->setProperty("useIconHighlightEffect", 0x2);
//playModeBtn->setFlat(true);
playModeBtn->setToolTip(tr("Random"));
playController::getInstance().setPlaymode(playController::Random);
break;
default:
break;
}
m_playMode = new QMenu(this);
loopAct = new QAction(tr("Loop"));
loopAct->setIcon(QIcon::fromTheme("media-playlist-repeat-symbolic"));
randomAct = new QAction(tr("Random"));
randomAct->setIcon(QIcon::fromTheme("media-playlist-shuffle-symbolic"));
currentItemInLoopAct = new QAction(tr("CurrentItemInLoop"));
currentItemInLoopAct->setIcon(QIcon::fromTheme("media-playlist-repeat-one-symbolic"));
m_playMode->addAction(loopAct);
m_playMode->addAction(randomAct);
m_playMode->addAction(currentItemInLoopAct);
// playModeBtn->setMenu(m_playMode);
//历史播放列表
listBtn = new QPushButton;
listBtn->setFixedSize(36, 36);
listBtn->setCheckable(true); //按钮是否是可点击状态,默认不点击
// listBtn->setChecked(false); //只可检查按钮是否是点击状态,保存点击的状态
listBtn->setCursor(Qt::PointingHandCursor);
listBtn->setIcon(QIcon::fromTheme("ukui-play-list-symbolic"));
listBtn->setProperty("isWindowButton", 0x1);
listBtn->setProperty("useIconHighlightEffect", 0x2);
listBtn->setFlat(true);
listBtn->setToolTip(tr("Play List"));
coverPhotoLabel = new QLabel(this);
coverPhotoLabel->setFixedSize(40,40);
playingLabel = new MyLabel(this);
playingLabel->setFixedHeight(28);
// playingLabel->setText(tr("Music Player"));
timeLabel = new QLabel(this);
// timeLabel->setText(tr("00:00/00:00"));
QString playPath = playController::getInstance().getPath();
if(playPath != "")
{
slotSongInfo(playPath);
slotPositionChanged(0);
}
else
{
playingLabel->setText(tr("Music Player"));
timeLabel->setText(tr("00:00/00:00"));
}
QWidget *letfWid = new QWidget(this);
QWidget *centreWid = new QWidget(this);
QWidget *rightWid = new QWidget(this);
QHBoxLayout *leftLayout = new QHBoxLayout(letfWid);
QWidget *vWidget = new QWidget(letfWid);
vWidget->setFixedHeight(44);
QVBoxLayout *vLayout = new QVBoxLayout();
vLayout->addStretch();
vLayout->addWidget(playingLabel,0,Qt::AlignVCenter);
// vLayout->addSpacing(8);
vLayout->addWidget(timeLabel,0,Qt::AlignVCenter);
vLayout->addStretch();
vLayout->setContentsMargins(8,3,0,3);
vLayout->setMargin(0);
vWidget->setLayout(vLayout);
leftLayout->addWidget(coverPhotoLabel,Qt::AlignVCenter);
leftLayout->addWidget(vWidget,Qt::AlignVCenter);
leftLayout->setMargin(0);
QHBoxLayout *playLayout = new QHBoxLayout(centreWid);
playLayout->addStretch(0);
playLayout->addWidget(preBtn,Qt::AlignHCenter);
playLayout->addSpacing(12);
playLayout->addWidget(playBtn,Qt::AlignHCenter);
playLayout->addSpacing(12);
playLayout->addWidget(nextBtn,Qt::AlignHCenter);
playLayout->addStretch();
playLayout->setMargin(0);
QHBoxLayout *rightLayout = new QHBoxLayout(rightWid);
rightLayout->addStretch(0);
rightLayout->addWidget(volumeBtn,Qt::AlignRight);
rightLayout->addSpacing(8);
rightLayout->addWidget(favBtn,Qt::AlignRight);
rightLayout->addSpacing(8);
rightLayout->addWidget(playModeBtn,Qt::AlignRight);
rightLayout->addSpacing(8);
rightLayout->addWidget(listBtn,Qt::AlignRight);
rightLayout->setContentsMargins(0,14,30,14);
rightLayout->setMargin(0);
letfWid->setLayout(leftLayout);
// letfWid->setStyleSheet("background: red;");
centreWid->setLayout(playLayout);
// centreWid->setStyleSheet("background: blue;");
rightWid->setLayout(rightLayout);
// rightWid->setStyleSheet("background: green;");
m_hmainLayout->addWidget(hSlider);
m_hmainLayout->setMargin(0);
m_hmainLayout->setSpacing(0);
m_mainLayout->addWidget(letfWid);
// m_mainLayout->addStretch(0);
m_mainLayout->addWidget(centreWid);
// m_mainLayout->addStretch(0);
m_mainLayout->addWidget(rightWid);
// m_mainLayout->setMargin(0);
m_mainLayout->setSpacing(0);
m_mainLayout->setStretchFactor(letfWid,1);
m_mainLayout->setStretchFactor(centreWid,1);
m_mainLayout->setStretchFactor(rightWid,1);
m_mainLayout->setContentsMargins(25,0,25,0);
m_vmainLayout->addLayout(m_hmainLayout);
m_vmainLayout->addLayout(m_mainLayout);
m_vmainLayout->setContentsMargins(0,0,0,8);
m_vmainLayout->setSpacing(0);
this->setLayout(m_vmainLayout);
//限制应用字体不随着主题变化
// QFont sizeFont;
// sizeFont.setPixelSize(14);
// playingLabel->setFont(sizeFont);
// timeLabel->setFont(sizeFont);
}
void PlaySongArea::slotLableSetFontSize(int size)
{
//默认大小12px,换算成pt为9
double lableBaseFontSize = PT_9;//魔鬼数字,自行处理
double nowFontSize = lableBaseFontSize * double(size) / 11;//11为系统默认大小魔鬼数字自行处理
QFont font;
font.setPointSizeF(nowFontSize);
timeLabel->setFont(font);
}
void PlaySongArea::initConnect()
{
//
connect(preBtn,&QPushButton::clicked,this,&PlaySongArea::slotPrevious);
connect(playBtn,&QPushButton::clicked,this,&PlaySongArea::slotPlayClicked);
connect(nextBtn,&QPushButton::clicked,this,&PlaySongArea::slotNext);
connect(listBtn,&QPushButton::clicked,this,&PlaySongArea::listBtnClicked);
connect(m_volSliderWid->vSlider,&QSlider::valueChanged,this,&PlaySongArea::slotVolumeChanged);
connect(volumeBtn,&QPushButton::clicked,this,&PlaySongArea::slotVolSliderWidget);
connect(favBtn,&QPushButton::clicked,this,&PlaySongArea::slotFav);
//connect(playModeBtn,&QPushButton::clicked,this,&PlaySongArea::slotPlayBackModeChanged);
connect(playModeBtn,&QToolButton::clicked,this,&PlaySongArea::slotPlayBackModeChanged);
// connect(m_playBackModeWid->loopBtn,&QToolButton::clicked,this,&PlaySongArea::slotLoopClicked);
// connect(m_playBackModeWid->randomBtn,&QToolButton::clicked,this,&PlaySongArea::slotRandomClicked);
// connect(m_playBackModeWid->sequentialBtn,&QToolButton::clicked,this,&PlaySongArea::slotSequentialClicked);
// connect(m_playBackModeWid->currentItemInLoopBtn,&QToolButton::clicked,this,&PlaySongArea::slotCurrentItemInLoopClicked);
connect(loopAct,&QAction::triggered,this,&PlaySongArea::slotLoopClicked);
connect(randomAct,&QAction::triggered,this,&PlaySongArea::slotRandomClicked);
connect(currentItemInLoopAct,&QAction::triggered,this,&PlaySongArea::slotCurrentItemInLoopClicked);
connect(&playController::getInstance(),&playController::singalChangePath,this,&PlaySongArea::slotSongInfo);
connect(&playController::getInstance(),&playController::playerStateChange,this,&PlaySongArea::playerStateChange);
connect(playController::getInstance().getPlayer(),SIGNAL(positionChanged(qint64)),this,SLOT(slotPositionChanged(qint64)));
connect(playController::getInstance().getPlayer(),SIGNAL(durationChanged(qint64)),this,SLOT(slotDurationChanged(qint64)));
connect(hSlider,SIGNAL(sliderPressed()),this,SLOT(slotSlidePressd()));
connect(hSlider,SIGNAL(sliderReleased()),this,SLOT(slotSlideReleased()));
connect(hSlider,&MusicSlider::valueChanged,this,&PlaySongArea::setPosition);
connect(&playController::getInstance(),&playController::signalPlayMode,this,&PlaySongArea::setPlayMode);
connect(&playController::getInstance(),&playController::signalNotPlaying,this,&PlaySongArea::slotNotPlaying);
connect(&playController::getInstance(),&playController::signalSetValue,this,&PlaySongArea::slotSetValue);
connect(&playController::getInstance(),&playController::signalVolume,this,&PlaySongArea::slotVolume);
connect(&playController::getInstance(),&playController::signalMute,this,&PlaySongArea::slotMute);
}
void PlaySongArea::slotVolumeChanged(int values)
{
playController::getInstance().setVolume(values);
int volume = playController::getInstance().getVolume();
KyInfo() << "volume = " << volume;
if(volume == 0)
{
volumeBtn->setIcon(QIcon::fromTheme("audio-volume-muted-symbolic"));
}
else if(volume > 0 && volume <= 33)
{
volumeBtn->setIcon(QIcon::fromTheme("audio-volume-low-symbolic"));
}
else if(volume > 33 && volume <= 77)
{
volumeBtn->setIcon(QIcon::fromTheme("audio-volume-medium-symbolic"));
}
else
{
volumeBtn->setIcon(QIcon::fromTheme("audio-volume-high-symbolic"));
}
}
void PlaySongArea::volumeIncrease()
{
int value = m_volSliderWid->vSlider->value() + VOLUME;
if(value > 100)
value = 100;
m_volSliderWid->vSlider->setValue(value);
}
void PlaySongArea::volumeReduce()
{
int value = m_volSliderWid->vSlider->value() - VOLUME;
if(value < 0)
value = 0;
m_volSliderWid->vSlider->setValue(value);
}
void PlaySongArea::slotVolSliderWidget()
{
if(m_volSliderWid->isVisible())
{
m_volSliderWid->hide();
}
else
{
moveVolSliderWid();
m_volSliderWid->show();
m_volSliderWid->raise();
}
}
void PlaySongArea::slotVolume(int volume)
{
m_volSliderWid->vSlider->setValue(volume);
}
void PlaySongArea::slotMute(bool mute)
{
if (mute) {
volumeBtn->setIcon(QIcon::fromTheme("audio-volume-muted-symbolic"));
}
}
void PlaySongArea::slotText(QString btnText)
{
listName = btnText;
}
void PlaySongArea::slotFav()
{
if(g_db->checkSongIsInFav(filePath))
{
QList<musicDataStruct> resList;
int ref = g_db->getSongInfoListFromDB(resList, FAV);
int ret = g_db->delMusicFromPlayList(filePath,FAV);
if(ref == DB_OP_SUCC)
{
// Q_EMIT signalAddFromFavButton("我喜欢");
//根据歌单名title值查询对应歌单列表
// int ref = g_db->getSongInfoListFromDB(resList, "我喜欢");
if(ret == DB_OP_SUCC)
{
for(int i = 0; i < resList.size(); i++)
{
if(resList.at(i).filepath == filePath)
{
playController::getInstance().removeSongFromCurList(FAV, i);
//刷新我喜欢界面
if(listName == tr("I Love"))
{
Q_EMIT signalRefreshFav(FAV);
}
break;
}
}
}
}
}
else
{
int ref = g_db->addMusicToPlayList(filePath,FAV);
if(ref == DB_OP_SUCC)
{
playController::getInstance().addSongToCurList(FAV, filePath);
// Q_EMIT signalDelFromFavButton("我喜欢");
if(listName == tr("I Love"))
{
Q_EMIT signalRefreshFav(FAV);
}
}
// Q_EMIT signalRefreshFav("我喜欢");
}
slotFavExixts();
// if(favBtn->isVisible())
// {
//// favBtn->setStyleSheet("QPushButton{border-image:url(:/img/clicked/love1.png);}");
// favBtn->setIcon(QIcon(":/img/clicked/love1.png"));
// }
// else
// {
// favBtn->setIcon(QIcon(":/img/default/loveblack2.png"));
// }
//// favBtn->setIcon(QIcon(":/img/clicked/love1.png"));
}
void PlaySongArea::slotPlayBackModeChanged()
{
movePlayMenu();
// if(m_playBackModeWid->isVisible())
// {
// m_playBackModeWid->hide();
// }
// else
// {
// movePlayModeWid();
// m_playBackModeWid->show();
// m_playBackModeWid->raise();
// }
}
void PlaySongArea::slotLoopClicked()
{
playController::getInstance().setMode(playController::Loop);
playModeBtn->setIcon(QIcon::fromTheme("media-playlist-repeat-symbolic"));
playModeBtn->setToolTip(tr("Loop"));
playController::getInstance().setPlaymode(playController::Loop);
m_playBackModeWid->hide();
}
void PlaySongArea::slotRandomClicked()
{
playController::getInstance().setMode(playController::Random);
playModeBtn->setIcon(QIcon::fromTheme("media-playlist-shuffle-symbolic"));
playModeBtn->setToolTip(tr("Random"));
playController::getInstance().setPlaymode(playController::Random);
m_playBackModeWid->hide();
}
void PlaySongArea::slotSequentialClicked()
{
// playModeBtn->setIcon(QIcon::fromTheme("media-playlist-repeat-symbolic"));
// playModeBtn->setToolTip(tr("Sequential"));
// playController::getInstance().setPlaymode(playController::Sequential);
// m_playBackModeWid->hide();
}
void PlaySongArea::slotCurrentItemInLoopClicked()
{
playController::getInstance().setMode(playController::CurrentItemInLoop);
playModeBtn->setIcon(QIcon::fromTheme("media-playlist-repeat-one-symbolic"));
playModeBtn->setToolTip(tr("CurrentItemInLoop"));
playController::getInstance().setPlaymode(playController::CurrentItemInLoop);
m_playBackModeWid->hide();
}
void PlaySongArea::setPlayMode(int playModel)
{
switch (playModel) {
case 1:
playModeBtn->setIcon(QIcon::fromTheme("media-playlist-repeat-one-symbolic"));
playModeBtn->setToolTip(tr("CurrentItemInLoop"));
playController::getInstance().setPlaymode(playController::CurrentItemInLoop);
break;
// case 2:
// playModeBtn->setIcon(QIcon::fromTheme("media-playlist-repeat-symbolic"));
// playModeBtn->setToolTip(tr("Sequential"));
// playController::getInstance().setPlaymode(playController::Sequential);
// break;
case 3:
playModeBtn->setIcon(QIcon::fromTheme("media-playlist-repeat-symbolic"));
playModeBtn->setToolTip(tr("Loop"));
playController::getInstance().setPlaymode(playController::Loop);
break;
case 4:
playModeBtn->setIcon(QIcon::fromTheme("media-playlist-shuffle-symbolic"));
playModeBtn->setToolTip(tr("Random"));
playController::getInstance().setPlaymode(playController::Random);
break;
default:
break;
}
playController::getInstance().setMode(static_cast<playController::PlayMode>(playModel));
}
void PlaySongArea::slotSongInfo(QString path)
{
musicDataStruct musicStruct;
if(!path.isEmpty()) {
filePath = path.remove("file://");
g_db->getSongInfoFromDB(filePath, musicStruct);
}
//使用库解析总时间
m_time = musicStruct.time;
if(musicStruct.title == "")
{
playingLabel->setText(tr("Music Player"));
coverPhotoLabel->setPixmap(QIcon(":/img/fengmian.png").pixmap(QSize(40,40)));
Q_EMIT signalPlayingLab(tr("Music Player"));
}
else
{
hSlider->isPlaying(true);
playingLabel->setText(musicStruct.title);
QPixmap pix = MusicFileInformation::getInstance().getCoverPhotoPixmap(filePath);
setCoverPhotoPixmap(pix);
Q_EMIT signalPlayingLab(musicStruct.title);
}
slotFavExixts();
}
void PlaySongArea::setCoverPhotoPixmap(QPixmap pixmap)
{
if(pixmap.isNull())
{
pixmap = QIcon(":/img/fengmian.png").pixmap(QSize(40,40));
}
else
{
pixmap = pixmap.scaled(QSize(40,40),Qt::KeepAspectRatio,Qt::SmoothTransformation);
}
coverPhotoLabel->setPixmap(pixmap);
}
void PlaySongArea::playerStateChange(playController::PlayState newState)
{
if(newState == playController::PlayState::PLAY_STATE)
{
playBtn->setStyleSheet("QPushButton{border-radius:17px;border-image:url(:/img/default/pause2.png);}"
"QPushButton::hover{border-image:url(:/img/hover/pause2.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/pause2.png);}");
}
else if(newState == playController::PlayState::PAUSED_STATE)
{
playBtn->setStyleSheet("QPushButton{border-radius:17px;border-image:url(:/img/default/play2.png);}"
"QPushButton::hover{border-image:url(:/img/hover/play2.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/play2.png);}");
}
else if(newState == playController::PlayState::STOP_STATE)
{
playBtn->setStyleSheet("QPushButton{border-radius:17px;border-image:url(:/img/default/play2.png);}"
"QPushButton::hover{border-image:url(:/img/hover/play2.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/play2.png);}");
}
}
void PlaySongArea::slotPositionChanged(qint64 position)
{
QString str_time;
int pos = position / 1000;
int hour = static_cast<int>(pos / 3600);
int minutes = static_cast<int>(pos % 3600 / 60);
int seconds = static_cast<int>(pos % 60);
QTime duration(hour, minutes, seconds);
QStringList s = m_time.split(":");
if(s.size() == 3) {
str_time = duration.toString("hh:mm:ss");
}
else {
str_time = duration.toString("mm:ss");
}
QString length = str_time + "/" + m_time;
if(m_time == "")
{
timeLabel->setText("00:00/00:00");
Q_EMIT signalTimeLab("00:00/00:00");
}
else
{
timeLabel->setText(length);
Q_EMIT signalTimeLab(length);
}
if(hSlider->signalsBlocked())
{
return;
}
hSlider->blockSignals(true);
hSlider->setValue(static_cast<int>(position));
hSlider->blockSignals(false);
hSlider->update();
}
void PlaySongArea::slotNotPlaying()
{
//滑块可以点击,无法跳转
hSlider->isPlaying(false);
//禁用
hSlider->setDisabled(true);
hSlider->setValue(0);
playingLabel->setText(tr("Music Player"));
timeLabel->setText("00:00/00:00");
}
void PlaySongArea::slotSetValue()
{
hSlider->setValue(0);
}
void PlaySongArea::slotDurationChanged(qint64 duration)
{
hSlider->setRange(0,static_cast<int>(duration));
hSlider->setEnabled(duration>0);
hSlider->setPageStep(static_cast<int>(duration)/10);
}
void PlaySongArea::slotSlidePressd()
{
playController::getInstance().getPlayer()->pause();
}
void PlaySongArea::slotSlideReleased()
{
playController::getInstance().getPlayer()->play();
}
void PlaySongArea::setPosition(int position)
{
// qDebug() << "position" << position;
// qDebug() << "playController::getInstance().getPlayer()->position()" << playController::getInstance().getPlayer()->position();
// qDebug() << "playController::getInstance().getPlayer()->position() - position" << playController::getInstance().getPlayer()->position() - position;
//判断播放的位置 - 滑块的位置是否大于0.1s
if (qAbs(playController::getInstance().getPlayer()->position() - position) > 99)
playController::getInstance().getPlayer()->setPosition(position);
}
void PlaySongArea::resizeEvent(QResizeEvent *event)
{
moveVolSliderWid();
movePlayModeWid();
playingLabel->setFixedWidth(this->width()/3.6);
QWidget::resizeEvent(event);
}
void PlaySongArea::moveVolSliderWid()
{
QPoint volumePos = volumeBtn->mapToGlobal(volumeBtn->rect().center());
m_volSliderWid->adjustSize();
QSize size = m_volSliderWid->size();
volumePos.setX(volumePos.x() - size.width() / 2);
volumePos.setY(volumePos.y() - size.height() - 25);
QSize volumSize = volumeBtn->size();
int newPosX = volumePos.x() + size.width() / 2 - volumSize.width() / 2 + 1;
int newPosY = volumePos.y() + 25 + size.height() - volumSize.height() / 2 + 1;
m_volSliderWid->changeVolumePos(newPosX, newPosY, volumSize.width(), volumSize.height());
m_volSliderWid->move(volumePos);
}
void PlaySongArea::movePlayModeWid()
{
QPoint modePos = playModeBtn->mapToGlobal(playModeBtn->rect().center());
m_playBackModeWid->adjustSize();
QSize size = m_playBackModeWid->size();
modePos.setX(modePos.x() - size.width() / 2);
modePos.setY(modePos.y() - size.height() - 25);
QSize modeSize = playModeBtn->size();
int newPosX = modePos.x() + size.width() / 2 - modeSize.width() / 2 + 1;
int newPosY = modePos.y() + 25 + size.height() - modeSize.height() / 2 + 1;
m_playBackModeWid->changePlayModePos(newPosX, newPosY, modeSize.width(), modeSize.height());
m_playBackModeWid->move(modePos);
}
void PlaySongArea::movePlayMenu()
{
QPoint modePos = playModeBtn->mapToGlobal(playModeBtn->rect().center());
QSize size = m_playMode->sizeHint();
modePos.setX(modePos.x() - size.width() + 70);
modePos.setY(modePos.y() - size.height() - 15);
m_playMode->move(modePos);
m_playMode->show();
// m_playMode->exec(modePos);
}
void PlaySongArea::slotPlayClicked()
{
KyInfo() << QString("%1 %2")
.arg("slotPlayCliked: ")
.arg(playController::getInstance().getPlayer()->state());
if(playController::getInstance().getPlayer()->state() == MMediaPlayer::PlayingState)
{
playController::getInstance().getPlayer()->pause();
}
else if(playController::getInstance().getPlayer()->state() == MMediaPlayer::PausedState)
{
playController::getInstance().getPlayer()->play();
int currentVolume = playController::getInstance().getVolume();
KyInfo() << "currentVolume = " << currentVolume
<< "playState = " << playController::getInstance().getPlayer()->state();
delayMsecond(100);
playController::getInstance().setVolume(currentVolume);
}
else if(playController::getInstance().getPlayer()->state() == MMediaPlayer::StoppedState)
{
playMeta();
int currentVolume = playController::getInstance().getVolume();
KyInfo() << "currentVolume = " << currentVolume
<< "playState = " << playController::getInstance().getPlayer()->state();
delayMsecond(100);
playController::getInstance().setVolume(currentVolume);
}
}
void PlaySongArea::playMeta()
{
QString playListName = playController::getInstance().getPlayListName();
QString playPath = playController::getInstance().getPath();
QList<musicDataStruct> resList;
QStringList filePaths;
int index;
int ret = g_db->getSongInfoListFromDB(resList, playListName);
if(playPath != "")
{
if(ret == DB_OP_SUCC)
{
if(resList.size() == 0)
{
return;
}
for(int i = 0; i < resList.size(); i++)
{
filePaths << resList.at(i).filepath;
if(resList.at(i).filepath == playPath)
{
index = i;
}
}
playController::getInstance().setCurPlaylist(playListName, filePaths);
playController::getInstance().play(playListName, index);
}
}
else
{
QList<musicDataStruct> resList;
int ref = g_db->getSongInfoListFromDB(resList,ALLMUSIC);
if(ref == DB_OP_SUCC)
{
if(resList.size() == 0)
{
return;
}
if(resList.size() >= 1)
{
QStringList paths;
for(int i = 0; i < resList.size(); i++)
{
paths << resList.at(i).filepath;
}
playController::getInstance().setCurPlaylist(ALLMUSIC,paths);
playController::getInstance().play(ALLMUSIC,0);
}
}
}
}
void PlaySongArea::slotPrevious()
{
playController::getInstance().onPreviousSong();
}
void PlaySongArea::delayMsecond(unsigned int msec)
{
QEventLoop loop;//定义一个新的事件循环
QTimer::singleShot(msec, &loop, SLOT(quit()));//创建单次定时器,槽函数为事件循环的退出函数
loop.exec();//事件循环开始执行,程序会卡在这里,直到定时时间到,本循环被退出
}
void PlaySongArea::slotNext()
{
playController::getInstance().onNextSong();
}
void PlaySongArea::listBtnClicked()
{
Q_EMIT showHistoryListBtnClicked();
}
void PlaySongArea::slotFavExixts()
{
if (g_db->checkSongIsInFav(filePath)) {
favBtn->setIcon(QIcon::fromTheme("favorite-new-symbolic"));
favBtn->setProperty("useIconHighlightEffect", 0x4);
} else {
favBtn->setIcon(QIcon::fromTheme("ukui-love-symbolic"));
favBtn->setProperty("useIconHighlightEffect", 0x2);
}
Q_EMIT signalFavBtnChange(filePath);
}
void PlaySongArea::slotFavExixtsDark()
{
if(g_db->checkSongIsInFav(filePath))
{
favBtn->setIcon(QIcon::fromTheme("favorite-new-symbolic"));
favBtn->setProperty("useIconHighlightEffect", 0x4);
}
else
{
favBtn->setIcon(QIcon::fromTheme("ukui-love-symbolic"));
favBtn->setProperty("useIconHighlightEffect", 0x2);
}
Q_EMIT signalFavBtnChange(filePath);
}
void PlaySongArea::slotHistoryBtnChecked(bool checked)
{
listBtn->setChecked(checked);
}
void PlaySongArea::slotFavIsExixts(QString filePaths)
{
if(g_db->checkSongIsInFav(filePaths))
{
if(playingLabel->text() == tr("Music Player"))
{
return;
}
//用于判断添加到我喜欢的歌曲是否是当前播放的歌曲, 如果是刷新, 如果不是不做操作
if(filePath != filePaths)
{
return;
}
favBtn->setIcon(QIcon::fromTheme("favorite-new-symbolic"));
favBtn->setProperty("useIconHighlightEffect", 0x4);
}
else
{
//用于判断添加到我喜欢的歌曲是否是当前播放的歌曲, 如果是刷新, 如果不是不做操作
if(filePath != filePaths)
{
return;
}
favBtn->setIcon(QIcon::fromTheme("ukui-love-symbolic"));
favBtn->setProperty("useIconHighlightEffect", 0x2);
}
}
void PlaySongArea::slotFavBtnChange(QString filePath)
{
if(g_db->checkSongIsInFav(filePath))
{
if(playingLabel->text() == tr("Music Player"))
{
return;
}
favBtn->setIcon(QIcon::fromTheme("favorite-new-symbolic"));
favBtn->setProperty("useIconHighlightEffect", 0x4);
}
else
{
favBtn->setIcon(QIcon::fromTheme("ukui-love-symbolic"));
favBtn->setProperty("useIconHighlightEffect", 0x2);
}
}
void PlaySongArea::playcolor()
{
if(WidgetStyle::themeColor == 1)
{
this->setStyleSheet("#PlaySongArea{background-color:#252526;}");
preBtn->setStyleSheet("QPushButton{background:transparent;border-radius:15px;border-image:url(:/img/dark/lastsong.png);}"
"QPushButton::hover{border-image:url(:/img/hover/lastsong.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/lastsong.png);}");
if(playController::getInstance().getState() == playController::PlayState::PLAY_STATE)
{
playBtn->setStyleSheet("QPushButton{border-radius:17px;border-image:url(:/img/default/pause2.png);}"
"QPushButton::hover{border-image:url(:/img/hover/pause2.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/pause2.png);}");
}
else if(playController::getInstance().getState() == playController::PlayState::PAUSED_STATE)
{
playBtn->setStyleSheet("QPushButton{border-radius:17px;border-image:url(:/img/default/play2.png);}"
"QPushButton::hover{border-image:url(:/img/hover/play2.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/play2.png);}");
}
else if(playController::getInstance().getState() == playController::PlayState::STOP_STATE)
{
playBtn->setStyleSheet("QPushButton{border-radius:17px;border-image:url(:/img/default/play2.png);}"
"QPushButton::hover{border-image:url(:/img/hover/play2.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/play2.png);}");
}
nextBtn->setStyleSheet("QPushButton{background:transparent;border-radius:15px;border-image:url(:/img/dark/nextsong.png);}"
"QPushButton::hover{border-image:url(:/img/hover/nextsong.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/nextsong.png);}");
slotFavExixtsDark();
// listBtn->setIcon(QIcon(":/img/dark/icon_songlist_h@2x.png"));
// listBtn->setStyleSheet("QPushButton{background:transparent;border-image:url(:/img/dark/icon_songlist_h@2x.png);}"
// "QPushButton::hover{border-image:url(:/img/clicked/songlist.png);}"
// "QPushButton::checked{border-image:url(:/img/clicked/songlist.png);}");
coverPhotoLabel->setStyleSheet("background:transparent;border-image:url(:/img/fengmian.png);");
playingLabel->setStyleSheet("color:#F9F9F9;line-height:14px;");
hSlider->initStyle();
}
else if(WidgetStyle::themeColor == 0)
{
this->setStyleSheet("#PlaySongArea{background-color:#FFFFFF;}");
preBtn->setStyleSheet("QPushButton{background:transparent;border-radius:15px;border-image:url(:/img/default/lastsong.png);}"
"QPushButton::hover{border-image:url(:/img/hover/lastsong.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/lastsong.png);}");
// playBtn->setStyleSheet("QPushButton{border-radius:17px;border-image:url(:/img/default/play2.png);}"
// "QPushButton::hover{border-image:url(:/img/hover/play2.png);}"
// "QPushButton::pressed{border-image:url(:/img/clicked/play2.png);}");
if(playController::getInstance().getState() == playController::PlayState::PLAY_STATE)
{
playBtn->setStyleSheet("QPushButton{border-radius:17px;border-image:url(:/img/default/pause2.png);}"
"QPushButton::hover{border-image:url(:/img/hover/pause2.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/pause2.png);}");
}
else if(playController::getInstance().getState() == playController::PlayState::PAUSED_STATE)
{
playBtn->setStyleSheet("QPushButton{border-radius:17px;border-image:url(:/img/default/play2.png);}"
"QPushButton::hover{border-image:url(:/img/hover/play2.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/play2.png);}");
}
else if(playController::getInstance().getState() == playController::PlayState::STOP_STATE)
{
playBtn->setStyleSheet("QPushButton{border-radius:17px;border-image:url(:/img/default/play2.png);}"
"QPushButton::hover{border-image:url(:/img/hover/play2.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/play2.png);}");
}
nextBtn->setStyleSheet("QPushButton{background:transparent;border-radius:15px;border-image:url(:/img/default/nextsong.png);}"
"QPushButton::hover{border-image:url(:/img/hover/nextsong.png);}"
"QPushButton::pressed{border-image:url(:/img/clicked/nextsong.png);}");
slotFavExixts();
// listBtn->setStyleSheet("QPushButton{background:transparent;border-image:url(:/img/default/songlist.png)}"
// "QPushButton::hover{border-image:url(:/img/clicked/songlist.png);}"
// "QPushButton::checked{border-image:url(:/img/clicked/songlist.png);}");
coverPhotoLabel->setStyleSheet("background:transparent;border-image:url(:/img/fengmian.png);");
playingLabel->setStyleSheet("line-height:14px;color:#303133;");
timeLabel->setStyleSheet("line-height:12px;color:#8F9399;");
hSlider->initStyle();
}
}

171
UI/player/playsongarea.h Normal file
View File

@ -0,0 +1,171 @@
#ifndef PLAYSONGAREA_H
#define PLAYSONGAREA_H
#include <QWidget>
#include <QTimerEvent>
#include <QTimer>
#include <QEventLoop>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QVariant>
#include <QShortcut>
#include <QMenu>
#include <QDebug>
#include "sliderwidget.h"
#include "playbackmodewidget.h"
#include "musicslider.h"
#include "UIControl/player/player.h"
#include "UIControl/tableview/musiclistmodel.h"
#include "UI/tableview/tableone.h"
#include "UI/base/mylabel.h"
#include "UI/player/sliderwidget.h"
class PlaySongArea : public QWidget
{
Q_OBJECT
public:
explicit PlaySongArea(QWidget *parent = nullptr);
public:
// static PlaySongArea& getInstance()
// {
// static PlaySongArea instance;
// return instance;
// }
public:
void playcolor();
public:
SliderWidget *m_volSliderWid = nullptr;
PlayBackModeWidget *m_playBackModeWid = nullptr;
//播放列表
QPushButton *listBtn = nullptr;
Q_SIGNALS:
void showHistoryListBtnClicked();
//发送信号播放区我喜欢按钮改变
void signalFavBtnChange(QString filePath);
//正在播放title
void signalPlayingLab(QString playing);
//正在播放时长
void signalTimeLab(QString time);
//刷新我喜欢界面
void signalRefreshFav(QString listName);
// //按钮添加到我喜欢刷新界面
// void signalAddFromFavButton(QString listName);
// //按钮从我喜欢删除刷新界面
// void signalDelFromFavButton(QString listName);
public Q_SLOTS:
//上一首
void slotPrevious();
void delayMsecond(unsigned int msec); // 延时函数,不阻塞线程
//播放/暂停
void slotPlayClicked();
//下一首
void slotNext();
//播放通过路径判断我喜欢是否存在此歌曲
void slotFavExixts();
//深色模式图标样式
void slotFavExixtsDark();
//动态添加判断我喜欢是否存在
void slotFavIsExixts(QString filePaths);
//显示音量界面
void slotVolSliderWidget();
//音量调高
void volumeIncrease();
//音量调低
void volumeReduce();
//改变音量
void slotVolumeChanged(int values);
//系统音乐音量改变
void slotVolume(int volume);
//系统音乐音量是否静音( mute = true 静音
void slotMute(bool mute);
//我喜欢按钮
void slotFav();
//改变播放模式弹窗
void slotPlayBackModeChanged();
//判断当前点击的按钮是否为我喜欢(歌单名)
void slotText(QString btnText);
void slotLoopClicked();
void slotRandomClicked();
void slotSequentialClicked();
void slotCurrentItemInLoopClicked();
void setPlayMode(int playModel);
//获取当前播放歌曲的路径
void slotSongInfo(QString path);
void setCoverPhotoPixmap(QPixmap pixmap);
void playerStateChange(playController::PlayState newState);
//播放滑动条相关
void slotPositionChanged(qint64 position);
void slotDurationChanged(qint64 duration);
void setPosition(int position);
void slotSlidePressd();
void slotSlideReleased();
//接收mini窗口我喜欢按钮改变
void slotFavBtnChange(QString filePath);
//没有歌曲在播放
void slotNotPlaying();
//设置进度条归 0
void slotSetValue();
//播放历史按钮选中状态改变
void slotHistoryBtnChecked(bool checked);
//字体
void slotLableSetFontSize(int size);
protected:
void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE;
private:
void initWidget();
void initConnect();
//移动音量
void moveVolSliderWid();
//计算新的播放模式
void movePlayModeWid();
//计算新的播放模式菜单
void movePlayMenu();
void listBtnClicked();
void playMeta();
private:
QHBoxLayout *m_mainLayout = nullptr;
//上一首
QPushButton *preBtn = nullptr;
//播放/暂停
QPushButton *playBtn = nullptr;
//下一首
QPushButton *nextBtn = nullptr;
//音量
QPushButton *volumeBtn = nullptr;
//我喜欢
QPushButton *favBtn = nullptr;
//播放模式
//QPushButton *playModeBtn;
QToolButton *playModeBtn = nullptr;
//歌词
QPushButton *lyricBtn = nullptr;
//封面
QLabel *coverPhotoLabel = nullptr;
//正在播放
MyLabel *playingLabel = nullptr;
//时长
QLabel *timeLabel = nullptr;
//播放滑动条
MusicSlider *hSlider = nullptr;
//保存库解析总时间
QString m_time = nullptr;
//路径
QString filePath = nullptr;
//歌单名
QString listName = nullptr;
//播放模式菜单
QMenu *m_playMode = nullptr;
QAction *loopAct = nullptr;
QAction *randomAct = nullptr;
QAction *currentItemInLoopAct = nullptr;
};
#endif // PLAYSONGAREA_H

130
UI/player/searchedit.cpp Normal file
View File

@ -0,0 +1,130 @@
#include "searchedit.h"
#include "UI/base/xatom-helper.h"
SearchEdit::SearchEdit(QWidget *parent) : KSearchLineEdit(parent)
{
setContextMenuPolicy(Qt::DefaultContextMenu);
setCompleter(nullptr); // kdk自带记忆功能取消搜索记忆功能
connect(this, &SearchEdit::textChanged,this,&SearchEdit::slotTextChanged);
connect(this, &SearchEdit::returnPressed,this,&SearchEdit::slotReturnPressed);
// connect(this, &SearchEdit::editingFinished,this,&SearchEdit::slotEditingFinished);
m_result = new SearchResult(m_mainWidget);
m_result->setSearchEdit(this);
MotifWmHints hints;
hints.flags = MWM_HINTS_FUNCTIONS|MWM_HINTS_DECORATIONS;
hints.functions = MWM_FUNC_ALL;
hints.decorations = MWM_DECOR_BORDER;
XAtomHelper::getInstance()->setWindowMotifHint(m_result->winId(), hints);
moveSearchResult();
}
void SearchEdit::keyPressEvent(QKeyEvent *event)
{
if(m_result == nullptr)
{
return;
}
if(event->key() == Qt::Key_Up)
{
m_result->selectUp();
}
if(event->key() == Qt::Key_Down)
{
m_result->selectDown();
}
QLineEdit::keyPressEvent(event);
}
void SearchEdit::focusInEvent(QFocusEvent *event)
{
this->setFocus();
return QLineEdit::focusInEvent(event);
}
void SearchEdit::focusOutEvent(QFocusEvent *event)
{
this->clearFocus();
return QLineEdit::focusOutEvent(event);
}
void SearchEdit::slotTextChanged()
{
if (m_result == nullptr) {
return;
}
QString alltext = this->text();
if (alltext.isEmpty()) {
m_result->hide();
return;
}/* else {
m_result->show();
m_result->raise();
}*/
this->setCursorPosition(this->cursorPosition());
auto text = this->text().trimmed();
if (this->text().size() == 0) {
m_result->hide();
return;
}
if (text.length() >= 1) {
m_result->setListviewSearchString(text);
moveSearchResult();
m_result->show();
// m_result->activateWindow();
// m_result->raise();
m_result->autoResize();
// m_result->setFocusPolicy(Qt::StrongFocus);
// m_result->raise();
} else {
m_result->hide();
}
}
void SearchEdit::slotReturnPressed()
{
if (m_result == nullptr) {
return;
}
if (m_result->getCurrentIndex() >= 0) {
m_result->onReturnPressed();
m_result->hide();
return;
}
auto text = QString(this->text().trimmed());
if(text.length() == 0)
return;
m_result->hide();
Q_EMIT signalReturnPressed(tr("Search Result"));
Q_EMIT signalReturnText(text);
}
void SearchEdit::setWidget(QWidget *mainWidget)
{
m_mainWidget = mainWidget;
}
void SearchEdit::moveSearchResult()
{
m_result->setFixedWidth(240);
QPoint resultPos = this->mapToGlobal(this->rect().bottomLeft());
resultPos.setX(resultPos.x());
resultPos.setY(resultPos.y() + 12);
QSize editSize = this->size();
int newPosX = resultPos.x();
int newPosY = resultPos.y() - editSize.height() - 12;
m_result->changeSrearchResultPos(newPosX, newPosY, editSize.width(), editSize.height());
m_result->move(resultPos);
}

51
UI/player/searchedit.h Normal file
View File

@ -0,0 +1,51 @@
#ifndef SEARCHEDIT_H
#define SEARCHEDIT_H
#include <QLineEdit>
#include <QFocusEvent>
#include <QDebug>
#include "UI/player/searchresult.h"
//#include "kwidget.h"
#include "ksearchlineedit.h"
using namespace kdk;
class SearchResult;
class SearchEdit : public KSearchLineEdit
{
Q_OBJECT
public:
SearchEdit(QWidget *parent = nullptr);
public:
void setWidget(QWidget *mainWidget);
void moveSearchResult();
Q_SIGNALS:
void sigFoucusIn();
//发送展示搜索结果界面
void signalReturnPressed(QString searchEdit);
//搜索的关键字
void signalReturnText(QString text);
protected:
void keyPressEvent(QKeyEvent *event);
void focusInEvent(QFocusEvent *event);
void focusOutEvent(QFocusEvent *event);
public Q_SLOTS:
void slotTextChanged();
void slotReturnPressed();
public:
SearchResult *m_result = nullptr;
private:
QWidget *m_mainWidget = nullptr;
};
#endif // SEARCHEDIT_H

436
UI/player/searchresult.cpp Normal file
View File

@ -0,0 +1,436 @@
#include "searchresult.h"
#define PT_11 11
#include <QScrollArea>
#include <QScrollBar>
#include <X11/keysym.h>
#include <X11/extensions/xtestconst.h>
#include <X11/extensions/XInput.h>
#include <X11/extensions/XTest.h>
#include "UI/base/xatom-helper.h"
SearchResult::SearchResult(QWidget *parent) : QWidget(parent)
{
this->setAutoFillBackground(true);
this->setBackgroundRole(QPalette::Base);
this->setWindowFlag(Qt::Tool);
//窗体禁止拖动
this->setProperty("useStyleWindowManager", false);
vlayout = new QVBoxLayout(this);
vlayout->setContentsMargins(4, 4, 4, 4);
vlayout->setSpacing(0);
// this->setLayout(vlayout);
//歌曲名
m_MusicLabel = new QLabel(tr("Music"),this);
m_MusicLabel->setFixedHeight(36);
m_MusicLabel->setIndent(28);
// m_MusicLabel->setContentsMargins(32, 0, 0, 0);
m_MusicView = new MusicSearchListview(this);
m_MusicView->setSearchType(SearchType::TitleType);
m_MusicView->setMinimumWidth(232);
// m_MusicView->setContentsMargins(28, 0, 28, 0);
// m_SingerFrame = new QFrame(this);
// m_SingerFrame->setFrameShape(QFrame::HLine);
// m_SingerFrame->setFrameShadow(QFrame::Raised);
// m_SingerFrame->setLineWidth(2);
//歌手
m_SingerLabel = new QLabel(tr("Singer"),this);
m_SingerLabel->setFixedHeight(36);
m_SingerLabel->setIndent(28);
// m_SingerLabel->setContentsMargins(32, 0, 0, 0);
m_SingerView = new MusicSearchListview(this);
m_SingerView->setSearchType(SearchType::SingerType);
m_SingerView->setMinimumWidth(232);
// m_SingerView->setContentsMargins(32, 0, 0, 0);
// m_AlbumFrame = new QFrame(this);
// m_AlbumFrame->setFrameShape(QFrame::HLine);
// m_AlbumFrame->setFrameShadow(QFrame::Raised);
// m_AlbumFrame->setLineWidth(2);
//专辑
m_AlbumLabel = new QLabel(tr("Album"),this);
m_AlbumLabel->setFixedHeight(36);
m_AlbumLabel->setIndent(28);
// m_AlbumLabel->setContentsMargins(32, 0, 0, 0);
m_AlbumView = new MusicSearchListview(this);
m_AlbumView->setSearchType(SearchType::AlbumType);
m_AlbumView->setMinimumWidth(232);
// m_AlbumView->setContentsMargins(32, 0, 0, 0);
m_MusicLabel->setStyleSheet("color:#8F9399;");
m_SingerLabel->setStyleSheet("color:#8F9399;");
m_AlbumLabel->setStyleSheet("color:#8F9399;");
vlayout->addWidget(m_MusicLabel, 1);
vlayout->addWidget(m_MusicView, 0);
// vlayout->addWidget(m_SingerFrame);
vlayout->addWidget(m_SingerLabel, 1);
vlayout->addWidget(m_SingerView, 0);
// vlayout->addWidget(m_AlbumFrame);
vlayout->addWidget(m_AlbumLabel, 1);
vlayout->addWidget(m_AlbumView, 0);
QScrollArea *scrollArea = new QScrollArea(this);
scrollArea->setFrameStyle(0);
scrollArea->setWidgetResizable(true);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scrollArea->setFrameShape(QFrame::NoFrame);
QWidget *vWid = new QWidget(this);
vWid->setLayout(vlayout);
scrollArea->setWidget(vWid);
scrollArea->verticalScrollBar()->setProperty("drawScrollBarGroove",false);
QVBoxLayout *sideLayout = new QVBoxLayout(this);
sideLayout->addWidget(scrollArea);
sideLayout->setMargin(0);
sideLayout->setSpacing(0);
this->setLayout(sideLayout);
autoResize();
connect(m_MusicView,&MusicSearchListview::clicked,this,&SearchResult::slotMusicItemClicked);
connect(m_SingerView,&MusicSearchListview::clicked,this,&SearchResult::slotSingerItemClicked);
connect(m_AlbumView,&MusicSearchListview::clicked,this,&SearchResult::slotAlbumItemClicked);
}
SearchResult::~SearchResult()
{
}
void SearchResult::keyPressEvent(QKeyEvent *event)
{
// m_searchEdit->raise();
m_searchEdit->activateWindow();
// QApplication::sendEvent(m_searchEdit,event);
setCursorWithXEvent();
if (event->key() == Qt::Key_Return) {
this->hide();
return;
}
if (event->key() == Qt::Key_Backspace) {
QApplication::sendEvent(m_searchEdit,event);
Q_EMIT m_searchEdit->textChanged(m_searchEdit->text());
return;
}
m_key = event->nativeVirtualKey();
QTimer *timer = new QTimer;
timer->setSingleShot(true);
connect(timer,&QTimer::timeout,this,[=]{
Display *display = XOpenDisplay(NULL);
XTestFakeKeyEvent(display, XKeysymToKeycode(display,m_key), 1, 10);
XFlush(display);
XTestFakeKeyEvent(display, XKeysymToKeycode(display,m_key), 0, 10);
XFlush(display);
XCloseDisplay(display);
});
connect(timer,&QTimer::timeout,timer,&QTimer::deleteLater);
timer->start(200);
// Q_EMIT m_searchEdit->textChanged(m_searchEdit->text());
}
void SearchResult::setCursorWithXEvent()
{
double device = QGuiApplication::primaryScreen()->devicePixelRatio();
if (device <= 0) {
device = 1;
}
QPoint point = m_searchEdit->mapToGlobal(QPoint(m_searchEdit->rect().topRight().x() - 10,m_searchEdit->rect().topRight().y() - 5));
XEvent xEvent;
//该值返回一个指向存储区 &xEvent 的指针。
memset(&xEvent, 0, sizeof(XEvent));
//默认显示
Display *display = QX11Info::display();
xEvent.type = ButtonPress;
xEvent.xbutton.button = Button1;
//this->effectiveWinId()本机父窗口系统标识符
xEvent.xbutton.window = this->effectiveWinId();
if (point.y() < 5) {
xEvent.xbutton.x = point.x() * device;
xEvent.xbutton.y = point.y() * device;
} else {
xEvent.xbutton.x = this->mapFromGlobal(point).x() * device;
xEvent.xbutton.y = this->mapFromGlobal(point).y() * device;
}
xEvent.xbutton.x_root = point.x()* device;
xEvent.xbutton.y_root = point.y()* device;
xEvent.xbutton.display = display;
XSendEvent(display,this->effectiveWinId(),False,ButtonPressMask,&xEvent);
XFlush(display);
XSendEvent(display,this->effectiveWinId(),False,ButtonReleaseMask,&xEvent);
XFlush(display);
}
void SearchResult::autoResize()
{
if (m_searchEdit != nullptr) {
if (m_searchEdit->text() != "") {
this->show();
this->raise();
this->activateWindow();
}
}
int lineHeight = 0;
int lineShowCount = 0;
if (m_MusicView->rowCount() == 0) {
m_MusicLabel->hide();
m_MusicView->hide();
} else {
m_MusicLabel->show();
m_MusicView->show();
lineShowCount++;
m_MusicView->setFixedHeight(m_MusicView->rowCount() * 36);
}
if (m_SingerView->rowCount() == 0) {
m_SingerLabel->hide();
m_SingerView->hide();
} else {
m_SingerLabel->show();
m_SingerView->show();
lineShowCount++;
m_SingerView->setFixedHeight(m_SingerView->rowCount() * 36);
}
if (m_AlbumView->rowCount() == 0) {
m_AlbumLabel->hide();
m_AlbumView->hide();
} else {
m_AlbumLabel->show();
m_AlbumView->show();
lineShowCount++;
m_AlbumView->setFixedHeight(m_AlbumView->rowCount() * 36);
}
if (lineShowCount > 0) {
lineHeight = 2 * (lineShowCount - 1);
}
int total = 0;
total += m_MusicLabel->isVisible() ? m_MusicLabel->height() : 0;
total += m_MusicView->isVisible() ? m_MusicView->height() : 0;
// total += s_ArtistLine->isVisible() ? s_ArtistLine->height() : 0;
total += m_SingerLabel->isVisible() ? m_SingerLabel->height() : 0;
total += m_SingerView->isVisible() ? m_SingerView->height() : 0;
// total += s_AblumLine->isVisible() ? s_AblumLine->height() : 0;
total += m_AlbumLabel->isVisible() ? m_AlbumLabel->height() : 0;
total += m_AlbumView->isVisible() ? m_AlbumView->height() : 0;
total += lineHeight;
if (m_MusicView->isHidden() && m_SingerView->isHidden() && m_AlbumLabel->isHidden()) {
if (total > 500) {
setFixedHeight(500);
} else {
setFixedHeight(total);
}
} else {
if (total > 500) {
setFixedHeight(500);
} else {
setFixedHeight(total + 28);
}
}
}
void SearchResult::setListviewSearchString(const QString &str)
{
//搜索歌曲候选:<=5个
m_MusicView->setSearchText(str);
m_SingerView->setSearchText(str);
m_AlbumView->setSearchText(str);
m_Count = m_MusicView->rowCount()
+ m_AlbumView->rowCount()
+ m_SingerView->rowCount();
m_CurrentIndex = -1;
}
void SearchResult::setLineEditSearchString(const QString &str)
{
// if (m_searchEdit) {
// m_searchEdit->blockSignals(true);
// m_searchEdit->setText(str);
// m_searchEdit->blockSignals(false);
// }
}
void SearchResult::selectUp()
{
if (m_Count == 0) {
return;
}
if (m_CurrentIndex < 0) {
return;
}
m_CurrentIndex --;
if (m_CurrentIndex < m_MusicView->rowCount()) {
m_MusicView->setCurrentIndexInt(m_CurrentIndex);
m_SingerView->setCurrentIndexInt(-1);
m_AlbumView->setCurrentIndexInt(-1);
} else if (m_CurrentIndex >= m_MusicView->rowCount() - 1
&& m_CurrentIndex < (m_MusicView->rowCount() + m_SingerView->rowCount())) {
m_SingerView->setCurrentIndexInt(m_CurrentIndex
- m_MusicView->rowCount());
m_MusicView->setCurrentIndexInt(-1);
m_AlbumView->setCurrentIndexInt(-1);
} else {
m_AlbumView->setCurrentIndexInt(m_CurrentIndex
- m_MusicView->rowCount()
- m_SingerView->rowCount());
m_MusicView->setCurrentIndexInt(-1);
m_SingerView->setCurrentIndexInt(-1);
}
m_MusicView->update();
m_SingerView->update();
m_AlbumView->update();
}
void SearchResult::selectDown()
{
if (m_Count == 0) {
return;
}
if (m_CurrentIndex >= m_Count - 1) {
return;
}
m_CurrentIndex ++;
if (m_CurrentIndex < m_MusicView->rowCount()) {
m_MusicView->setCurrentIndexInt(m_CurrentIndex);
m_SingerView->setCurrentIndexInt(-1);
m_AlbumView->setCurrentIndexInt(-1);
} else if (m_CurrentIndex >= m_MusicView->rowCount() - 1
&& m_CurrentIndex < (m_MusicView->rowCount() + m_SingerView->rowCount())) {
m_SingerView->setCurrentIndexInt(m_CurrentIndex
- m_MusicView->rowCount());
m_MusicView->setCurrentIndexInt(-1);
m_AlbumView->setCurrentIndexInt(-1);
} else {
m_AlbumView->setCurrentIndexInt(m_CurrentIndex
- m_MusicView->rowCount()
- m_SingerView->rowCount());
m_MusicView->setCurrentIndexInt(-1);
m_SingerView->setCurrentIndexInt(-1);
m_MusicView->clearSelection();
m_SingerView->clearSelection();
}
m_MusicView->update();
m_SingerView->update();
m_AlbumView->update();
}
int SearchResult::getCurrentIndex()
{
return m_CurrentIndex;
}
void SearchResult::setSearchEdit(SearchEdit *edit)
{
m_searchEdit = edit;
}
bool SearchResult::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
Q_UNUSED(result);
if(eventType != "xcb_generic_event_t")
{
return false;
}
xcb_generic_event_t *event = (xcb_generic_event_t*)message;
switch (event->response_type & ~0x80)
{
case XCB_FOCUS_OUT:
QRect rect(m_resultPosX, m_resultPosY, m_resultPosWidth, m_resultPosHeight);
if(rect.contains(QCursor::pos(), false))
{
return 0;
}
else
{
this->hide();
break;
}
}
return false;
}
void SearchResult::changeSrearchResultPos(int posX, int posY, int width, int height)
{
m_resultPosX = posX;
m_resultPosY = posY;
m_resultPosWidth = width;
m_resultPosHeight = height;
}
void SearchResult::onReturnPressed()
{
if (m_MusicView->getIndexInt() >= 0) {
m_MusicView->onReturnPressed();
} else if (m_SingerView->getIndexInt() >= 0) {
m_SingerView->onReturnPressed();
} else if (m_AlbumView->getIndexInt() >= 0) {
m_AlbumView->onReturnPressed();
}
}
void SearchResult::slotLableSetFontSize(int size)
{
//默认大小12px,换算成pt为9
double lableBaseFontSize = PT_11;//魔鬼数字,自行处理
double nowFontSize = lableBaseFontSize * double(size) / 11;//11为系统默认大小魔鬼数字自行处理
QFont font;
font.setPointSizeF(nowFontSize);
m_MusicLabel->setFont(font);
m_SingerLabel->setFont(font);
m_AlbumLabel->setFont(font);
}
void SearchResult::slotMusicItemClicked(QModelIndex index)
{
this->hide();
musicDataStruct metaPtr = index.data(Qt::UserRole + SearchType::TitleType).value<musicDataStruct>();
Q_EMIT signalFilePath(metaPtr.filepath);
}
void SearchResult::slotSingerItemClicked(QModelIndex index)
{
this->hide();
musicDataStruct metaPtr = index.data(Qt::UserRole + SearchType::SingerType).value<musicDataStruct>();
Q_EMIT signalSongListBySinger(metaPtr.singer);
}
void SearchResult::slotAlbumItemClicked(QModelIndex index)
{
this->hide();
musicDataStruct metaPtr = index.data(Qt::UserRole + SearchType::AlbumType).value<musicDataStruct>();
Q_EMIT signalSongListByAlbum(metaPtr.album);
}

82
UI/player/searchresult.h Normal file
View File

@ -0,0 +1,82 @@
#ifndef SEARCHRESULT_H
#define SEARCHRESULT_H
#include <QWidget>
#include <QKeyEvent>
#include <QDialog>
#include <QVBoxLayout>
#include <QLabel>
#include <QListView>
#include <QTreeView>
#include <QFrame>
#include <QX11Info>
#include <QApplication>
#include <QScreen>
#include <QTimer>
#include "UI/search/musicsearchlistview.h"
#include "UI/player/searchedit.h"
class MusicSearchListview;
class SearchEdit;
class SearchResult : public QWidget
{
Q_OBJECT
public:
explicit SearchResult(QWidget *parent = nullptr);
~SearchResult();
public:
void autoResize();
//设置各列表搜索关键字
void setListviewSearchString(const QString &str);
//点击列表时设置lineEdit显示文字
void setLineEditSearchString(const QString &str);
void selectUp();
void selectDown();
int getCurrentIndex();
void setSearchEdit(SearchEdit *edit);
void changeSrearchResultPos(int posX, int posY, int width, int height);
public Q_SLOTS:
void onReturnPressed();
void slotLableSetFontSize(int size);
void slotMusicItemClicked(QModelIndex index);
void slotSingerItemClicked(QModelIndex index);
void slotAlbumItemClicked(QModelIndex index);
protected:
bool nativeEvent(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;
void keyPressEvent(QKeyEvent *event);
Q_SIGNALS:
void signalFilePath(QString path);
void signalSongListBySinger(QString singer);
void signalSongListByAlbum(QString album);
public:
MusicSearchListview *m_MusicView = nullptr;
MusicSearchListview *m_SingerView = nullptr;
MusicSearchListview *m_AlbumView = nullptr;
private:
void setCursorWithXEvent();
QVBoxLayout *vlayout = nullptr;
QLabel *m_MusicLabel = nullptr;
QLabel *m_SingerLabel = nullptr;
QLabel *m_AlbumLabel = nullptr;
int m_CurrentIndex = -1;
int m_Count = 0;
QFrame *m_SingerFrame = nullptr;
QFrame *m_AlbumFrame = nullptr;
SearchEdit *m_searchEdit = nullptr;
int m_resultPosX;
int m_resultPosY;
int m_resultPosWidth;
int m_resultPosHeight;
quint32 m_key;
};
#endif // SEARCHRESULT_H

142
UI/player/sliderwidget.cpp Normal file
View File

@ -0,0 +1,142 @@
#include "sliderwidget.h"
#include "UI/base/widgetstyle.h"
#include "UIControl/player/player.h"
//#include "UI/player/xatom-helper.h"
SliderWidget::SliderWidget(QWidget *parent) : QDialog(parent)
{
installEventFilter(this);
// this->setAttribute(Qt::WA_DeleteOnClose);
this->setAutoFillBackground(true);
this->setBackgroundRole(QPalette::Base);
initUi(); //初始化样式
initColor();
}
void SliderWidget::initUi()
{
setFixedSize(30,90);
vSlider = new QSlider(this);
vSlider->installEventFilter(this);
vSlider->setOrientation(Qt::Vertical);
vSlider->setMinimum(0);
vSlider->setMaximum(100);
vSlider->setValue(playController::getInstance().getVolume());
HLayout = new QHBoxLayout;
HLayout->addWidget(vSlider);
this->setLayout(HLayout);
}
bool SliderWidget::eventFilter(QObject *obj, QEvent *event) //鼠标滑块点击
{
if(obj == vSlider)
{
if (event->type()==QEvent::MouseButtonPress) //判断类型
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
if (mouseEvent->button() == Qt::LeftButton) //判断左键
{
int dur = vSlider->maximum() - vSlider->minimum();
int pos = vSlider->minimum() + (dur * (vSlider->height() - ((double)mouseEvent->y())) / vSlider->height());
if(pos != vSlider->sliderPosition())
{
vSlider->setValue(pos);
}
}
}
}
return QObject::eventFilter(obj,event);
}
bool SliderWidget::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
Q_UNUSED(result);
if(eventType != "xcb_generic_event_t")
{
return false;
}
xcb_generic_event_t *event = (xcb_generic_event_t*)message;
switch (event->response_type & ~0x80)
{
case XCB_FOCUS_OUT:
QRect rect(volunmPosX, volunmPosY, volunmPosWidth, volunmPosHeight);
if(rect.contains(QCursor::pos(), false))
{
return 0;
}
else
{
this->hide();
break;
}
}
return false;
}
void SliderWidget::changeVolumePos(int posX, int posY, int width, int height)
{
volunmPosX = posX;
volunmPosY = posY;
volunmPosWidth = width;
volunmPosHeight = height;
}
void SliderWidget::initColor()
{
if(WidgetStyle::themeColor == 1)
{
// vSlider->setStyleSheet(
// "QSlider::groove:vertical {width: 4px;\
// border: 1px solid #4A708B;\
// padding-left:-1px;\
// padding-right:-1px;\
// border-radius:2px;\
// padding-top:-1px;\
// padding-bottom:-1px;\
// }"
// "QSlider::add-page:vertical{background:#3790FA;}"
// "QSlider::sub-page:vertical{background:#4D4D4D;}"
// "QSlider::handle:vertical {\
// background: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5,\
// stop:0 #3790FA, stop:0.1 #3790FA);\
// width: 10px;\
// height: 10px;\
// margin-top: -4px;\
// margin-left: -3px;\
// margin-bottom: -4px;\
// margin-right: -3px;\
// border-radius: 4px;\
// margin: 0 -3px;\
// }"
// );
}
else if(WidgetStyle::themeColor == 0)
{
// vSlider->setStyleSheet(
// "QSlider::groove:vertical {width: 4px;\
// border: 1px solid #4A708B;\
// padding-left:-1px;\
// padding-right:-1px;\
// border-radius:2px;\
// padding-top:-1px;\
// padding-bottom:-1px;\
// }"
// "QSlider::add-page:vertical{background:#3790FA;}"
// "QSlider::sub-page:vertical{background:#ECEEF5;}"
// "QSlider::handle:vertical {\
// background: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5,\
// stop:0 #3790FA, stop:0.1 #3790FA);\
// width: 10px;\
// height: 10px;\
// margin-top: -4px;\
// margin-left: -3px;\
// margin-bottom: -4px;\
// margin-right: -3px;\
// border-radius: 4px;\
// margin: 0 -3px;\
// }"
// );
}
}

38
UI/player/sliderwidget.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef SLIDERWIDGET_H
#define SLIDERWIDGET_H
#include <QWidget>
#include <QDialog>
#include <QHBoxLayout>
#include <QSlider>
#include <QEvent>
#include <QMouseEvent>
#include <QEvent>
#include <QFocusEvent>
#include <QX11Info>
class SliderWidget : public QDialog
{
Q_OBJECT
public:
explicit SliderWidget(QWidget *parent = nullptr);
// QDialog *vSliderDialog;
QHBoxLayout *HLayout = nullptr;
QSlider *vSlider = nullptr;
public:
void changeVolumePos(int posX, int posY, int width, int height);
void initColor();
protected:
bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE; //鼠标滑块点击 事件过滤器
bool nativeEvent(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;
private:
void initUi();
private:
int volunmPosX;
int volunmPosY;
int volunmPosWidth;
int volunmPosHeight;
};
#endif // SLIDERWIDGET_H

View File

@ -0,0 +1,280 @@
/*
* Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co., Ltd.
*
* Author: ZouYa <zouya@uniontech.com>
*
* Maintainer: WangYu <wangyu@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* 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 <http://www.gnu.org/licenses/>.
*/
#include "musicsearchlistdelegate.h"
#include "musicsearchlistview.h"
#include <QDebug>
#include <QPainter>
#include <QPainterPath>
#include <QTextDocument>
#include <QStyleOptionViewItem>
#include <QTextCursor>
#include <QTextBlock>
#include <QAbstractTextDocumentLayout>
#include <QApplication>
#include "UI/base/widgetstyle.h"
QT_BEGIN_NAMESPACE
extern Q_WIDGETS_EXPORT void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0);
QT_END_NAMESPACE
MusicSearchListDelegate::MusicSearchListDelegate(QWidget *parent)
: QStyledItemDelegate(parent)
{
}
MusicSearchListDelegate::~MusicSearchListDelegate()
{
}
void MusicSearchListDelegate::initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const
{
QStyledItemDelegate::initStyleOption(option, index);
}
bool MusicSearchListDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
Q_UNUSED(event)
Q_UNUSED(model)
Q_UNUSED(option)
Q_UNUSED(index)
return true;
}
void MusicSearchListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
//获取当前行信息
const MusicSearchListview *listview = qobject_cast<const MusicSearchListview *>(option.widget);
QString searchText = listview->getSearchText();
QColor textColor;
QColor lightColor;
if (WidgetStyle::themeColor == 1) {
textColor = QColor("#FFFFFF");
} else if (WidgetStyle::themeColor == 0) {
textColor = QColor("#000000");
}
QPalette pa = option.palette;
QBrush selectBrush = pa.brush(QPalette::Active, QPalette::Highlight);
QColor selectColor = selectBrush.color();
lightColor = selectColor;
painter->setRenderHint(QPainter::Antialiasing);
painter->setRenderHint(QPainter::HighQualityAntialiasing);
// QFont fontT6;
// fontT6.setPixelSize(14);
// 通过字体宽度来对齐左右间隔
int allFontWidth = 232 - 28 -28;
if (listview->getSearchType() == SearchType::TitleType) {
// 绘制歌曲
musicDataStruct metaPtr = index.data(Qt::UserRole + SearchType::TitleType).value<musicDataStruct>();
QString mtext;
mtext = metaPtr.title + "-" + metaPtr.singer;
QFontMetricsF fontWidth(listview->font());
mtext = fontWidth.elidedText(mtext, Qt::ElideRight, allFontWidth);
QStyleOptionViewItem viewOption(option);
initStyleOption(&viewOption, index);
if (option.state.testFlag(QStyle::State_HasFocus))
viewOption.state = viewOption.state ^ QStyle::State_HasFocus;
QStyle *pStyle = viewOption.widget ? viewOption.widget->style() : QApplication::style();
viewOption.text = "";
pStyle->drawControl(QStyle::CE_ItemViewItem, &viewOption, painter, viewOption.widget);
QTextDocument document;
// 设置文字边距,保证绘制文字居中
document.setDocumentMargin(0);
document.setPlainText(mtext);
bool found = false;
QTextCursor highlight_cursor(&document);
QTextCursor cursor(&document);
cursor.beginEditBlock();
QTextCharFormat color_format(highlight_cursor.charFormat());
color_format.setForeground(lightColor);
// 搜索字体高亮
QTextCursor testcursor(&document);
testcursor.select(QTextCursor::LineUnderCursor);
QTextCharFormat fmt;
fmt.setForeground(textColor);
fmt.setFont(listview->font());
testcursor.mergeCharFormat(fmt);
testcursor.clearSelection();
testcursor.movePosition(QTextCursor::EndOfLine);
while (!highlight_cursor.isNull() && !highlight_cursor.atEnd()) {
highlight_cursor = document.find(searchText, highlight_cursor);
if (!highlight_cursor.isNull()) {
if (!found) {
found = true;
}
highlight_cursor.mergeCharFormat(color_format);
}
}
cursor.endEditBlock();
QAbstractTextDocumentLayout::PaintContext paintContext;
int margin = static_cast<int>(((option.rect.height() - fontWidth.height()) / 2));
// QRect textRect(0+28, option.rect.y() + margin, 287, option.rect.height());
// 0+28 为左缩进28px
QRect textRect(0+28, option.rect.y() + margin, allFontWidth, option.rect.height());
painter->save();
painter->translate(textRect.topLeft());
painter->setClipRect(textRect.translated(-textRect.topLeft()));
document.documentLayout()->draw(painter, paintContext);
painter->restore();
} else if (listview->getSearchType() == SearchType::SingerType) {
// 绘制歌曲
musicDataStruct metaPtr = index.data(Qt::UserRole + SearchType::SingerType).value<musicDataStruct>();
QString mtext;
mtext = metaPtr.title + "-" + metaPtr.singer;
QFontMetricsF fontWidth(listview->font());
mtext = fontWidth.elidedText(mtext, Qt::ElideRight, allFontWidth);
QStyleOptionViewItem viewOption(option);
initStyleOption(&viewOption, index);
if (option.state.testFlag(QStyle::State_HasFocus))
viewOption.state = viewOption.state ^ QStyle::State_HasFocus;
QStyle *pStyle = viewOption.widget ? viewOption.widget->style() : QApplication::style();
viewOption.text = "";
pStyle->drawControl(QStyle::CE_ItemViewItem, &viewOption, painter, viewOption.widget);
QTextDocument document;
// 设置文字边距,保证绘制文字居中
document.setDocumentMargin(0);
document.setPlainText(mtext);
bool found = false;
QTextCursor highlight_cursor(&document);
QTextCursor cursor(&document);
cursor.beginEditBlock();
QTextCharFormat color_format(highlight_cursor.charFormat());
color_format.setForeground(lightColor);
// 搜索字体高亮
QTextCursor testcursor(&document);
testcursor.select(QTextCursor::LineUnderCursor);
QTextCharFormat fmt;
fmt.setForeground(textColor);
fmt.setFont(listview->font());
testcursor.mergeCharFormat(fmt);
testcursor.clearSelection();
testcursor.movePosition(QTextCursor::EndOfLine);
while (!highlight_cursor.isNull() && !highlight_cursor.atEnd()) {
highlight_cursor = document.find(searchText, highlight_cursor);
if (!highlight_cursor.isNull()) {
if (!found)
found = true;
highlight_cursor.mergeCharFormat(color_format);
}
}
cursor.endEditBlock();
QAbstractTextDocumentLayout::PaintContext paintContext;
int margin = static_cast<int>(((option.rect.height() - fontWidth.height()) / 2));
QRect textRect(0+28, option.rect.y() + margin, allFontWidth, option.rect.height());
painter->save();
painter->translate(textRect.topLeft());
painter->setClipRect(textRect.translated(-textRect.topLeft()));
document.documentLayout()->draw(painter, paintContext);
painter->restore();
} else if (listview->getSearchType() == SearchType::AlbumType) {
// 绘制歌曲
musicDataStruct metaPtr = index.data(Qt::UserRole + SearchType::AlbumType).value<musicDataStruct>();
QString mtext;
mtext = metaPtr.album + "-" + metaPtr.singer;
QFontMetricsF fontWidth(listview->font());
mtext = fontWidth.elidedText(mtext, Qt::ElideRight, allFontWidth);
QStyleOptionViewItem viewOption(option);
initStyleOption(&viewOption, index);
if (option.state.testFlag(QStyle::State_HasFocus))
viewOption.state = viewOption.state ^ QStyle::State_HasFocus;
QStyle *pStyle = viewOption.widget ? viewOption.widget->style() : QApplication::style();
viewOption.text = "";
pStyle->drawControl(QStyle::CE_ItemViewItem, &viewOption, painter, viewOption.widget);
QTextDocument document;
// 设置文字边距,保证绘制文字居中
document.setDocumentMargin(0);
document.setPlainText(mtext);
bool found = false;
QTextCursor highlight_cursor(&document);
QTextCursor cursor(&document);
cursor.beginEditBlock();
QTextCharFormat color_format(highlight_cursor.charFormat());
color_format.setForeground(lightColor);
// 搜索字体高亮
QTextCursor testcursor(&document);
testcursor.select(QTextCursor::LineUnderCursor);
QTextCharFormat fmt;
fmt.setForeground(textColor);
fmt.setFont(listview->font());
testcursor.mergeCharFormat(fmt);
testcursor.clearSelection();
testcursor.movePosition(QTextCursor::EndOfLine);
while (!highlight_cursor.isNull() && !highlight_cursor.atEnd()) {
highlight_cursor = document.find(searchText, highlight_cursor);
if (!highlight_cursor.isNull()) {
if (!found)
found = true;
highlight_cursor.mergeCharFormat(color_format);
}
}
cursor.endEditBlock();
QAbstractTextDocumentLayout::PaintContext paintContext;
int margin = static_cast<int>(((option.rect.height() - fontWidth.height()) / 2));
QRect textRect(0+28, option.rect.y() + margin, allFontWidth, option.rect.height());
painter->save();
painter->translate(textRect.topLeft());
painter->setClipRect(textRect.translated(-textRect.topLeft()));
document.documentLayout()->draw(painter, paintContext);
painter->restore();
}
}
QSize MusicSearchListDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(option)
Q_UNUSED(index)
return QSize(126, 36);
}

View File

@ -0,0 +1,25 @@
#include <QScopedPointer>
#include <QStyledItemDelegate>
#include <QListView>
class MusicSearchListDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit MusicSearchListDelegate(QWidget *parent = Q_NULLPTR);
~MusicSearchListDelegate() override;
Q_SIGNALS:
void SearchClear() const;
protected:
virtual void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override;
bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override;
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
private:
QPixmap m_shadowImg;
};

View File

@ -0,0 +1,54 @@
/*
* Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co., Ltd.
*
* Author: ZouYa <zouya@uniontech.com>
*
* Maintainer: WangYu <wangyu@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* 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 <http://www.gnu.org/licenses/>.
*/
#include "musicsearchlistmodel.h"
#include <QDebug>
MusicSearchListModel::MusicSearchListModel(int rows, int columns, QObject *parent):
QStandardItemModel(rows, columns, parent)
{
}
MusicSearchListModel::~MusicSearchListModel()
{
}
bool MusicSearchListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
return QStandardItemModel::setData(index, value, role);
}
//Qt::DropActions MusicSearchListModel::supportedDropActions() const
//{
// return Qt::CopyAction | Qt::MoveAction;
//}
Qt::ItemFlags MusicSearchListModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags defaultFlags = QAbstractItemModel::flags(index);
if (index.isValid()) {
return Qt::ItemIsDragEnabled | defaultFlags;
} else {
return Qt::ItemIsDropEnabled | defaultFlags;
}
}

View File

@ -0,0 +1,17 @@
#pragma once
#include <QStandardItemModel>
#include <QScopedPointer>
class MusicSearchListModel : public QStandardItemModel
{
Q_OBJECT
public:
MusicSearchListModel(int rows, int columns, QObject *parent = Q_NULLPTR);
~MusicSearchListModel() override;
virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) Q_DECL_OVERRIDE;
//virtual Qt::DropActions supportedDropActions() const Q_DECL_OVERRIDE;
virtual Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE;
};

View File

@ -0,0 +1,254 @@
/*
* Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co., Ltd.
*
* Author: ZouYa <zouya@uniontech.com>
*
* Maintainer: WangYu <wangyu@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* 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 <http://www.gnu.org/licenses/>.
*/
#include "musicsearchlistview.h"
#include "musicsearchlistmodel.h"
#include "musicsearchlistdelegate.h"
#include <QTouchEvent>
#include <QDebug>
#include <QFileInfo>
#define NUM 10000
//DWIDGET_USE_NAMESPACE
MusicSearchListview::MusicSearchListview(QWidget *parent)
: QListView(parent)
{
setAttribute(Qt::WA_AcceptTouchEvents);
setFrameShape(QListView::NoFrame);
m_model = new MusicSearchListModel(3, 3, this);
setModel(m_model);
m_delegate = new MusicSearchListDelegate(this);
setItemDelegate(m_delegate);
setUniformItemSizes(true);
this->setFocusPolicy(Qt::NoFocus);
setViewMode(QListView::ListMode);
setResizeMode(QListView::Adjust);
setMovement(QListView::Static);
setLayoutMode(QListView::Batched);
setBatchSize(2000);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
connect(m_delegate, &MusicSearchListDelegate::SearchClear, this, &MusicSearchListview::SearchClear);
connect(this, SIGNAL(clicked(const QModelIndex &)), this, SLOT(slotOnClicked(const QModelIndex &)));
}
MusicSearchListview::~MusicSearchListview()
{
}
SearchType MusicSearchListview::getSearchType() const
{
return m_searchType;
}
void MusicSearchListview::setSearchResultWidget(SearchResult *result)
{
m_SearchResultWidget = result;
}
void MusicSearchListview::setSearchType(SearchType type)
{
m_searchType = type;
}
void MusicSearchListview::setSearchText(QString text)
{
m_CurrentIndex = -1;
m_searchText = text;
Q_EMIT signalSearchTexts(m_searchText);
QList<musicDataStruct> musicDataInfos;
QList<musicDataStruct> singerInfos;
QList<musicDataStruct> albumInfos;
g_db->getCurtEstimatedListByKeyword(text,NUM,musicDataInfos,singerInfos,albumInfos);
if (m_searchType == SearchType::TitleType) {
m_MusicDataStruct.clear();
for (int i = 0; i < musicDataInfos.count(); i++) {
musicDataStruct titleList = musicDataInfos.at(i);
m_MusicDataStruct.append(titleList);
}
m_model->clear();
for (musicDataStruct musicData : m_MusicDataStruct) {
QStandardItem *item = new QStandardItem;
QString Str = musicData.title + "-" + musicData.singer;
item->setData(Str,Qt::ToolTipRole);
m_model->appendRow(item);
auto row = m_model->rowCount() - 1;
QModelIndex index = m_model->index(row, 0, QModelIndex());
QVariant mediaMeta;
mediaMeta.setValue(musicData);
m_model->setData(index, mediaMeta, Qt::UserRole + SearchType::TitleType);
// QFont sizeFont;
// sizeFont.setPixelSize(12);
// QFontMetrics fm(sizeFont);
// QString Str = musicData.title + "-" + musicData.singer;
// QString displayStr = fm.elidedText(Str,Qt::ElideRight,136);
// item->setData(displayStr, Qt::DisplayRole);
// item->setData(Str,Qt::ToolTipRole);
// m_model->appendRow(item);
}
} else if (m_searchType == SearchType::SingerType) {
m_SingerInfos.clear();
for (int i = 0; i < singerInfos.count(); i++) {
musicDataStruct singerList = singerInfos.at(i);
m_SingerInfos.append(singerList);
}
m_model->clear();
for (musicDataStruct singerData : m_SingerInfos) {
QStandardItem *item = new QStandardItem;
QString Str = singerData.title + "-" + singerData.singer;
item->setData(Str,Qt::ToolTipRole);
m_model->appendRow(item);
auto row = m_model->rowCount() - 1;
QModelIndex index = m_model->index(row, 0, QModelIndex());
QVariant mediaMeta;
mediaMeta.setValue(singerData);
m_model->setData(index, mediaMeta, Qt::UserRole + SearchType::SingerType);
// QFont sizeFont;
// sizeFont.setPixelSize(12);
// QFontMetrics fm(sizeFont);
// QString Str = singerData.title + "-" + singerData.singer;
// QString displayStr = fm.elidedText(Str,Qt::ElideRight,136);
// item->setData(displayStr, Qt::DisplayRole);
// item->setData(Str,Qt::ToolTipRole);
// m_model->appendRow(item);
}
} else if (m_searchType == SearchType::AlbumType) {
m_AlbumInfos.clear();
for (int i = 0; i < albumInfos.count(); i++) {
musicDataStruct albumList = albumInfos.at(i);
m_AlbumInfos.append(albumList);
}
m_model->clear();
for (musicDataStruct albumData : m_AlbumInfos) {
QStandardItem *item = new QStandardItem;
QString Str = albumData.album + "-" + albumData.singer;
item->setData(Str,Qt::ToolTipRole);
m_model->appendRow(item);
auto row = m_model->rowCount() - 1;
QModelIndex index = m_model->index(row, 0, QModelIndex());
QVariant mediaMeta;
mediaMeta.setValue(albumData);
m_model->setData(index, mediaMeta, Qt::UserRole + SearchType::AlbumType);
// QFont sizeFont;
// sizeFont.setPixelSize(12);
// QFontMetrics fm(sizeFont);
// QString Str = albumData.album + "-" + albumData.singer;
// QString displayStr = fm.elidedText(Str,Qt::ElideRight,136);
// item->setData(displayStr, Qt::DisplayRole);
// item->setData(Str,Qt::ToolTipRole);
// m_model->appendRow(item);
}
}
}
int MusicSearchListview::rowCount()
{
return m_model->rowCount();
}
int MusicSearchListview::getIndexInt()const
{
return m_CurrentIndex;
}
QString MusicSearchListview::getSearchText()const
{
return m_searchText;
}
void MusicSearchListview::setCurrentIndexInt(int row)
{
m_CurrentIndex = row;
}
void MusicSearchListview::switchToSearchResultTab(const QModelIndex &index)
{
// if (m_SearchType == SearchType::SearchMusic) {
// MediaMeta mediaMeta = index.data(Qt::UserRole + SearchType::SearchMusic).value<MediaMeta>();
// Q_EMIT CommonService::getInstance()->signalSwitchToView(SearchMusicResultType, mediaMeta.title);
// if (m_SearchResultWidget) {
// m_SearchResultWidget->setLineEditSearchString(mediaMeta.title);
// }
// } else if (m_SearchType == SearchType::SearchSinger) {
// SingerInfo singerInfo = index.data(Qt::UserRole + SearchType::SearchSinger).value<SingerInfo>();
// Q_EMIT CommonService::getInstance()->signalSwitchToView(SearchSingerResultType, singerInfo.singerName);
// if (m_SearchResultWidget) {
// m_SearchResultWidget->setLineEditSearchString(singerInfo.singerName);
// }
// } else if (m_SearchType == SearchType::SearchAlbum) {
// AlbumInfo albumInfo = index.data(Qt::UserRole + SearchType::SearchAlbum).value<AlbumInfo>();
// Q_EMIT CommonService::getInstance()->signalSwitchToView(SearchAlbumResultType, albumInfo.albumName);
// if (m_SearchResultWidget) {
// m_SearchResultWidget->setLineEditSearchString(albumInfo.albumName);
// }
// }
}
void MusicSearchListview::SearchClear()
{
Q_EMIT this->sigSearchClear();
}
void MusicSearchListview::slotOnClicked(const QModelIndex &index)
{
switchToSearchResultTab(index);
}
void MusicSearchListview::onReturnPressed()
{
qDebug() << "------MusicSearchListview::onReturnPressed";
slotOnClicked(m_model->index(m_CurrentIndex, 0));
}
void MusicSearchListview::mouseMoveEvent(QMouseEvent *event)
{
Q_UNUSED(event)
qDebug() << "MusicSearchListview::mouseMoveEvent";
}
bool MusicSearchListview::event(QEvent *event)
{
if (event->type() == QEvent::TouchBegin) {
QTouchEvent *touch = static_cast<QTouchEvent *>(event);
if (touch && touch->touchPoints().size() > 0) {
QModelIndex index = this->indexAt(touch->touchPoints().at(0).pos().toPoint());
switchToSearchResultTab(index);
}
}
return QListView::event(event);
}

View File

@ -0,0 +1,58 @@
#pragma once
#include <QListView>
#include <QPixmap>
#include <QVariant>
#include "UI/player/searchresult.h"
#include "UIControl/base/musicDataBase.h"
#include "UIControl/base/musicfileinformation.h"
class MusicSearchListModel;
class MusicSearchListDelegate;
class SearchResult;
class MusicSearchListview: public QListView
{
Q_OBJECT
public:
explicit MusicSearchListview(QWidget *parent = Q_NULLPTR);
~MusicSearchListview() override;
void setSearchResultWidget(SearchResult *result);
void setSearchType(SearchType type);
SearchType getSearchType() const;
void setSearchText(QString text);
int rowCount();
int getIndexInt()const;
QString getSearchText()const;
void setCurrentIndexInt(int row);
private:
// 单击或者触屏单击时调用跳转到搜索结果tab页
void switchToSearchResultTab(const QModelIndex &index);
Q_SIGNALS:
void sigSearchClear();
void signalSearchTexts(QString text);
public Q_SLOTS:
void SearchClear();
void slotOnClicked(const QModelIndex &index);
void onReturnPressed();
protected:
virtual void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
virtual bool event(QEvent *event) Q_DECL_OVERRIDE;
public:
SearchType m_searchType;
private:
MusicSearchListModel *m_model = nullptr;
MusicSearchListDelegate *m_delegate = nullptr;
QString m_searchText = "";
int m_CurrentIndex = -1;
// QPixmap m_defaultIcon = QPixmap(":/icons/deepin/builtin/actions/cover_max_200px.svg");
QList<musicDataStruct> m_MusicDataStruct;
QList<musicDataStruct> m_SingerInfos;
QList<musicDataStruct> m_AlbumInfos;
SearchResult *m_SearchResultWidget = nullptr;
};

View File

@ -0,0 +1,51 @@
#include "leftsiderbarwidget.h"
#include <QDebug>
#include <QGSettings>
#include <QStyleOption>
#include <QPainter>
#define PERSONALSIE_SCHEMA "org.ukui.control-center.personalise"
#define PERSONALSIE_TRAN_KEY "transparency"
#define CONTAIN_PERSONALSIE_TRAN_KEY "transparency"
LeftsiderbarWidget::LeftsiderbarWidget(QWidget *parent)
: QWidget(parent)
{
QGSettings *personalQgsettings = nullptr;
if (QGSettings::isSchemaInstalled(PERSONALSIE_SCHEMA)) {
personalQgsettings = new QGSettings(PERSONALSIE_SCHEMA, QByteArray(), this);
transparency = personalQgsettings->get(PERSONALSIE_TRAN_KEY).toDouble() * 255;
connect(personalQgsettings,&QGSettings::changed,this,[=](QString changedKey) { //监听透明度变化
if (changedKey == CONTAIN_PERSONALSIE_TRAN_KEY) {
transparency = personalQgsettings->get(PERSONALSIE_TRAN_KEY).toDouble() * 255;
this->repaint();
}
});
} else {
personalQgsettings = nullptr;
qDebug()<<PERSONALSIE_SCHEMA<<" not installed";
}
}
LeftsiderbarWidget::~LeftsiderbarWidget()
{
}
void LeftsiderbarWidget::paintEvent(QPaintEvent *event)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
p.setPen(Qt::NoPen);
QColor color = palette().color(QPalette::Window);
color.setAlpha(transparency);
QPalette pal(this->palette());
pal.setColor(QPalette::Window,QColor(color));
this->setPalette(pal);
QBrush brush =QBrush(color);
p.setBrush(brush);
p.drawRoundedRect(opt.rect,0,0);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

View File

@ -0,0 +1,21 @@
#ifndef LEFTSIDERBARWIDGET_H
#define LEFTSIDERBARWIDGET_H
#include <QWidget>
#include <QObject>
class LeftsiderbarWidget : public QWidget
{
Q_OBJECT
public:
LeftsiderbarWidget(QWidget *parent = nullptr);
~LeftsiderbarWidget();
void paintEvent(QPaintEvent *event);
private:
int transparency = 0;
};
#endif // LEFTSIDERBARWIDGET_H

View File

@ -0,0 +1,29 @@
#include "myscrollarea.h"
myScrollArea::myScrollArea(QWidget *parent) : QScrollArea(parent)
{
// QScrollArea本身主题有背景避免干扰需要设置全透明不使用主题的背景颜色,只有1种恰当方式, rgba(0,0,0,0)
this->setStyleSheet("background-color: rgba(0, 0, 0, 0);");
/** setStyleBar组件设置样式技巧通过整体设置背景、大小等参数之后可以通过::来指定控件中其他小部件, :可以设置点击、垂直方向等用户手动操作的状态参数;
* width border-radius也应该越小;
* margin-left和margin-right来控制滑块大小
*/
this->verticalScrollBar()->setStyleSheet("QScrollBar:vertical{width:16px; border-radius:4px;}" // 可设置可区分背景颜色进行调节整个滑动条控件的宽度width = 滑块宽度 + margin-left + margin-right
"QScrollBar::handle:vertical{background:rgba(0,0,0, 10%); width: 4px;border-radius: 2px; margin-left:6px;margin-right:6px;}" // 滑动条滑块handle两端变椭圆,和滑轨之间的间隙
"QScrollBar::handle:vertical:hover{background:rgba(0,0,0, 15%); width: 8px; border-radius:4px;margin-left:4px;margin-right:4px;}" // 鼠标放到滑块上颜色加深
"QScrollBar::sub-line:vertical{border: none; background: none; color:none;}" // 设置上箭头不可见
"QScrollBar::add-line:vertical{border: none; background: none; color:none;}" // 设置下箭头不可见
"QScrollBar::sub-page:vertical{background:none;}" // 滑块还没经过的滑轨区域的颜色
"QScrollBar::add-page:vertical{background:none;}" // 滑块已经经过的滑轨区域的颜色
"QScrollBar::up-arrow:vertical{background:none;}" // 上箭头图标
"QScrollBar::down-arrow:vertical{background:none;}" // 下箭头图标
);
}
myScrollArea::~myScrollArea()
{
}

18
UI/sidebar/myscrollarea.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef MYSCROLLAREA_H
#define MYSCROLLAREA_H
#include <QWidget>
#include <QScrollArea>
#include <QScrollBar>
class myScrollArea : public QScrollArea
{
Q_OBJECT
public:
explicit myScrollArea(QWidget *parent = nullptr);
~myScrollArea();
};
#endif // MYSCROLLAREA_H

167
UI/sidebar/mytoolbutton.cpp Normal file
View File

@ -0,0 +1,167 @@
#include "mytoolbutton.h"
#include "UI/base/widgetstyle.h"
#include "UIControl/base/musicDataBase.h"
#include <QDebug>
MyToolButton::MyToolButton()
{
//在按钮没有默认选中时,实例化时先调用(故注释)
// defaultStyle();
this->setFixedSize(162,32);
//文字在图标旁边
this->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
this->setIconSize(QSize(16,16));
connect(this,&MyToolButton::clicked,this,&MyToolButton::selectChanged);
this->setContextMenuPolicy(Qt::CustomContextMenu);
connect(this,&MyToolButton::customContextMenuRequested,this,&MyToolButton::selectChanged);
connect(this,&MyToolButton::customContextMenuRequested,this,&MyToolButton::requestCustomContextMenu);
//限制应用内字体固定大小
// QFont sizeFont;
// sizeFont.setPixelSize(14);
// this->setFont(sizeFont);
}
MyToolButton::~MyToolButton()
{
}
void MyToolButton::selectChanged()
{
if(this->statusTip() == IS_SELECT)
{
Q_EMIT selectButtonChanged(this->text());
return;
}
Q_EMIT selectButtonChanged(this->text());
QList<MyToolButton *> list = this->parent()->parent()->parent()->findChildren<MyToolButton *>();
for(MyToolButton *tmp : list)
{
if(tmp->statusTip() == IS_SELECT)
{
tmp->setStatusTip("");
tmp->defaultStyle();
}
}
this->setStatusTip(IS_SELECT);
this->defaultStyle();
}
void MyToolButton::defaultStyle()
{
if(this->statusTip() == IS_SELECT)
{
this->setStyleSheet("QToolButton{background-color:#3790FA;padding-left:14px;color:#FFFFFF;border-radius: 6px;}");
if(buttonListName == ALLMUSIC)
{
this->setIcon(QIcon(":/img/clicked/ukui-folder-music-symbolic.svg"));
}
else if(buttonListName == FAV)
{
this->setIcon(QIcon(":/img/clicked/ukui-play-love-symbolic.svg"));
}
else
{
this->setIcon(QIcon(":/img/clicked/audio-card-symbolic.svg"));
}
return;
}
else if(this->statusTip() != IS_SELECT)
{
if(WidgetStyle::themeColor == 0)
{
//padding-left:15px; 左内边距
this->setStyleSheet("QToolButton{padding-left:14px; background-color:#FFFFFF;color:#303133;border-radius:4px;}"
"QToolButton::hover{background-color:#EEEEEE;border-radius:4px;}");
if(buttonListName == ALLMUSIC)
{
this->setIcon(QIcon(":/img/default/ukui-folder-music-symbolic.svg"));
}
else if(buttonListName == FAV)
{
this->setIcon(QIcon(":/img/default/ukui-play-love-symbolic.svg"));
}
else
{
this->setIcon(QIcon(":/img/default/audio-card-symbolic.svg"));
}
}
else if(WidgetStyle::themeColor == 1)
{
this->setStyleSheet("QToolButton{padding-left:14px;background-color:#252526;color:#f9f9f9;border-radius:4px;}"
"QToolButton::hover{background-color:#303032;border-radius:4px;}");
if(buttonListName == ALLMUSIC)
{
this->setIcon(QIcon(":/img/dark/ukui-folder-music-symbolic.svg"));
}
else if(buttonListName == FAV)
{
this->setIcon(QIcon(":/img/dark/ukui-play-love-symbolic.svg"));
}
else
{
this->setIcon(QIcon(":/img/dark/audio-card-symbolic.svg"));
}
}
}
}
void MyToolButton::requestCustomContextMenu(const QPoint &pos)
{
// 不用this因此可以使用主题的QMenu
QMenu *menu = new QMenu();
// QFont sizeFont;
// sizeFont.setPixelSize(14);
// menu->setFont(sizeFont);
QAction *playAct = new QAction(this);
QAction *pauseAct = new QAction(this);
renameAct = new QAction(this);
deleteAct = new QAction(this);
playAct->setText(tr("Play"));
pauseAct->setText(tr("Pause"));
renameAct->setText(tr("Rename"));
deleteAct->setText(tr("Delete"));
menu->addAction(playAct);
// menu->addAction(pauseAct);
QString text = this->text();
QString btnText = text;
connect(menu,&QMenu::triggered,this,[ = ](QAction * action)
{
if(action->text() == tr("Play"))
{
Q_EMIT playall(text);
}
else if(action->text() == tr("Pause"))
{
// Q_EMIT
}
else if(action->text() == tr("Rename"))
{
Q_EMIT renamePlayList(text);
}
else if(action->text() == tr("Delete"))
{
Q_EMIT removePlayList(text);
}
});
if(btnText != tr("Song List") && btnText != tr("I Love"))
{
menu->addAction(renameAct);
menu->addAction(deleteAct);
}
menu->exec(mapToGlobal(pos));
delete menu;
delete playAct;
delete renameAct;
delete deleteAct;
}

38
UI/sidebar/mytoolbutton.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef MYTOOLBUTTON_H
#define MYTOOLBUTTON_H
#include <QToolButton>
#include <QPainter>
#include <QWidget>
#include <QPushButton>
#include <QLabel>
#include <QtWidgets>
const QString IS_SELECT = "IS_SELECT";
class MyToolButton : public QToolButton
{
Q_OBJECT
public:
MyToolButton();
~MyToolButton();
void selectChanged();
void defaultStyle();
void requestCustomContextMenu(const QPoint &pos);
public:
QAction *deleteAct = nullptr;
QAction *renameAct = nullptr;
QString buttonListName = "";
Q_SIGNALS:
void playall(QString text);
void renamePlayList(QString text);
void removePlayList(QString text);
void selectButtonChanged(QString text);
public Q_SLOTS:
private:
};
#endif

View File

@ -0,0 +1,457 @@
#include "sidebarwidget.h"
#include "UIControl/player/player.h"
#include "UIControl/base/musicDataBase.h"
#include "UI/base/widgetstyle.h"
#include "UI/mainwidget.h"
#include <ukui-log4qt.h>
SideBarWidget::SideBarWidget(QWidget *parent) : LeftsiderbarWidget(parent)
{
// setFixedSize(210, 640);
resize(210, 640);
this->setObjectName("SideBarWidget");
initWidget(); //初始化侧边栏界面
initConnect(); //建立connect
sidecolor(); //初始化样式
getPlayListName();
}
void SideBarWidget::initWidget()
{
this->setProperty("useSystemStyleBlur", true);
this->setAttribute(Qt::WA_TranslucentBackground, true);
//侧边栏界面样式
QVBoxLayout *mainLayout = new QVBoxLayout();
//logo
QHBoxLayout *logoLayout = new QHBoxLayout();
QLabel *logoNameLabel = new QLabel(this);
logoNameLabel->setText(tr("Music Player"));
logoNameLabel->setFixedHeight(28);
QLabel *logoIconLabel = new QLabel(this);
logoIconLabel->setFixedSize(QSize(25, 25));
logoIconLabel->setPixmap(QIcon::fromTheme("kylin-music").pixmap(logoIconLabel->size()));
logoLayout->setSpacing(0);
logoLayout->setMargin(8);
logoLayout->addWidget(logoIconLabel,Qt::AlignLeft);
logoLayout->addSpacing(8);
logoLayout->addWidget(logoNameLabel,0,Qt::AlignLeft);
logoLayout->addStretch();
logoLayout->setContentsMargins(8,8,0,0);
//音乐库
QHBoxLayout *libraryLayout = new QHBoxLayout();
libraryLabel = new QLabel(this);
libraryLabel->setText(tr("Library"));
libraryLabel->setFixedHeight(28);
// libraryLabel->setFixedSize(80,30);
libraryLayout->addWidget(libraryLabel);
libraryLayout->setContentsMargins(38,0,38,0);
//歌曲列表
QHBoxLayout *playListBtnLayout = new QHBoxLayout();
playListBtn = new MyToolButton;
playListBtn->setText(tr("Song List"));
// playListBtn->setIcon(QIcon::fromTheme("ukui-folder-music-symbolic"));
playListBtn->setStatusTip(IS_SELECT);
playListBtn->buttonListName = ALLMUSIC;
playListBtn->defaultStyle();
playListBtnLayout->addWidget(playListBtn,Qt::AlignCenter);
// playListBtnLayout->setContentsMargins(24,0,24,0);
connect(playListBtn,&MyToolButton::selectButtonChanged,this,&SideBarWidget::playListBtnCliced);
//我的歌单
QHBoxLayout *myPlayListLayout = new QHBoxLayout();
myPlayListLabel = new QLabel(this);
myPlayListBtn = new QPushButton(this);
myPlayListLabel->setText(tr("My PlayList"));
myPlayListLabel->setFixedHeight(28);
myPlayListBtn->setFixedSize(20,20);
myPlayListBtn->setIcon(QIcon::fromTheme("list-add-symbolic"));
myPlayListBtn->setProperty("isWindowButton", 0x1);
myPlayListBtn->setProperty("useIconHighlightEffect", 0x2);
myPlayListBtn->setFlat(true);
myPlayListLayout->addWidget(myPlayListLabel);
myPlayListLayout->addStretch();
myPlayListLayout->addWidget(myPlayListBtn);
myPlayListLayout->setContentsMargins(38,0,38,0);
scrollArea = new myScrollArea(this);
scrollArea->setFrameStyle(0);
//歌单界面
newPlayListWidget = new QWidget();
newPlayListLayout = new QVBoxLayout();
scrollArea->setWidgetResizable(true);
// scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scrollArea->setFrameShape(QFrame::NoFrame);
newPlayListLayout->setAlignment(Qt::AlignTop);
newPlayListWidget->setLayout(newPlayListLayout);
newPlayListLayout->setContentsMargins(24,0,24,0);
mainLayout->addLayout(libraryLayout);
mainLayout->addSpacing(6);
mainLayout->addLayout(playListBtnLayout);
mainLayout->addSpacing(16);
mainLayout->addLayout(myPlayListLayout);
mainLayout->addSpacing(6);
mainLayout->addWidget(newPlayListWidget);
mainLayout->addStretch();
mainLayout->setMargin(0);
//新建歌单弹窗
newSonglistPup = new AllPupWindow(this);
newSonglistPup->titleLab->setText(tr("New Playlist"));
newSonglistPup->hide();
renameSongListPup = new AllPupWindow(this);
renameSongListPup->titleLab->setText(tr("Rename"));
renameSongListPup->hide();
//侧边栏界面 嵌套 widget
mainWid = new QWidget(this);
mainWid->setLayout(mainLayout);
mainWid->setObjectName("mainWid");
scrollArea->setWidget(mainWid);
scrollArea->verticalScrollBar()->setProperty("drawScrollBarGroove",false);
logoWid = new QWidget(this);
logoWid->setFixedHeight(40);
logoWid->setLayout(logoLayout);
logoWid->setObjectName("logoWid");
//放置活动条
QVBoxLayout *scrollLayout = new QVBoxLayout(this);
scrollLayout->addWidget(logoWid);
scrollLayout->addSpacing(16);
scrollLayout->addWidget(scrollArea);
scrollLayout->setMargin(0);
scrollLayout->setSpacing(0);
this->setLayout(scrollLayout);
this->setAutoFillBackground(true);
// // 真正的主widget
// sideWid = new QWidget(this);
// sideWid->setLayout(scrollLayout);
// sideWid->setObjectName("sideWid");
// QVBoxLayout *sideLayout = new QVBoxLayout(this);
// sideLayout->addWidget(sideWid);
// sideLayout->setMargin(0);
// sideLayout->setSpacing(0);
}
void SideBarWidget::initConnect()
{
connect(myPlayListBtn,&QPushButton::clicked,this,&SideBarWidget::addPlayList);
connect(playListBtn,SIGNAL(playall(QString)),this,SLOT(playAll(QString)));
connect(newSonglistPup->confirmBtn,SIGNAL(clicked(bool)),this,SLOT(addItemToSongList()));
connect(newSonglistPup->enterLineEdit,SIGNAL(returnPressed()),this,SLOT(addItemToSongList()));
connect(renameSongListPup->confirmBtn,SIGNAL(clicked(bool)),this,SLOT(renamePlayList()));
connect(renameSongListPup->enterLineEdit,SIGNAL(returnPressed()),this,SLOT(renamePlayList()));
}
void SideBarWidget::sidecolor()
{
myPlayListLabel->setStyleSheet("line-height: 14px;");
libraryLabel->setStyleSheet("line-height: 14px;");
if(WidgetStyle::themeColor == 1)
{
// 黑色主题跟随主题切换否则paintevent主题切换不生效
QPalette pal(palette());
pal.setColor(QPalette::Background, QColor(38, 38, 38));
setAutoFillBackground(true);
setPalette(pal);
QList<MyToolButton *> list = this->findChildren<MyToolButton *>();
for(MyToolButton *tmp : list)
{
tmp->defaultStyle();
}
}
else if(WidgetStyle::themeColor == 0)
{
QPalette pal(palette());
pal.setColor(QPalette::Background, QColor(255, 255, 255));
setAutoFillBackground(true);
setPalette(pal);
QList<MyToolButton *> list = this->findChildren<MyToolButton *>();
for(MyToolButton *tmp : list)
{
tmp->defaultStyle();
}
}
}
void SideBarWidget::getPlayListName()
{
int ret = g_db->getPlayList(playListName);
if(ret != DB_OP_SUCC)
{
qDebug() << "获取歌单名信息失败" <<__FILE__<< ","<<__FUNCTION__<<","<<__LINE__;
return;
}
QString listName;
for(int i = 0; i < playListName.size();i++)
{
listName = playListName.at(i);
if(listName == SEARCH)
{
continue;
}
MyToolButton *newBtn = new MyToolButton;
newPlayListLayout->setAlignment(Qt::AlignTop);
newPlayListLayout->addWidget(newBtn);
// newPlayListLayout->setContentsMargins(24,0,24,0);
newPlayListLayout->setSpacing(6);
if(listName == FAV)
{
newBtn->setText(tr("I Love"));
newBtn->buttonListName = FAV;
newBtn->defaultStyle();
}
else
{
newBtn->setText(listName);
newBtn->buttonListName = "";
newBtn->defaultStyle();
}
connect(newBtn,SIGNAL(playall(QString)),this,SLOT(playAll(QString)));
connect(newBtn,SIGNAL(renamePlayList(QString)),this,SLOT(rename(QString)));
connect(newBtn,SIGNAL(removePlayList(QString)),this,SLOT(removePlayList(QString)));
connect(newBtn,&MyToolButton::selectButtonChanged,this,&SideBarWidget::playListBtnCliced);
QString name = playController::getInstance().getPlayListName();
if(listName == name )
{
m_lastBtn = newBtn;
}
}
if(m_lastBtn != nullptr)
{
m_lastBtn->clicked();
}
}
void SideBarWidget::addPlayList()
{
newSonglistPup->enterLineEdit->clear();
newSonglistPup->show();
newSonglistPup->enterLineEdit->setFocus();
}
void SideBarWidget::addItemToSongList()
{
MyToolButton *newBtn = new MyToolButton();
newPlayListLayout->setAlignment(Qt::AlignTop);
newPlayListLayout->setSpacing(6);
QString text = newSonglistPup->enterLineEdit->text();
// QString showText = fm.elidedText(text, Qt::ElideRight, 200);
if(text != "")
{
for(int i = 0;i< playListName.size();i++)
{
if(playListName.at(i) == text)
{
newSonglistPup->hide();
QMessageBox::warning(Widget::mutual,tr("Prompt information"),tr("Single song name already exists!!!"),QMessageBox::Ok);
return ;
}
}
newBtn->setText(text);
newBtn->buttonListName = "";
newBtn->defaultStyle();
newPlayListLayout->addWidget(newBtn);
playListName.append(text);
newSonglistPup->hide();
g_db->createNewPlayList(text);
Q_EMIT playListAdded(text);
}
else
{
QString listName = newPlayListName();
newBtn->setText(listName);
newBtn->buttonListName = "";
newBtn->defaultStyle();
newPlayListLayout->addWidget(newBtn);
playListName.append(listName);
newSonglistPup->hide();
g_db->createNewPlayList(listName);
Q_EMIT playListAdded(listName);
}
connect(newBtn,SIGNAL(playall(QString)),this,SLOT(playAll(QString)));
connect(newBtn,SIGNAL(renamePlayList(QString)),this,SLOT(rename(QString)));
connect(newBtn,SIGNAL(removePlayList(QString)),this,SLOT(removePlayList(QString)));
connect(newBtn,&MyToolButton::selectButtonChanged,this,&SideBarWidget::playListBtnCliced);
}
QString SideBarWidget::newPlayListName()
{
QMap<QString, QString> exitsName;
for (auto &name : playListName)
{
exitsName.insert(name, name);
}
QString name = tr("New Playlist");
if(!exitsName.contains(name))
{
return name;
}
int i = 1;
for(i = 1; i < exitsName.size() + 1; i++)
{
QString newName = QString("%1 %2").arg(name).arg(i);
if(!exitsName.contains(newName))
{
return newName;
}
}
return QString("%1 %2").arg(name).arg(i);
}
void SideBarWidget::playAll(QString btnText)
{
Q_EMIT signalPlayAll(btnText);
}
void SideBarWidget::rename(QString text)
{
btnText = text;
renameSongListPup->enterLineEdit->clear();
renameSongListPup->show();
renameSongListPup->enterLineEdit->setFocus();
}
void SideBarWidget::renamePlayList()
{
QList<MyToolButton *> list = this->findChildren<MyToolButton *>();
for(MyToolButton *tmp : list)
{
if(tmp->text() == btnText)
{
QString text = renameSongListPup->enterLineEdit->text();
if(text != "")
{
for(int i = 0;i< playListName.size();i++)
{
if(playListName.at(i) == text)
{
renameSongListPup->hide();
QMessageBox::warning(Widget::mutual,tr("Prompt information"),tr("Single song name already exists!!!"),QMessageBox::Ok);
return ;
}
}
tmp->setText(text);
playController::getInstance().setCurList(text);
for(int i = 0; i < playListName.size();i++)
{
if(btnText == playListName[i])
{
playListName[i] = text;
}
}
g_db->renamePlayList(btnText,text); // 从数据库中重命名
Q_EMIT playListRenamed(btnText,text); //fff
renameSongListPup->hide();
}
else
{
QString listName = btnText;
tmp->setText(listName);
playController::getInstance().setCurList(listName);
renameSongListPup->hide();
}
}
}
}
void SideBarWidget::removePlayList(QString text)
{
QList<MyToolButton *> list = this->findChildren<MyToolButton *>();
MyToolButton *tmp = nullptr;
for(auto i = list.begin();i < list.end();i++)
{
if((*i)->text() == text)
{
if(i+1 == list.end())
{
tmp = *(i-1);
tmp->click();
}
else
{
tmp = *(i+1);
tmp->click();
}
//删除歌单时删除改播放歌单的所有media
int ret;
QList<musicDataStruct> musicDateList;
ret = g_db->getSongInfoListFromPlayList(musicDateList,text);
if(ret == DB_OP_SUCC)
{
for(int i = 0; i < musicDateList.size(); i++)
{
playController::getInstance().removeSongFromCurList(text, 0);
}
}
(*i)->deleteLater();
g_db->delPlayList(text);
playListName.removeOne(text);
}
}
Q_EMIT playListRemoved(text);
// promptSongListPup->pupDialog->hide();
}
void SideBarWidget::slotListSearch()
{
QList<MyToolButton *> list = this->findChildren<MyToolButton *>();
for(MyToolButton *tmp : list)
{
tmp->setStatusTip("");
tmp->buttonListName = "";
tmp->defaultStyle();
}
}
void SideBarWidget::slotSongListHigh()
{
QList<MyToolButton *> list = this->findChildren<MyToolButton *>();
for(MyToolButton *tmp : list)
{
tmp->setStatusTip("");
tmp->buttonListName = "";
tmp->defaultStyle();
}
playListBtn->setStatusTip(IS_SELECT);
playListBtn->buttonListName = ALLMUSIC;
playListBtn->defaultStyle();
}

100
UI/sidebar/sidebarwidget.h Normal file
View File

@ -0,0 +1,100 @@
#ifndef SIDEBARWIDGET_H
#define SIDEBARWIDGET_H
#include <QWidget>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QScrollArea>
#include <UI/base/allpupwindow.h>
#include <QPalette>
#include <QPainter>
#include <QPainterPath>
#include <QColor>
#include <QStyleOption>
#include <QGSettings>
#include "myscrollarea.h"
#include "mytoolbutton.h"
#include "leftsiderbarwidget.h"
class SideBarWidget : public LeftsiderbarWidget
{
Q_OBJECT
public:
explicit SideBarWidget(QWidget *parent = nullptr);
public:
void sidecolor();
public:
//新建歌单弹窗界面
AllPupWindow *newSonglistPup = nullptr;
//重命名歌单弹窗界面
AllPupWindow *renameSongListPup = nullptr;
MyToolButton *playListBtn = nullptr;
public Q_SLOTS:
//添加歌单弹窗输入框
void addPlayList();
//添加歌单
void addItemToSongList();
//歌单播放
void playAll(QString btnText);
void rename(QString btnText);
//歌单重命名
void renamePlayList();
//删除歌单
void removePlayList(QString text);
//取消侧边栏所有按钮的选中状态
void slotListSearch();
//高亮歌曲列表按钮
void slotSongListHigh();
Q_SIGNALS:
void playListBtnCliced(QString listname);
void playListRemoved(QString listname);
void playListRenamed(QString oldName,QString newName);
void playListAdded(QString listName);
void signalPlayAll(QString listName);
private:
void initWidget();
void initConnect();
//获取歌单名称
void getPlayListName();
//输入为空添加歌单
QString newPlayListName();
private:
//歌曲列表 QToolButton
//MyToolButton *playListBtn;
//我喜欢 QToolButton
// MyToolButton *loveBun;
QGSettings *m_transparencyGSettings = nullptr; // 控制面板透明度
double m_transparency = 1.0; // 透明度
//添加歌单按钮
QPushButton *myPlayListBtn = nullptr;
//新建歌单按钮界面(包含我喜欢在内)
myScrollArea *scrollArea;
QWidget *newPlayListWidget = nullptr;
QWidget *logoWid = nullptr;
QWidget *mainWid = nullptr;
// QWidget *sideWid = nullptr;
QVBoxLayout *newPlayListLayout = nullptr;
//歌单名
QStringList playListName;
//音乐库label
QLabel *libraryLabel = nullptr;
//我的歌单label
QLabel *myPlayListLabel = nullptr;
//获取歌单名
QString btnText;
//保存程序关闭之前歌单按钮
MyToolButton *m_lastBtn = nullptr;
};
#endif // SIDEBARWIDGET_H

View File

@ -0,0 +1,80 @@
#include "tablebaseview.h"
#include "UI/base/widgetstyle.h"
TableBaseView::TableBaseView(QTableView *parent)
{
m_delegate = new TableViewDelegate();
setItemDelegate(m_delegate);
connect(this,&TableBaseView::hoverIndexChanged,m_delegate,&TableViewDelegate::onHoverIndexChanged);
connect(this,&TableBaseView::leaveFromItem,m_delegate,&TableViewDelegate::onLeaveFromItemEvent);
this->setMouseTracking(true);
initStyle();
}
void TableBaseView::initStyle()
{
setEditTriggers(QAbstractItemView::NoEditTriggers);
setSelectionBehavior(QAbstractItemView::SelectRows);//设置选中模式为选中行
setSelectionMode(QAbstractItemView::ExtendedSelection);//设置按ctrl键选中多个
// setAutoScroll(false);
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
// setAutoFillBackground(true);
setAlternatingRowColors(false);
this->setAutoScroll(false);
// this->verticalScrollBarPolicy();
// this->setAutoFillBackground(false);
//限制应用内字体固定大小
// QFont sizeFont;
// sizeFont.setPixelSize(14);
// this->setFont(sizeFont);
}
TableBaseView::~TableBaseView()
{
if(m_delegate!=nullptr) {
m_delegate->deleteLater();
}
}
QString TableBaseView::getSearchText()const
{
return m_searchText;
}
void TableBaseView::setSearchText(QString text)
{
m_searchText = text;
}
QString TableBaseView::getSearchListName()const
{
return m_searchListName;
}
void TableBaseView::setSearchListName(QString listName)
{
m_searchListName = listName;
}
void TableBaseView::mouseMoveEvent(QMouseEvent *event)
{
QModelIndex index = this->indexAt(event->pos());
Q_EMIT hoverIndexChanged(index);
}
void TableBaseView::leaveEvent(QEvent *event)
{
Q_EMIT leaveFromItem();
viewport()->update();
}
QString TableBaseView::getNowPlayListName()const
{
return m_nowListName;
}
void TableBaseView::setNowPlayListName(QString listName)
{
m_nowListName = listName;
}

View File

@ -0,0 +1,43 @@
#ifndef TABLEBASEVIEW_H
#define TABLEBASEVIEW_H
#include <QWidget>
#include <QTableView>
#include <QHeaderView>
#include <QStandardItemModel>
#include <QStandardItemModel>
#include "UIControl/tableview/musiclistmodel.h"
#include "UIControl/base/musicDataBase.h"
#include "tableviewdelegate.h"
class TableBaseView : public QTableView
{
Q_OBJECT
// void mouseMoveEvent(QMouseEvent *event);
public:
explicit TableBaseView(QTableView *parent = nullptr);
~TableBaseView();
MusicListModel *m_model = nullptr;
QString getSearchText()const;
QString getSearchListName()const;
QString getNowPlayListName()const;
public:
void setSearchText(QString text);
void setSearchListName(QString listName);
public Q_SLOTS:
void setNowPlayListName(QString listName);
protected:
void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void leaveEvent(QEvent *event) Q_DECL_OVERRIDE;
Q_SIGNALS:
void hoverIndexChanged(QModelIndex index);
void leaveFromItem();
private:
TableViewDelegate *m_delegate = nullptr;
QString m_searchText;
QString m_searchListName;
QString m_nowListName = "";
private:
void initStyle();
};
#endif // TABLEBASEVIEW_H

View File

@ -0,0 +1,380 @@
#include "tablehistory.h"
#include "UI/mainwidget.h"
#define PT_15 15
TableHistory::TableHistory(QWidget *parent) : QDialog(parent)
{
initSetModel();
initStyle();
initConnect();
initRightMenu();
initTableStyle();
qDebug() << "播放历史列表初始化完成.";
}
void TableHistory::initSetModel()
{
//禁用界面拖拽
this->setProperty("useStyleWindowManager", false);
mainVLayout = new QVBoxLayout();
m_tableHistory = new TableBaseView;
m_tableHistory->setObjectName("m_tableHistory");
m_tableHistory->setContextMenuPolicy(Qt::CustomContextMenu);
m_tableHistory->setSelectionMode(QAbstractItemView::SingleSelection);
m_tableHistory->setShowGrid(false);
m_tableHistory->verticalHeader()->setDefaultSectionSize(40);
m_model = new MusicListModel;
QList<musicDataStruct> resList;
g_db->getSongInfoListFromHistoryMusic(resList);
m_model->add(resList);
m_model->setView(*m_tableHistory);
historyTitileLabel = new QLabel(this);
historyTitileLabel->setText(tr("History"));
listCountLabel = new QLabel(this);
historyTitileWidget = new QWidget(this);
historyTitileWidget->setFixedHeight(64);
deleteAllBtn = new QToolButton(this);
deleteAllBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
deleteAllBtn->setIconSize(QSize(16,16));
deleteAllBtn->setIcon(QIcon::fromTheme("edit-delete-symbolic"));
deleteAllBtn->setText(tr("Empty"));
titleHBoxLayout = new QHBoxLayout();
historyTitileWidget->setLayout(titleHBoxLayout);
titleHBoxLayout->addWidget(historyTitileLabel,0,Qt::AlignLeft);
titleHBoxLayout->addWidget(listCountLabel,1,Qt::AlignBottom);
titleHBoxLayout->addWidget(deleteAllBtn,Qt::AlignRight);
titleHBoxLayout->setContentsMargins(16,16,16,12);
nullPageWidget = new QWidget(this);
nullIconLabel = new QLabel(this);
if (WidgetStyle::themeColor == 1) {
// black theme
nullIconLabel->setPixmap(QPixmap(":/img/default/defaultIconDark.png").scaled(200,180));
} else {
nullIconLabel->setPixmap(QPixmap(":/img/default/defaultIconLight.png").scaled(200,180));
}
nullTextLabel = new QLabel(this);
nullTextLabel->setFixedHeight(30);
nullTextLabel->setText(tr("The playlist has no songs"));
nullPageLayout = new QVBoxLayout();
nullPageLayout->addStretch(1);
nullPageLayout->addWidget(nullIconLabel);
nullIconLabel->setAlignment(Qt::AlignHCenter);
nullPageLayout->addWidget(nullTextLabel);
nullTextLabel->setAlignment(Qt::AlignHCenter);
nullPageLayout->addStretch(1);
nullPageLayout->setSpacing(20);
nullPageLayout->setAlignment(Qt::AlignCenter);
nullPageWidget->setLayout(nullPageLayout);
mainVLayout->addWidget(historyTitileWidget,Qt::AlignTop);
// mainVLayout->addStretch(0);
mainVLayout->addWidget(m_tableHistory);
mainVLayout->addWidget(nullPageWidget);
mainVLayout->setMargin(0);
mainVLayout->setSpacing(0);
this->setLayout(mainVLayout);
this->setFixedWidth(320);
this->setAutoFillBackground(true);
this->setBackgroundRole(QPalette::Base);
// this->setAutoFillBackground(true);
// this->setBackgroundRole(QPalette::Base);
changeNumber();
}
void TableHistory::initStyle()
{
m_tableHistory->setStyleSheet("#m_tableHistory{border:none;}");
historyTitileLabel->setStyleSheet("height:20px;\
font-weight: 600;\
line-height: 20px;");
listCountLabel->setStyleSheet("font-weight: 400;color:#8C8C8C;\
line-height: 14px;");
deleteAllBtn->setStyleSheet("color:#8F9399;background:transparent;");
}
void TableHistory::slotLableSetFontSize(int size)
{
//默认大小12px,换算成pt为9
double lableBaseFontSize = PT_15;//魔鬼数字,自行处理
double nowFontSize = lableBaseFontSize * double(size) / 11;//11为系统默认大小魔鬼数字自行处理
QFont font;
font.setPointSizeF(nowFontSize);
historyTitileLabel->setFont(font);
}
void TableHistory::deleteAllClicked()
{
QMessageBox msg(QMessageBox::Warning,tr("Prompt information"),tr("Clear the playlist?"),QMessageBox::Yes|QMessageBox::No,Widget::mutual);
int ret = msg.exec();
if(ret == QMessageBox::Yes)
{
for(int i = 0;i < m_model->count();i++)
{
playController::getInstance().removeSongFromCurList(HISTORY, 0);
}
int result = g_db->emptyHistoryMusic();
if(result == DB_OP_SUCC) {
m_model->clear();
changeNumber();
}
else {
return;
}
}
else
{
return;
}
}
void TableHistory::slotPlayIndexChanged(int index, QString listname)
{
if(listname == HISTORY) {
nowPlayListName = HISTORY;
nowPlayIndex = index;
noRefreshHistory();
}
else {
nowPlayListName = listname;
}
}
void TableHistory::slotPlayPathChanged(QString songPath)
{
if(nowPlayListName != HISTORY && songPath != "") {
int ret = g_db->addMusicToHistoryMusic(songPath);
if(ret == DB_OP_SUCC) {
nowPlayIndex = 0;
refreshHistoryTable();
}
else {
return;
}
}
else if(songPath == "")
{
nowPlayIndex = -1;
noRefreshHistory();
}
else
{
return;
}
}
bool TableHistory::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
Q_UNUSED(result);
if(eventType != "xcb_generic_event_t")
{
return false;
}
xcb_generic_event_t *event = (xcb_generic_event_t*)message;
switch (event->response_type & ~0x80)
{
case XCB_FOCUS_OUT:
// -playHistoryPosWidth (负数原因:因为计算按钮的右下角点)
QRect rect(playHistoryPosX, playHistoryPosY, -playHistoryPosWidth, playHistoryPosHeight);
if(rect.contains(QCursor::pos(), false)) {
return false;
}
if (this->geometry().contains(QCursor::pos(), false)) {
return false;
}
this->hide();
Q_EMIT signalHistoryBtnChecked(false);
break;
}
return false;
}
void TableHistory::initTableStyle()
{
m_tableHistory->hideColumn(2);
m_tableHistory->setColumnWidth(0,150);
m_tableHistory->setColumnWidth(1,80);
m_tableHistory->setColumnWidth(3,40);
m_tableHistory->setAutoFillBackground(true);
m_tableHistory->verticalHeader()->setVisible(false);// 垂直不可见
m_tableHistory->horizontalHeader()->setVisible(false);
m_tableHistory->setAlternatingRowColors(false);
}
void TableHistory::initConnect()
{
connect(deleteAllBtn,&QToolButton::clicked,this,&TableHistory::deleteAllClicked);
connect(m_tableHistory,&TableHistory::customContextMenuRequested,this,&TableHistory::showRightMenu);
connect(m_tableHistory,&TableBaseView::doubleClicked,this,&TableHistory::playSongs);
connect(&playController::getInstance(),&playController::currentIndexAndCurrentList,this,&TableHistory::slotPlayIndexChanged);
connect(&playController::getInstance(),&playController::singalChangePath,this,&TableHistory::slotPlayPathChanged);
}
void TableHistory::showHistroryPlayList()
{
if(this->isVisible())
{
this->hide();
signalHistoryBtnChecked(false);
}
else
{
Widget::mutual->movePlayHistoryWid();
this->show();
signalHistoryBtnChecked(true);
this->raise();
}
m_tableHistory->setAlternatingRowColors(false);
}
void TableHistory::changeNumber()
{
int num = m_model->count();
listCountLabel->setText(QString::number(num) + tr(" songs"));
if(num == 0) {
nullPageWidget->show();
m_tableHistory->hide();
isHightLight = false;
} else{
nullPageWidget->hide();
m_tableHistory->show();
}
}
void TableHistory::refreshHistoryTable()
{
m_model->clear();
QList<musicDataStruct> resList;
g_db->getSongInfoListFromHistoryMusic(resList);
m_model->add(resList);
changeNumber();
initTableStyle();
setHighlight(nowPlayIndex);
}
void TableHistory::noRefreshHistory()
{
changeNumber();
initTableStyle();
setHighlight(nowPlayIndex);
}
void TableHistory::initRightMenu()
{
m_menu = new QMenu;
playRow = new QAction(tr("Play"));
removeRow = new QAction(tr("Delete"));
playNextRow = new QAction(tr("Play the next one"));
m_menu->addAction(playRow);
m_menu->addAction(removeRow);
// m_menu->addAction(playNextRow);
connect(playRow,&QAction::triggered,this,&TableHistory::playSongs);
connect(removeRow,&QAction::triggered,this,&TableHistory::deleteSongs);
connect(playNextRow,&QAction::triggered,this,&TableHistory::playNextRowClicked);
// m_tableHistory->installEventFilter(this);
}
void TableHistory::showRightMenu(const QPoint &pos)
{
QModelIndex index = m_tableHistory->indexAt(pos);
if(index.row() < 0)
{
return;
}
m_menu->exec(QCursor::pos());
}
void TableHistory::playSongs()
{
int index = m_tableHistory->currentIndex().row();
musicDataStruct date = m_model->getItem(index);
QStringList pathList;
pathList = m_model->getPathList(nowListName);
playController::getInstance().setCurPlaylist(nowListName,pathList);
playController::getInstance().play(nowListName,index);
Q_EMIT signalHistoryPlaying();
}
void TableHistory::deleteSongs()
{
int index = m_tableHistory->currentIndex().row();
// if(index == nowPlayIndex && nowPlayListName != HISTORY) {
// QMessageBox::warning(Widget::mutual,tr("Prompt information"),tr("歌曲列表或歌单中正在播放此歌曲,无法删除~"));
// return;
// }
musicDataStruct date = m_model->getItem(index);
// g_db->delMusicFromPlayList(date.filepath,nowListName);
playController::getInstance().removeSongFromCurList(nowListName,index);
g_db->delMusicFromHistoryMusic(date.filepath);
if(index == nowPlayIndex && nowPlayListName != HISTORY) {
nowPlayIndex = -1;
}
refreshHistoryTable();
}
void TableHistory::playNextRowClicked()
{
}
void TableHistory::changePlayHistoryPos(int posX, int posY, int width, int height)
{
playHistoryPosX = posX;
playHistoryPosY = posY;
playHistoryPosWidth = width;
playHistoryPosHeight = height;
}
void TableHistory::setHighlight(int index)
{
//播放历史模块高亮
if(m_model->count() == 0 || index >= m_model->count()) {
return;
}
if(WidgetStyle::themeColor == 0)
{
for (int i = 0 ;i<4 ;i++ )
{
for(int j = 0; j < m_model->count() ; j++)
{
m_model->m_model.item(j,i)->setForeground(QBrush(QColor(Qt::black)));
}
}
if(index != -1)
{
for (int i = 0 ; i<4 ;i++ )
{
m_model->m_model.item(index,i)->setData(QBrush(QColor(55,144,250)),Qt::ForegroundRole);
}
}
}
if(WidgetStyle::themeColor == 1)
{
for (int i = 0; i < 4; i++ )
{
for(int j = 0; j < m_model->count() ; j++)
{
m_model->m_model.item(j,i)->setForeground(QBrush(QColor(Qt::white)));
}
}
if(index != -1)
{
for (int i = 0 ; i<4 ;i++ )
{
// m_model->m_model.item(heightLightIndex,i)->setForeground(QBrush(QColor(55,144,250)));
m_model->m_model.item(index,i)->setData(QBrush(QColor(55,144,250)),Qt::ForegroundRole);
}
}
}
}

View File

@ -0,0 +1,96 @@
#ifndef TABLEHISTORY_H
#define TABLEHISTORY_H
#include <QWidget>
#include <QListView>
#include <QLabel>
#include <QToolButton>
#include <QTableView>
#include <QStandardItemModel>
#include <QStandardItem>
#include <QSqlRelationalTableModel>
#include <QSqlTableModel>
#include <QSqlQueryModel>
#include <QDebug>
#include <QHeaderView>
#include <QMenu>
#include <QVBoxLayout>
#include <QAction>
#include <QFileDialog>
#include <QMessageBox>
#include <QMouseEvent>
#include <QFrame>
#include <QGraphicsDropShadowEffect>
#include <QHeaderView>
#include "tablebaseview.h"
#include "UIControl/tableview/musiclistmodel.h"
#include "UIControl/base/musicDataBase.h"
#include "UIControl/player/player.h"
#include "UI/base/widgetstyle.h"
class TableHistory : public QDialog
{
Q_OBJECT
public:
explicit TableHistory(QWidget *parent = nullptr);
TableBaseView *m_tableHistory = nullptr;
MusicListModel *m_model = nullptr;
void changeNumber();
void setHighlight(int index);
void initStyle();
void initTableStyle();
bool isHightLight = false;
void refreshHistoryTable();
void noRefreshHistory();
void deleteAllClicked();
void changePlayHistoryPos(int posX, int posY, int width, int height);
public Q_SLOTS:
void showHistroryPlayList();
// void addMusicToHistoryListSlot();
void slotPlayIndexChanged(int index, QString listname);
void slotPlayPathChanged(QString songPath);
//字体
void slotLableSetFontSize(int size);
protected:
bool nativeEvent(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;
Q_SIGNALS:
void signalHistoryPlaying();
void signalHistoryBtnChecked(bool checked);
private Q_SLOTS:
void playSongs();
void deleteSongs();
void playNextRowClicked();
void showRightMenu(const QPoint &pos);
private:
void initRightMenu();
QVBoxLayout *mainVLayout = nullptr;
QHBoxLayout *titleHBoxLayout = nullptr;
void initSetModel();
void initConnect();
QLabel *listCountLabel = nullptr;
QLabel *historyTitileLabel = nullptr;
QToolButton *deleteAllBtn = nullptr;
QWidget *historyTitileWidget = nullptr;
QAction *playRow = nullptr;
QAction *removeRow = nullptr;
QAction *playNextRow = nullptr;
QMenu *m_menu = nullptr;
QString nowListName = HISTORY;
QString nowPlayListName = "";
int nowPlayIndex = -1;
QWidget *nullPageWidget = nullptr;
QVBoxLayout *nullPageLayout = nullptr;
QLabel *nullIconLabel = nullptr;
QLabel *nullTextLabel = nullptr;
QHeaderView *horizonHeader = nullptr;
private:
int playHistoryPosX;
int playHistoryPosY;
int playHistoryPosWidth;
int playHistoryPosHeight;
};
#endif // TABLEHISTORY_H

1242
UI/tableview/tableone.cpp Normal file

File diff suppressed because it is too large Load Diff

167
UI/tableview/tableone.h Normal file
View File

@ -0,0 +1,167 @@
#ifndef TableOne_H
#define TableOne_H
#include <QWidget>
#include <QLabel>
#include <QToolButton>
#include <QTableView>
#include <QStandardItemModel>
#include <QStandardItem>
#include <QDebug>
#include <QHeaderView>
#include <QMenu>
#include <QVBoxLayout>
#include <QAction>
#include <QFileDialog>
#include <QMessageBox>
#include <QMouseEvent>
#include <QFileSystemWatcher>
#include <QStandardPaths>
#include <QScrollArea>
#include <QScrollBar>
#include <QProcess>
#include "UIControl/base/musicDataBase.h"
#include "UIControl/tableview/musiclistmodel.h"
#include "UIControl/player/player.h"
#include "tableviewdelegate.h"
#include "tablebaseview.h"
#include "UIControl/base/musicfileinformation.h"
#include "UI/base/mylabel.h"
#include "UI/base/widgetstyle.h"
#include "UI/base/allpupwindow.h"
class TableOne : public QWidget
{
Q_OBJECT
public:
explicit TableOne(QString listName,QWidget *parent = nullptr);
~TableOne();
public:
/// 基于MVC设计模式设计的, C(controllor)控制在Qt中被弱化与View合并到一起。
/// 表格视图控件 V(TableBaseView),需要和 M(MusicListModel), 配套使用
MusicListModel *m_model = nullptr; // 数据模型,不能单独显示出来
TableBaseView *tableView = nullptr; // 视图要来显示数据模型MusicListModel 歌单列表,包括歌单标题和内容
QLabel *listTitleLabel = nullptr; // 歌单名称
QString nowListName;
MusicInfoDialog *infoDialog = nullptr;
void changeNumber();
void initTableViewStyle();
void setHightLightAndSelect();
void getMusicList();
void playMusicforIndex(QString listName,int index);
//通过列表名和索引值播放相应歌曲
void showTitleText(QString listName);
void initStyle();
void addMusicToDatebase(QStringList fileNames);
public Q_SLOTS:
void slotSearchTexts(QString text);
void slotSearchReturnPressed(QString listName);
void slotLableSetFontSize(int size);
void slotFilePath(QString path);
void slotSongListBySinger(QString singer);
void slotSongListByAlbum(QString album);
private:
void initUI(); //初始化ui
void initConnect(); //信号绑定
void initRightMenu(); //初始化右键菜单
void tableViewDoubleClicked(); //双击播放
// static void deleteImage(const QString &savepath);
//成功添加多少首歌曲
void importFinished(int successCount, int failCount, int allCount);
//导入失败
void importFailed(int successCount, int failCount, int allCount);
void showRightMenu(const QPoint &pos);
void isDeleteSongs(); //是否从歌单中删除歌曲
void isDeleteLocalSongs(); //是否从本地删除歌曲
void deleteSongs(); //从歌单中删除歌曲
void deleteLocalSongs(); //从本地以及歌单中删除歌曲
void playSongs();
void showInfo();
void addToOtherList(QAction *listNameAction);
void addMusicSlot(); // 添加歌曲文件槽函数
void addDirMusicSlot(); //添加文件夹槽函数
// void addMusicToDatebase(QStringList fileNames);
// void importSongs(QString path);
void clearSearchList();
QMenu *m_menu = nullptr; //新建一个Menu属性
QSqlQueryModel *tableModel = nullptr;
QAction * playRow = nullptr;
QAction * removeRow = nullptr;
QAction * removeLocalRow = nullptr;
QAction * showInfoRow = nullptr;
QMenu * addToOtherListMenu = nullptr;
QMap<int,QString> getSelectedTaskIdList();
QMenu *add_menu = nullptr;
QAction *addMusicFileAction = nullptr;
QAction *addDirMusicAction = nullptr;
TableViewDelegate *delegate = nullptr;
QHBoxLayout *listTitleHBoxLayout = nullptr;
QToolButton *addMusicButton = nullptr; //添加歌曲按钮
QPushButton *playAllButton = nullptr;
QLabel *listTotalNumLabel = nullptr; // 统计歌单中歌曲总数
int heightLightIndex = -1;
QString nowPlayListName; //后端播放器中正在播放的列表名
Q_SIGNALS:
void sendPathToPlayer(QString fp);
void countChanges();
void hoverIndexChanged(QModelIndex index);
void refreshHistoryListSignal();
// void heightIndexChanged(int index);
void addILoveFilepathSignal(QString filePath); //传递我喜欢歌单中添加歌曲的信号
void removeILoveFilepathSignal(QString filePath); //传递我喜欢歌单中删除歌曲的信号
void signalListSearch(); //取消侧边栏所有按钮的选中状态
void signalSongListHigh(); //高亮左侧歌曲列表按钮
public Q_SLOTS:
void selectListChanged(QString listname); //切换歌单
void playListRenamed(QString oldName,QString newName); //歌单重命名
void getHightLightIndex(int index, QString listName); //获得正在播放的歌曲索引和歌单名
void playAll(QString listName); //播放全部歌曲
void playAllButtonClicked();
void slotReturnText(QString text);
protected:
void dragEnterEvent(QDragEnterEvent *event)Q_DECL_OVERRIDE;
void dropEvent(QDropEvent *event)Q_DECL_OVERRIDE;
void mouseMoveEvent(QMouseEvent *event)Q_DECL_OVERRIDE;
void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE;
void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
private:
QWidget *m_musicWidget = nullptr;
QVBoxLayout *m_historyLayout = nullptr;
QWidget *nullPageWidget = nullptr;
QVBoxLayout *nullPageVLayout = nullptr;
QHBoxLayout *nullPageHLayout = nullptr;
QPushButton *n_addMusicButton = nullptr;
QPushButton *n_addDirMusicButton = nullptr;
QLabel *nullPageIconLabel = nullptr;
QLabel *nullPageTextLabel = nullptr;
QHeaderView *horizonHeader = nullptr; // 表头内容
QWidget *titleWid = nullptr;
int showScrollbarNumber = 10;
QString m_text;
QMap<int,QString> m_map;
};
#endif // TableOne_H

View File

@ -0,0 +1,156 @@
#include "tableviewdelegate.h"
#include "UI/base/widgetstyle.h"
#include "UIControl/player/player.h"
#include "UIControl/base/musicDataBase.h"
#include "UI/search/musicsearchlistview.h"
#include "UI/tableview/tablebaseview.h"
#include <QTextDocument>
#include <QAbstractTextDocumentLayout>
TableViewDelegate::TableViewDelegate(QWidget *parent)
: QStyledItemDelegate(parent),
m_pOpenButton(new QPushButton()),
m_pDeleteButton(new QPushButton()),
m_nSpacing(5),
m_nWidth(25),
m_nHeight(20),
m_hoverrow(-1)
{
}
TableViewDelegate::~TableViewDelegate()
{
}
// 绘制按钮
void TableViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
const TableBaseView *tableview = qobject_cast<const TableBaseView *>(option.widget);
QString listName = tableview->getNowPlayListName();
QStyleOptionViewItem opt = option;
if (index.row() == m_hoverrow ) {
opt.state |= QStyle::State_Selected;
} else {
opt.state &= ~QStyle::State_MouseOver;
}
//字体高亮颜色
opt.palette.setColor(QPalette::HighlightedText,index.data(Qt::ForegroundRole).value<QColor>());
if (WidgetStyle::themeColor == 0) {
opt.palette.setColor(QPalette::Highlight,QColor(240,240,240));
} else {
opt.palette.setColor(QPalette::Highlight,QColor(54,54,55));
}
QString playListName = tableview->getSearchListName();
if (listName != playListName || playListName == "") {
QStyledItemDelegate::paint(painter,opt,index);
return;
}
//以下是对搜索结果列表的处理
//设置选中和悬停样式
if (opt.state & QStyle::State_Selected) {
painter->fillRect(opt.rect, opt.palette.color(QPalette::Highlight));
}
// 根据关键字高亮
QString searchText = tableview->getSearchText();
QColor textColor;
QColor lightColor;
//设置非高亮字颜色
if (WidgetStyle::themeColor == 1) {
textColor = QColor("#FFFFFF");
} else if (WidgetStyle::themeColor == 0) {
textColor = QColor("#000000");
}
//如果文件不存在需要置灰
if (index.data(Qt::StatusTipRole).toString() == QString("nofile")) {
textColor = QColor(Qt::gray);
}
//设置高亮字的颜色
QPalette pa = option.palette;
QBrush selectBrush = pa.brush(QPalette::Active, QPalette::Highlight);
QColor selectColor = selectBrush.color();
lightColor = selectColor;
//获取该单元格文本
QString mtext = index.data(Qt::DisplayRole).value<QString>();
//超过单元格宽度,末尾换成...
QFontMetricsF fontWidth(tableview->font());
mtext = fontWidth.elidedText(mtext, Qt::ElideRight, 136);//魔鬼数字,且没考虑全屏布局,此处待优化
// 设置文字边距,保证绘制文字居中
QTextDocument document;
document.setDocumentMargin(0);
document.setPlainText(mtext);
QTextCursor highlight_cursor(&document);
QTextCursor cursor(&document);
cursor.beginEditBlock();
QTextCharFormat color_format(highlight_cursor.charFormat());
color_format.setForeground(lightColor);
// 搜索字体高亮
QTextCursor testcursor(&document);
testcursor.select(QTextCursor::LineUnderCursor);
QTextCharFormat fmt;
fmt.setForeground(textColor);
testcursor.mergeCharFormat(fmt);
testcursor.clearSelection();
testcursor.movePosition(QTextCursor::EndOfLine);
//当前正在播放的歌曲全部高亮
if (index.data(Qt::StatusTipRole).toString() == QString("heightLight")) {
searchText = mtext;
}
//关键字高亮
while (!highlight_cursor.isNull() && !highlight_cursor.atEnd()) {
highlight_cursor = document.find(searchText, highlight_cursor);
if (!highlight_cursor.isNull()) {
highlight_cursor.mergeCharFormat(color_format);
}
}
cursor.endEditBlock();
//调整布局
QStyle *pStyle = option.widget ? option.widget->style() : QApplication::style();
QAbstractTextDocumentLayout::PaintContext paintContext;
QRect textRect = pStyle->subElementRect(QStyle::SE_ItemViewItemText, &option);
double moveX = 25;//x轴偏移量
double moveY = opt.rect.height() / 2 - fontWidth.height() / 2;//y轴偏移量
if (index.column()+1 == index.model()->columnCount()) {
moveX = 77 - fontWidth.width(mtext);
}
//绘制
painter->save();
painter->translate(double(textRect.topLeft().rx()) + moveX ,double(textRect.topLeft().ry()) + moveY );
document.documentLayout()->draw(painter, paintContext);
painter->restore();
}
void TableViewDelegate::onHoverIndexChanged(const QModelIndex& index)
{
m_hoverrow = index.row();
}
void TableViewDelegate::onLeaveFromItemEvent()
{
m_hoverrow = -1;
}
QSize TableViewDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(option)
Q_UNUSED(index)
return QSize(690, 40);
}

View File

@ -0,0 +1,45 @@
#ifndef TABLEVIEWDELEGATE_H
#define TABLEVIEWDELEGATE_H
#include <QObject>
#include <QItemDelegate>
#include <QPainter>
#include <QApplication>
#include <QEvent>
#include <QMouseEvent>
#include <QDebug>
#include <QPushButton>
#include <QStyledItemDelegate>
#include <QToolTip>
class TableViewDelegate: public QStyledItemDelegate
{
Q_OBJECT
public:
explicit TableViewDelegate(QWidget *parent = 0);
~TableViewDelegate();
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
void onHoverIndexChanged(const QModelIndex &index);
void onLeaveFromItemEvent();
Q_SIGNALS:
void open(const QModelIndex &index);
void deleteData(const QModelIndex &index);
void hoverIndexChanged(QModelIndex index);
private:
QPoint m_mousePoint; // 鼠标位置
QScopedPointer<QPushButton> m_pOpenButton;
QScopedPointer<QPushButton> m_pDeleteButton;
QStringList m_list;
int m_nSpacing; // 按钮之间的间距
int m_nWidth; // 按钮宽度
int m_nHeight; // 按钮高度
int m_nType; // 按钮状态-1划过 2按下
int m_hoverrow;
};
#endif // TABLEVIEWDELEGATE_H

356
UI/titlebar/menumodule.cpp Normal file
View File

@ -0,0 +1,356 @@
#include "menumodule.h"
#include "UI/mainwidget.h"
#include "UI/base/xatom-helper.h"
#define PT_14 14
menuModule::menuModule(QWidget *parent = nullptr) : QWidget(parent)
{
init();
}
void menuModule::init(){
initAction();
setStyle();
}
void menuModule::initAction(){
aboutWindow = new QWidget();
aboutWindow->setAutoFillBackground(true);
aboutWindow->setBackgroundRole(QPalette::Base);
titleText = new QLabel();
bodyAppName = new QLabel();
bodyAppVersion = new QLabel();
bodyAppDescribe = new QLabel();
bodySupport = new QLabel();
menuButton = new QToolButton;
menuButton->setProperty("isWindowButton", 0x1);
menuButton->setProperty("useIconHighlightEffect", 0x2);
menuButton->setPopupMode(QToolButton::InstantPopup);
menuButton->setFixedSize(30,30);
menuButton->setIconSize(QSize(16, 16));
menuButton->setAutoRaise(true);
menuButton->setIcon(QIcon::fromTheme("open-menu-symbolic"));
m_menu = new QMenu();
QList<QAction *> actions ;
QAction *actionTheme = new QAction(m_menu);
actionTheme->setText(tr("Theme"));
QAction *actionHelp = new QAction(m_menu);
actionHelp->setText(tr("Help"));
QAction *actionAbout = new QAction(m_menu);
actionAbout->setText(tr("About"));
QAction *actionQuit = new QAction(m_menu);
// actionQuit->setText(tr("Quit"));
// actions<<actionTheme<<actionHelp<<actionAbout<<actionQuit;
// actions<<actionTheme<<actionHelp<<actionAbout; //隐藏关于主题颜色的设置,默认跟随主题,不随着用户操作更改。
actions<<actionHelp<<actionAbout;
m_menu->addActions(actions);
// 互斥按钮组
QMenu *themeMenu = new QMenu;
QActionGroup *themeMenuGroup = new QActionGroup(this);
QAction *autoTheme = new QAction(tr("Auto"),this);
autoTheme->setObjectName("Auto");//用TEXT判断有风险
themeMenuGroup->addAction(autoTheme);
themeMenu->addAction(autoTheme);
autoTheme->setCheckable(true);
QAction *lightTheme = new QAction(tr("Light"),this);
lightTheme->setObjectName("Light");//用TEXT判断有风险
// themeMenuGroup->addAction(lightTheme);
// themeMenu->addAction(lightTheme);
lightTheme->setCheckable(true);
QAction *darkTheme = new QAction(tr("Dark"),this);
darkTheme->setObjectName("Dark");//用TEXT判断有风险
// themeMenuGroup->addAction(darkTheme);
// themeMenu->addAction(darkTheme);
darkTheme->setCheckable(true);
QList<QAction* > themeActions;
themeActions<<autoTheme<<lightTheme<<darkTheme;
// autoTheme->setChecked(true);
actionTheme->setMenu(themeMenu);
menuButton->setMenu(m_menu);
connect(m_menu,&QMenu::triggered,this,&menuModule::triggerMenu);
initGsetting();
setThemeFromLocalThemeSetting(themeActions);
themeUpdate();
connect(themeMenu,&QMenu::triggered,this,&menuModule::triggerThemeMenu);
//键盘F1响应唤出用户手册绑定
connect(Widget::mutual,&Widget::signalShowGuide,this,&menuModule::helpAction);
//限制应用字体不随着主题变化
// QFont sizeFont;
// sizeFont.setPixelSize(14);
// m_menu->setFont(sizeFont);
// bodyAppName->setFont(sizeFont);
// titleText->setFont(sizeFont);
// bodyAppVersion->setFont(sizeFont);
// bodyAppDescribe->setFont(sizeFont);
// bodySupport->setFont(sizeFont);
}
void menuModule::setThemeFromLocalThemeSetting(QList<QAction* > themeActions)
{
#if DEBUG_MENUMODULE
confPath = "org.kylin-music-data.settings";
#endif
m_pGsettingThemeStatus = new QGSettings(confPath.toLocal8Bit());
if(!m_pGsettingThemeStatus){
qDebug()<<"系统对应的gsetting字段未正确配置";
}
QString appConf = m_pGsettingThemeStatus->get("thememode").toString();
if("lightonly" == appConf){
themeStatus = themeLightOnly;
themeActions[1]->setChecked(true); //程序gsetting中为浅色only的时候就给浅色按钮设置checked
}else if("darkonly" == appConf){
themeStatus = themeBlackOnly;
themeActions[2]->setChecked(true);
}else{
themeStatus = themeAuto;
themeActions[0]->setChecked(true);
}
}
void menuModule::themeUpdate(){
// if(themeStatus == themeLightOnly)
// {
// setThemeLight();
// }else if(themeStatus == themeBlackOnly){
// setThemeDark();
// }else{
// setStyleByThemeGsetting();
// }
setStyleByThemeGsetting(); //应用颜色更新只跟随主题
}
void menuModule::setStyleByThemeGsetting(){
QString nowThemeStyle = m_pGsettingThemeData->get("styleName").toString();
if("ukui-dark" == nowThemeStyle || "ukui-black" == nowThemeStyle)
{
setThemeDark();
}else{
setThemeLight();
}
}
void menuModule::triggerMenu(QAction *act){
QString str = act->text();
if(tr("Quit") == str){
Q_EMIT menuModuleClose();
}else if(tr("About") == str){
aboutAction();
}else if(tr("Help") == str){
helpAction();
}
}
void menuModule::triggerThemeMenu(QAction *act){
if(!m_pGsettingThemeStatus)
{
m_pGsettingThemeStatus = new QGSettings(confPath.toLocal8Bit()); //m_pGsettingThemeStatus指针重复使用避免占用栈空间
}
QString str = act->objectName();
if("Light" == str){
themeStatus = themeLightOnly;
disconnect(m_pGsettingThemeData,&QGSettings::changed,this,&menuModule::dealSystemGsettingChange);
m_pGsettingThemeStatus->set("thememode","lightonly");
// disconnect()
setThemeLight();
}else if("Dark" == str){
themeStatus = themeBlackOnly;
disconnect(m_pGsettingThemeData,&QGSettings::changed,this,&menuModule::dealSystemGsettingChange);
m_pGsettingThemeStatus->set("thememode","darkonly");
setThemeDark();
}else{
themeStatus = themeAuto;
m_pGsettingThemeStatus->set("thememode","auto");
initGsetting();
// updateTheme();
themeUpdate();
}
}
void menuModule::aboutAction(){
// 关于点击事件处理
initAbout();
}
void menuModule::helpAction(){
// 帮助点击事件处理
#if DEBUG_MENUMODULE
appName = "tools/kylin-music";
#endif
if(!ipcDbus)
{
ipcDbus = new DaemonIpcDbus();
}
if(!ipcDbus->daemonIsNotRunning())
{
ipcDbus->showGuide(appName);
}
}
void menuModule::initAbout(){
aboutWindow->setWindowModality(Qt::ApplicationModal);
aboutWindow->setWindowFlag(Qt::Tool);
MotifWmHints hints;
hints.flags = MWM_HINTS_FUNCTIONS|MWM_HINTS_DECORATIONS;
hints.functions = MWM_FUNC_ALL;
hints.decorations = MWM_DECOR_BORDER;
XAtomHelper::getInstance()->setWindowMotifHint(aboutWindow->winId(), hints);
aboutWindow->setFixedSize(420,390);
QVBoxLayout *mainlyt = new QVBoxLayout();
QHBoxLayout *titleLyt = initTitleBar();
QVBoxLayout *bodylyt = initBody();
mainlyt->setMargin(0);
mainlyt->addLayout(titleLyt);
mainlyt->addLayout(bodylyt);
mainlyt->addStretch();
aboutWindow->setLayout(mainlyt);
//TODO:在屏幕中央显示
// QRect availableGeometry = qApp->primaryScreen()->availableGeometry();
// aboutWindow->move((availableGeometry.width()-aboutWindow->width())/2,(availableGeometry.height()- aboutWindow->height())/2);
//弹窗位置应用居中
QRect availableGeometry = Widget::mutual->geometry();
aboutWindow->move(availableGeometry.center() - aboutWindow->rect().center());
aboutWindow->show();
}
QHBoxLayout* menuModule::initTitleBar(){
QPushButton* titleIcon = new QPushButton();
QPushButton *titleBtnClose = new QPushButton;
titleIcon->setFixedSize(24,24);
titleIcon->setIconSize(QSize(25,25));
//TODO直接从主题调图标不会QIcon转qpixmap所以暂时从本地拿
// titleIcon->setPixmap(QPixmap::fromImage(QImage(iconPath)));
titleIcon->setIcon(QIcon::fromTheme("kylin-music"));
titleIcon->setStyleSheet("QPushButton{border:0px;background:transparent;}"
"QPushButton::hover{border:0px;background:transparent;}"
"QPushButton::pressed{border:0px;background:transparent;}");
// titleIcon->setScaledContents(true);
titleBtnClose->setFixedSize(30,30);
titleBtnClose->setIcon(QIcon::fromTheme("window-close-symbolic"));
titleBtnClose->setProperty("isWindowButton",0x2);
titleBtnClose->setProperty("useIconHighlightEffect",0x8);
titleBtnClose->setFlat(true);
connect(titleBtnClose,&QPushButton::clicked,[=](){aboutWindow->close();});
QHBoxLayout *hlyt = new QHBoxLayout;
titleText->setText(tr("Music Player"));
// titleText->setStyleSheet("font-size:14px;");
hlyt->setSpacing(0);
hlyt->setMargin(4);
hlyt->addSpacing(4);
hlyt->addWidget(titleIcon,0,Qt::AlignBottom); //居下显示
hlyt->addSpacing(8);
hlyt->addWidget(titleText,0,Qt::AlignBottom);
hlyt->addStretch();
hlyt->addWidget(titleBtnClose,0,Qt::AlignBottom);
return hlyt;
}
void menuModule::slotLableSetFontSize(int size)
{
//默认大小12px,换算成pt为9
double lableBaseFontSize = PT_14;//魔鬼数字,自行处理
double nowFontSize = lableBaseFontSize * double(size) / 11;//11为系统默认大小魔鬼数字自行处理
QFont font;
font.setPointSizeF(nowFontSize);
bodyAppName->setFont(font);
}
QVBoxLayout* menuModule::initBody(){
QPushButton* bodyIcon = new QPushButton();
// bodyIcon->setPixmap(QPixmap::fromImage(QImage(iconPath)));
// bodyIcon->setStyleSheet("font-size:14px;");
// bodyIcon->setScaledContents(true);
bodyIcon->setFixedSize(96,94);
bodyIcon->setIconSize(QSize(96,94));
bodyIcon->setIcon(QIcon::fromTheme("kylin-music"));
bodyIcon->setStyleSheet("QPushButton{border:0px;background:transparent;}"
"QPushButton::hover{border:0px;background:transparent;}"
"QPushButton::pressed{border:0px;background:transparent;}");
bodyAppDescribe->setText(tr("Music player is a multimedia playback software.Cover Various music formats Playback tools for,fast and simple."));
bodyAppDescribe->setFixedSize(380, 86);
// bodyAppDescribe->setFixedHeight();
// bodyAppDescribe->setStyleSheet("font-size:14px;");
bodyAppDescribe->setWordWrap(true);
// bodyAppName->setFixedHeight(28);
bodyAppName->setText(tr("Music Player"));
// bodyAppName->setStyleSheet("font-size:18px;");
// bodyAppVersion->setFixedHeight(24);
bodyAppVersion->setText(tr("Version: ") + appVersion);
bodyAppVersion->setAlignment(Qt::AlignLeft);
// bodyAppVersion->setStyleSheet("font-size:14px;");
connect(bodySupport,&QLabel::linkActivated,this,[=](const QString url){
QDesktopServices::openUrl(QUrl(url));
});
bodySupport->setContextMenuPolicy(Qt::NoContextMenu);
bodySupport->setFixedHeight(30);
// bodySupport->setStyleSheet("font-size:14px;");
QVBoxLayout *vlyt = new QVBoxLayout;
// vlyt->setMargin(0);
// vlyt->setSpacing(0);
// vlyt->addSpacing(20);
vlyt->addWidget(bodyIcon,0,Qt::AlignHCenter);
vlyt->addSpacing(5);
vlyt->addWidget(bodyAppName,0,Qt::AlignHCenter);
vlyt->addSpacing(5);
vlyt->addWidget(bodyAppVersion,0,Qt::AlignHCenter);
vlyt->addSpacing(5);
vlyt->addWidget(bodyAppDescribe,0,Qt::AlignLeft);
vlyt->addSpacing(5);
vlyt->addWidget(bodySupport,0,Qt::AlignLeft);
// vlyt->addStretch();
vlyt->setContentsMargins(20,10,20,10);
return vlyt;
}
void menuModule::setStyle(){
// menuButton->setStyleSheet("QPushButton::menu-indicator{image:None;}");
}
void menuModule::initGsetting(){
if(QGSettings::isSchemaInstalled(FITTHEMEWINDOWS)){
m_pGsettingThemeData = new QGSettings(FITTHEMEWINDOWS);
connect(m_pGsettingThemeData,&QGSettings::changed,this,&menuModule::dealSystemGsettingChange);
}
}
void menuModule::dealSystemGsettingChange(const QString key){
if(key == "styleName"){
refreshThemeBySystemConf();
}
}
void menuModule::refreshThemeBySystemConf(){
QString themeNow = m_pGsettingThemeData->get("styleName").toString();
if("ukui-dark" == themeNow || "ukui-black" == themeNow){
setThemeDark();
}else{
setThemeLight();
}
}
void menuModule::setThemeDark(){
Q_EMIT menuModuleSetThemeStyle("dark-theme");
bodySupport->setText(tr("Service & Support: ") +
"<a href=\"mailto://support@kylinos.cn\""
"style=\"color:rgba(225,225,225,1)\">"
"support@kylinos.cn</a>");
}
void menuModule::setThemeLight(){
Q_EMIT menuModuleSetThemeStyle("light-theme");
bodySupport->setText(tr("Service & Support: ") +
"<a href=\"mailto://support@kylinos.cn\""
"style=\"color:rgba(0,0,0,1)\">"
"support@kylinos.cn</a>");
}

94
UI/titlebar/menumodule.h Normal file
View File

@ -0,0 +1,94 @@
#ifndef MENUMODULE_H
#define MENUMODULE_H
#define DEBUG_MENUMODULE 0 //DEBUG模式开关代码上线之前务必关掉
#define FITTHEMEWINDOWS "org.ukui.style"
#define FITCONTROLTRANS "org.ukui.control-center.personalise"
#include <QObject>
#include <QWidget>
#include <QMenu>
#include <QPushButton>
#include <QToolButton>
#include <QDebug>
#include <QString>
#include <QLabel>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QRect>
#include <QScreen>
#include <QGSettings>
#include <QMetaEnum>
#include <QDesktopServices>
#include <QUrl>
#include "UIControl/base/daemonipcdbus.h"
#include "UI/base/widgetstyle.h"
class menuModule : public QWidget
{
Q_OBJECT
public:
explicit menuModule(QWidget *);
void themeUpdate();
enum typeThemeStatus {
themeAuto = 0,
themeBlackOnly = 1,
themeLightOnly = 2
} themeStatus;
Q_SIGNALS:
void menuModuleClose();
void menuModuleSetThemeStyle(QString);
public:
QToolButton *menuButton = nullptr;
public:
// 程序在实例化的时候需要传递的信息字段,打开debug开关后这些字段会被自动填充
QString appName = "kylin-music"; //格式kylin-usb-creator
// QString appShowingName = tr("kylin music"); //格式kylin usb creator ,用来在前端展示
QString appVersion = "1.1.0";
QString appDesc = "appDesc字段未填充";
QString iconPath = ":/img/kylin-music.png";
QString confPath = "org.kylin-music-data.settings";
private:
QMenu *m_menu = nullptr;
QMenu *themeMenu = nullptr;
QSize iconSize;
QString appPath = "tools/kylin-music"; //拉起帮助菜单时使用appName字段
QWidget *aboutWindow = nullptr;
QGSettings *m_pGsettingThemeData = nullptr;
QGSettings *m_pGsettingThemeStatus = nullptr;
public Q_SLOTS:
void dealSystemGsettingChange(const QString);
void slotLableSetFontSize(int size);
private:
void init();
QHBoxLayout* initTitleBar(); //关于窗口标题栏初始化
QVBoxLayout* initBody(); // 关于窗口body初始化
void initGsetting();
void initAction();
void setStyle();
void triggerMenu(QAction* act); //主菜单动作4
void triggerThemeMenu(QAction* act); //主题动作
void aboutAction();
void initAbout(); //关于窗口初始化
void helpAction();
void setThemeFromLocalThemeSetting(QList<QAction* >); //获取本地主题配置
void setStyleByThemeGsetting(); //通过外部主题配置设置主题
void setThemeStyle();
void setThemeLight();
DaemonIpcDbus *ipcDbus;
void setThemeDark();
QLabel* titleText = nullptr;
QLabel* bodyAppName = nullptr;
QLabel* bodyAppVersion = nullptr;
QLabel* bodyAppDescribe = nullptr;
QLabel* bodySupport = nullptr;
// void updateTheme(); //点击菜单中的主题设置后更新一次主题
QVBoxLayout *mainlyt = nullptr;
void refreshThemeBySystemConf(); //通过系统配置更改主题
};
#endif // MENUMODULE_H

323
UI/titlebar/titlebar.cpp Normal file
View File

@ -0,0 +1,323 @@
/*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* 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 <https://www.gnu.org/licenses/>.
*/
#include <QMenu>
#include <QFile>
#include "titlebar.h"
#include "UI/mainwidget.h"
#include "UI/base/xatom-helper.h"
TitleBar::TitleBar(QWidget *parent) : QFrame(parent)
{
this->m_parent = parent;
setMouseTracking(true);
this->installEventFilter(this);
this->setObjectName("TitleBar");
initTitle();
titlecolor();
}
void TitleBar::initTitle()
{
setStyleSheet(::main_style);
menumodule = new menuModule(this);
// menumodule->menuButton
resize(750,56);
titleLayout = new QHBoxLayout(this);
LayoutLeft = new QHBoxLayout;
leftBtn = new QPushButton;
// leftBtn->setIcon(QIcon::fromTheme("pan-start-symbolic"));
// leftBtn->setStyleSheet("QPushButton{background:transparent;}");
leftBtn->setStyleSheet("QPushButton{background:transparent;\
border-image:url(:/img/default/backoff.png);}");
leftBtn->setFixedSize(16,16);
// leftBtn->setStyleSheet()
// leftBtn->setToolTip("后退");
leftBtn->setCursor(Qt::PointingHandCursor);
leftBtn->setToolTip(tr("back"));
leftBtn->setDisabled(true);
leftBtn->setContentsMargins(8,0,0,0);
leftBtn->hide();
rightBtn = new QPushButton;
// rightBtn->setIcon(QIcon::fromTheme("pan-end-symbolic"));
rightBtn->setStyleSheet("QPushButton{background:transparent;}");
rightBtn->setStyleSheet("QPushButton{background:transparent;\
border-image:url(:/img/default/forward.png);}");
rightBtn->setFixedSize(16,16);
// rightBtn->setToolTip("前进");
rightBtn->setCursor(Qt::PointingHandCursor);
rightBtn->setToolTip(tr("forward"));
rightBtn->setDisabled(true);
rightBtn->hide();
searchEdit = new SearchEdit(this);
searchEdit->setWidget(m_parent);
searchEdit->setFixedSize(QSize(240, 32));
// searchEdit->setPlaceholderText(tr("Search"));
//搜索框暂时隐藏
LayoutLeft->addWidget(searchEdit, Qt::AlignHCenter);
LayoutRight = new QHBoxLayout;
userIconBtn = new QPushButton;
userIconBtn->setCursor(Qt::PointingHandCursor);
userIconBtn->setFixedSize(20,20);
userIconBtn->setStyleSheet("QPushButton{background:transparent;\
border-image:url(:/img/default/headportrait.png);}");
loginBtn = new QPushButton;
// loginBtn->setText("未登录");
loginBtn->setText(tr("Not logged in"));
loginBtn->setFlat(true);
loginBtn->adjustSize();
loginBtn->setCursor(Qt::PointingHandCursor);
loginBtn->setStyleSheet("QPushButton{background:transparent;\
color:rgb(238,238,238);\
border:none;}");
//for trigon list
QMenu *loginMenu = new QMenu;
loginBtn->setMenu(loginMenu);
setBtn = new QPushButton;
setBtn->setCursor(Qt::PointingHandCursor);
setBtn->setFixedSize(30,30);
setBtn->setIcon(QIcon::fromTheme("application-menu"));
settingMenu = new QMenu(this);
changeThemeColorMenu = new QMenu(this);
darkThemeAct = new QAction(this);
lightThemeAct = new QAction(this);
aboutAct = new QAction(this);
if(WidgetStyle::themeColor == 1)
{
settingMenu->setStyleSheet("QMenu{background-color:#303032;color:#F9F9F9;}"
"QMenu::item:selected{background-color:#48484C;}");
changeThemeColorMenu->setStyleSheet("QMenu{background-color:#303032;color:#F9F9F9;}"
"QMenu::item:selected{background-color:#48484C;}");
}
else if(WidgetStyle::themeColor == 0)
{
settingMenu->setStyleSheet("QMenu{background-color:#FFFFFF;color:#303133;}"
"QMenu::item:selected{background-color:#F7F7F7;}");
changeThemeColorMenu->setStyleSheet("QMenu{background-color:#FFFFFF;color:#303133;}"
"QMenu::item:selected{background-color:#F7F7F7;}");
}
// changeThemeColorMenu->setTitle("更换主题颜色");
// changeThemeColorMenu->setTitle(tr("Change the theme color"));
// darkThemeAct->setText("深色模式");
// darkThemeAct->setText(tr("Dark mode"));
// lightThemeAct->setText("浅色模式");
// lightThemeAct->setText(tr("Light color pattern"));
// aboutAct->setText("关于");
// aboutAct->setText(tr("about"));
// settingMenu->addMenu(changeThemeColorMenu);
// changeThemeColorMenu->addAction(lightThemeAct);
// changeThemeColorMenu->addAction(darkThemeAct);
// settingMenu->addAction(aboutAct);
setBtn->setMenu(settingMenu); //下拉三角图标
// connect(aboutAct,SIGNAL(triggered()),this,SLOT(showAboutWidget()));
nullLabel = new QLabel;
nullLabel->setPixmap(QPixmap(":/images/TitleBar/line.png"));
miniBtn = new QPushButton;
miniBtn->setCursor(Qt::PointingHandCursor);
miniBtn->setFixedSize(30,30);
// miniBtn->setToolTip("精简模式");
miniBtn->setToolTip(tr("mini model"));
miniBtn->setIcon(QIcon::fromTheme("ukui-mini-symbolic"));
miniBtn->setProperty("isWindowButton", 0x1);
miniBtn->setProperty("useIconHighlightEffect", 0x2);
miniBtn->setFlat(true);
minimumBtn = new QPushButton;
minimumBtn->setCursor(Qt::PointingHandCursor);
// minimumBtn->setToolTip(tr("最小化"));
minimumBtn->setToolTip(tr("To minimize the"));
minimumBtn->setFixedSize(30,30);
minimumBtn->setIcon(QIcon::fromTheme("window-minimize-symbolic"));
minimumBtn->setProperty("isWindowButton", 0x1);
minimumBtn->setProperty("useIconHighlightEffect", 0x2);
minimumBtn->setFlat(true);
maximumBtn = new QPushButton;
maximumBtn->setCursor(Qt::PointingHandCursor);
maximumBtn->setFixedSize(30,30);
// maximumBtn->setToolTip(tr("最大化"));
maximumBtn->setToolTip(tr("maximize"));
maximumBtn->setIcon(QIcon::fromTheme("window-maximize-symbolic"));
maximumBtn->setProperty("isWindowButton", 0x1);
maximumBtn->setProperty("useIconHighlightEffect", 0x2);
maximumBtn->setFlat(true);
closeBtn = new QPushButton;
closeBtn->setCursor(Qt::PointingHandCursor);
closeBtn->setFixedSize(30,30);
// closeBtn->setToolTip("关闭");
closeBtn->setToolTip(tr("close"));
closeBtn->setIcon(QIcon::fromTheme("window-close-symbolic"));
closeBtn->setProperty("isWindowButton", 0x2);
closeBtn->setProperty("useIconHighlightEffect", 0x8);
closeBtn->setFlat(true);
connect(searchEdit,&SearchEdit::textChanged,this,&TitleBar::searchMusic);
connect(searchEdit,&SearchEdit::sigFoucusIn,this,&TitleBar::slotFoucusIn);
LayoutRight->setSpacing(0);
// LayoutRight->addWidget(userIconBtn);
// LayoutRight->addWidget(loginBtn);
// LayoutRight->addSpacing(20);
LayoutRight->addWidget(menumodule->menuButton);
LayoutRight->addSpacing(4);
LayoutRight->addWidget(miniBtn);
LayoutRight->addSpacing(4);
LayoutRight->addWidget(minimumBtn);
LayoutRight->addSpacing(4);
LayoutRight->addWidget(maximumBtn);
LayoutRight->addSpacing(4);
LayoutRight->addWidget(closeBtn);
titleLayout->addStretch();
titleLayout->addLayout(LayoutLeft);
titleLayout->addStretch();
titleLayout->addLayout(LayoutRight);
// titleLayout->setSpacing(0);
titleLayout->setContentsMargins(0,4,4,0);
}
bool TitleBar::eventFilter(QObject *watched, QEvent *event)
{
if(watched == this)
{
if (event->type() == QEvent::MouseButtonDblClick) //判断类型
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
if (mouseEvent->button() == Qt::LeftButton) //判断左键
{
Widget::mutual->slotShowMaximized();
}
}
}
return QWidget::eventFilter(watched,event);
}
void TitleBar::searchMusic()
{
// m_serach = new SearchResult(this);
// MotifWmHints hint;
// hint.flags = MWM_HINTS_FUNCTIONS|MWM_HINTS_DECORATIONS;
// hint.functions = MWM_FUNC_ALL;
// hint.decorations = MWM_DECOR_BORDER;
// XAtomHelper::getInstance()->setWindowMotifHint(m_serach->winId(), hint);
// m_serach->show();
// m_serach->raise();
// QString enterStr = searchEdit->text().trimmed();
// qDebug() << "搜索" <<"输入栏" << enterStr;
// // searchEdit->clear();
// if(enterStr == "")
// {
// searchWidget->close();
// return;
// }
// searchWidget->show();
// searchWidget->raise();
// searchWidget->clear();
// QSqlQuery searchQuery;
// QString searchStr = QString("select * from LocalMusic where musicname LIKE '%%1%'").arg(enterStr);
// qDebug() << "搜索" <<"数据库" << searchStr;
// searchQuery.exec(searchStr);
// while(searchQuery.next())
// {
// QString songName = searchQuery.value(1).toString();
// QString Path = searchQuery.value(2).toString();
// QString Title = searchQuery.value(3).toString();
// QString Album = searchQuery.value(4).toString();
// QString Time = searchQuery.value(7).toString();
// qDebug() << "搜索" << songName << Path ;
// QListWidgetItem *item1 = new QListWidgetItem(searchWidget);
// item1->setText(songName+" "+Title+" "+Album);
// }
}
void TitleBar::slotFoucusIn()
{
searchEdit->setFocus();
}
void TitleBar::titlecolor()
{
if (WidgetStyle::themeColor == 1)
{
settingMenu->setStyleSheet("QMenu{background-color:#303032;color:#F9F9F9;}"
"QMenu::item:selected{background-color:#3D6BE5;}");
changeThemeColorMenu->setStyleSheet("QMenu{background-color:#303032;color:#F9F9F9;}"
"QMenu::item:selected{background-color:#3D6BE5;}");
this->setStyleSheet("#TitleBar{background-color:#252526;}");
menumodule->menuButton->setStyleSheet("QPushButton{background:transparent;border-radius:4px;\
}"
"QPushButton::hover{background:#D4DBE9;opacity:0.04;}"
"QPushButton::pressed{background:#BEBEBE;opacity:0.04;}"
"QPushButton::menu-indicator{image:None;}"
);
}
else if(WidgetStyle::themeColor == 0)
{
settingMenu->setStyleSheet("QMenu{background-color:#FFFFFF;color:#303133;}"
"QMenu::item:selected{background-color:#3D6BE5;color:#FFFFFF;}");
changeThemeColorMenu->setStyleSheet("QMenu{background-color:#FFFFFF;color:#303133;}"
"QMenu::item:selected{background-color:#3D6BE5;color:#FFFFFF;}");
this->setStyleSheet("#TitleBar{background-color:#FFFFFF;}");
menumodule->menuButton->setStyleSheet("QPushButton{background:transparent;border-radius:4px;\
}"
"QPushButton::hover{background:rgba(0,0,0,0.15);}"
"QPushButton::pressed{background:rgba(0, 0, 0, 0.2);}"
"QPushButton::menu-indicator{image:None;}"
);
}
}

117
UI/titlebar/titlebar.h Normal file
View File

@ -0,0 +1,117 @@
/*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* 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 <https://www.gnu.org/licenses/>.
*/
#ifndef TITLEBAR_H
#define TITLEBAR_H
#include <QFrame>
#include <QLabel>
#include <QPushButton>
#include <QLineEdit>
#include <QHBoxLayout>
#include <QSqlTableModel>
#include <QListWidget>
#include <QSqlQuery>
#include <QDebug>
#include <QListWidgetItem>
#include <QEvent>
//#include "changelistwid.h"
//#include "allpupwindow.h"
//#include "widgetstyle.h"
#include "menumodule.h"
#include "UI/player/searchedit.h"
const QString main_style = "QFrame{background:#FFFFFF;border-top-right-radius:12px;}";
#pragma pack(push)
#pragma pack(1)
class TitleBar : public QFrame
{
Q_OBJECT
public:
explicit TitleBar(QWidget *parent = nullptr);
~TitleBar(){}
menuModule *menumodule = nullptr;
QLabel *nullLabel = nullptr;
QPushButton *leftBtn = nullptr;
QPushButton *rightBtn = nullptr;
SearchEdit *searchEdit = nullptr;
QPushButton *userIconBtn = nullptr;
QPushButton *loginBtn = nullptr;
QPushButton *setBtn = nullptr;
QPushButton *miniBtn = nullptr;
QPushButton *minimumBtn = nullptr;
QPushButton *maximumBtn = nullptr;
QPushButton *recoverNormalSizeBtn = nullptr;
QPushButton *closeBtn = nullptr;
//搜索相关
QSqlTableModel *searchModel = nullptr;
QListWidget *searchWidget = nullptr;
// MusicListWid *searchResultWidget; /*搜索部分暂时注释掉*/
//设置菜单
QMenu *settingMenu = nullptr;
QMenu *changeThemeColorMenu = nullptr;
QAction *darkThemeAct = nullptr;
QAction *lightThemeAct = nullptr;
QAction *aboutAct = nullptr;
// AllPupWindow *aboutWidget;
void titlecolor();
public Q_SLOTS:
void searchMusic();
void slotFoucusIn();
// void showAboutWidget();
protected:
// virtual void mouseDoubleClickEvent(QMouseEvent *event);
bool eventFilter(QObject *watched, QEvent *event);
private Q_SLOTS:
//进行最小化、最大化、还原、关闭
// void slot_showMaximized();
// void slot_quit();
private:
void initTitle();
QHBoxLayout *titleLayout = nullptr;
QHBoxLayout *searchLayout = nullptr;
QHBoxLayout *LayoutLeft = nullptr;
QHBoxLayout *LayoutRight = nullptr;
QWidget *m_parent = nullptr;
};
#pragma pack(pop)
#endif // TITLEBAR_H

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* 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 <https://www.gnu.org/licenses/>.
*/
#include "daemonipcdbus.h"
int DaemonIpcDbus::daemonIsNotRunning()
{
char service_name[SERVICE_NAME_SIZE];
memset(service_name, 0, SERVICE_NAME_SIZE);
snprintf(service_name, SERVICE_NAME_SIZE, "%s_%d",KYLIN_USER_GUIDE_SERVICE,getuid());
QDBusConnection conn = QDBusConnection::sessionBus();
if (!conn.isConnected())
return -1;
QDBusReply<QString> reply = conn.interface()->call("GetNameOwner", service_name);
return reply.value() == "";
}
void DaemonIpcDbus::showGuide(QString appName)
{
qDebug() << Q_FUNC_INFO << appName;
bool bRet = false;
char service_name[SERVICE_NAME_SIZE];
memset(service_name, 0, SERVICE_NAME_SIZE);
snprintf(service_name, SERVICE_NAME_SIZE, "%s_%d",KYLIN_USER_GUIDE_SERVICE,getuid());
// 用来构造一个在D-Bus上传递的Message
QDBusMessage m = QDBusMessage::createMethodCall(QString(service_name),KYLIN_USER_GUIDE_PATH,KYLIN_USER_GUIDE_INTERFACE,"showGuide");
// 给QDBusMessage增加一个参数;
// 这是一种比较友好的写法也可以用setArguments来实现
m << appName;
// 发送Message
QDBusMessage response = QDBusConnection::sessionBus().call(m);
// 判断Method是否被正确返回
if (response.type()== QDBusMessage::ReplyMessage)
{
// QDBusMessage的arguments不仅可以用来存储发送的参数也用来存储返回值;
// bRet = response.arguments().at(0).toBool();
}
else {
qDebug()<<"showGuide In fail!\n";
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* 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 <https://www.gnu.org/licenses/>.
*/
#ifndef DAEMONIPCDBUS_H
#define DAEMONIPCDBUS_H
#define KYLIN_USER_GUIDE_PATH "/"
#define KYLIN_USER_GUIDE_SERVICE "com.kylinUserGuide.hotel"
#define KYLIN_USER_GUIDE_INTERFACE "com.guide.hotel"
#define SERVICE_NAME_SIZE 30
#include <QObject>
#include <QApplication>
#include <QCoreApplication>
#include <QDebug>
#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusConnectionInterface>
#include <QtDBus/QDBusMessage>
#include <QtDBus/QDBusReply>
#include <unistd.h>
#include <sys/types.h>
class DaemonIpcDbus : public QObject
{
Q_OBJECT
// 定义Interface名称为com.scorpio.test.value
// Q_CLASSINFO("D-Bus Interface", "com.scorpio.test.value")
public:
DaemonIpcDbus() {}
public Q_SLOTS:
int daemonIsNotRunning();
void showGuide(QString appName);
};
/*
// 使用方法
DaemonIpcDbus *mDaemonIpcDbus;
mDaemonIpcDbus = new DaemonIpcDbus();
if (!mDaemonIpcDbus->daemonIsNotRunning()){
//增加标题栏帮助菜单、F1快捷键打开用户手册
mDaemonIpcDbus->showGuide("kylin-ipmsg");
}
*/
#endif // DAEMONIPCDBUS_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,183 @@
#ifndef MUSICDATABASE_H
#define MUSICDATABASE_H
#include <QSqlDatabase>
#include <QSqlDriver>
#include <QObject>
#include <QFile>
#include <QList>
#include <QString>
#include <QThread>
#include <QMutexLocker>
#include <sqlite3.h>
const QString ALLMUSIC = "LocalMusic"; //本地总表
const QString HISTORY = "HistoryPlayList"; //历史记录
const QString FAV = "我喜欢"; //我喜欢
const QString SEARCH = "SearchResult"; //搜索
const QString SHOWCONTEXTS =
"filepath,title,singer,album,filetype,size,time"; //播放列表显示项
enum DB_RETURN_STATUS{ //数据库操作结果返回表
DB_OP_SUCC = (0), //数据库操作成功
DB_UNCONNECT = (-1), //数据库连接失败导致的错误
INVALID_INPUT = (-2), //无效的输入值
DB_DISORDERD = (-3), //数据库与外界顺序不符导致的失败
DB_EMPTY_TABLE = (-4), //数据库中的表格内容为空
DB_OP_ADD_FAILED = (-5), //数据库添加操作失败
DB_OP_DEL_FAILED = (-6), //数据库删除操作失败
DB_OP_GET_FAILED = (-7), //数据库查询操作失败
DB_OP_ADD_REPEAT = (-8), //数据库添加失败,重复添加
DB_INSIDE_FAILED = (-9), //数据库内部错误
PLAYLIST_UNFOUND = (-10), //数据库中播放列表未找到
PLAYLIST_IS_EMPTY = (-11), //数据库中该播放列表为空
CREATE_TABLE_FAILED = (-12), //数据库创表失败
DEL_TABLE_FAILED = (-13), //数据库删表失败
SONG_NOT_FOUND = (-14), //数据库中未找到该歌曲
LIST_NOT_FOUND = (-15), //数据库中未找到该歌单
LIST_EXISTS = (-16), //数据库中已存在该名字歌单
LIST_RENAME_FAILED = (-17), //重命名歌单失败,正常退出
LIST_RENAME_ERR = (-18), //重命名歌单失败,创建了新名称歌单,但新建歌单的列表中名称未能重命名
LIST_REORDER_ERR = (-19), //歌单中歌曲更改顺序失败
LIST_NOT_EMPTY = (-20), //歌单不为空
LIST_IS_EMPTY = (-21), //歌单为空
EMPTYT_HIS_FAILED = (-22), //清空历史列表失败
CREATE_HIS_FAILED = (-23), //创建历史列表失败
OUT_OF_RESULT , //结果边界
};
typedef struct
{
QString title;
QString filepath;
QString singer;
QString album;
QString filetype;
QString size;
QString time;
}musicDataStruct;
//QVariant保存结构体
Q_DECLARE_METATYPE(musicDataStruct)
#define g_db (MusicDataBase::getInstance())
class MusicDataBase : public QObject
{
Q_OBJECT
public:
~MusicDataBase();
//单例,初始化返回指针,完成数据库文件建立
static MusicDataBase* getInstance();
//open数据库建立本地历史我喜欢及三个列表
int initDataBase();
//根据新建的播放列表名的title值创建新建歌单
int createNewPlayList(const QString& playListName);
//根据播放列表名的title值删除对应歌单
int delPlayList(const QString& playListName);
//查询当前已有歌单列表
int getPlayList(QStringList& playListNameList);
//重命名歌单名title
int renamePlayList(const QString& oldPlayListName, const QString& newPlayListName);
//从所有歌单中删除一首歌
int delSongFromEveryWhere(const QString& filePath);
//删除多首歌曲
int delMultiSongs(const QString &playListName, const QStringList &songsList);
//检查歌单是否为空
int checkIfPlayListIsEmpty(const QString& playListName);
/**************************新建歌曲增删改查****************************/
//添加歌曲到新建歌单使用歌曲filePath,歌单名title值输入数据必须有效
int addMusicToPlayList(const QString& filePath,const QString& playListName);
//从歌单中添加歌曲到新建歌单如果本地歌单中没有同样插入本地歌单使用musicDataStruct结构,输入数据必须有效,
int addNewSongToPlayList(const musicDataStruct& fileData,const QString& playListName);
//从新建歌单中删除歌曲使用歌曲filePath,歌单名title值输入数据必须有效
int delMusicFromPlayList(const QString& filePath,const QString& playListName);
//根据歌曲filePath在指定歌单中查询歌曲信息
int getSongInfoFromPlayList(musicDataStruct &fileData, const QString& filePath,const QString& playListName);
//根据歌单名title值查询对应歌单列表
int getSongInfoListFromPlayList(QList<musicDataStruct>& resList,const QString& playListName);
//更换新建歌单中某首歌曲的位置(从选中的位置更换到目的歌曲的位置的后面)
int changeSongOrderInPlayList(const QString& selectFilePath, const QString& destinationFilePath, const QString& playListName);
/**************************本地歌曲增删改查****************************/
//添加歌曲到本地歌单使用musicDataStruct结构,输入数据必须有效,
int addMusicToLocalMusic(const musicDataStruct& fileData);
//从本地歌单中删除歌曲使用key:filePath,输入数据必须有效,同时从其他列表中也删除
int delMusicFromLocalMusic(const QString& filePath);
//从本地歌单中获取指定歌曲信息使用key:filePath,输入数据必须有效,
int getSongInfoFromLocalMusic(const QString& filePath, musicDataStruct &fileData);
//从数据库中获取本地歌单列表歌曲信息
int getSongInfoListFromLocalMusic(QList<musicDataStruct>& resList);
//更换本地歌单中某首歌曲的位置(从选中的位置更换到目的歌曲的位置的后面)
int changeSongOrderInLocalMusic(const QString& selectFilePath, const QString& destinationFilePath);
/******************************搜索************************************/
//通过输入关键字从本地歌单中模糊检索列表歌曲信息,输入数据必须有效
int getSongInfoListFromLocalMusicByKeyword(QList<musicDataStruct>& resList, const QString& keyword);
//通过输入关键字Number用于限制展示条数从本地给出临时提示歌曲列表信息输入数据必须有效
int getCurtEstimatedListByKeyword(const QString& keyword, int Number, QList<musicDataStruct>& titleSongsList, QList<musicDataStruct>& singersList, QList<musicDataStruct>& albumsList);
//通过标准专辑名key:album获取该专辑歌曲信息
int getSongInfoListByAlbum(QList<musicDataStruct>& resList, const QString& album);
//通过标准歌手名key:singer获取歌曲信息
int getSongInfoListBySinger(QList<musicDataStruct>& resList, const QString& singer);
/**************************历史歌单增删改查****************************/
//添加歌曲到历史歌单使用歌曲的path值,输入数据必须有效,
int addMusicToHistoryMusic(const QString& filePath);
//从历史歌单中删除歌曲使用歌曲的path值,输入数据必须有效,
int delMusicFromHistoryMusic(const QString& filePath);
//从历史歌单中查询指定歌曲信息使用歌曲的path值,输入数据必须有效,
int getSongInfoFromHistoryMusic(const QString& filePath, musicDataStruct &fileData);
//从数据库中获取历史歌单列表歌曲信息
int getSongInfoListFromHistoryMusic(QList<musicDataStruct>& resList);
//清空历史歌单
int emptyHistoryMusic();
/**************************二层封装接口****************************/
//使用歌曲的path值查询歌曲信息(因为所有歌曲都在本地歌单,所以只用歌曲路径即可)
int getSongInfoFromDB(const QString& filePath, musicDataStruct &fileData);
//根据歌单名title值查询对应歌单列表
int getSongInfoListFromDB(QList<musicDataStruct>& resList,const QString& playListName);
//检查歌曲是是我喜欢的歌曲
bool checkSongIsInFav(const QString& filePath);
//检查歌单列表是否存在
int checkPlayListExist(const QString& playListName);
//检查歌曲是否在歌单列表中存在
int checkIfSongExistsInPlayList(const QString& filePath, const QString& playListName);
protected:
explicit MusicDataBase(QObject *parent = nullptr);
Q_SIGNALS:
private:
//日志处理函数
void msgHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg);
QSqlDatabase m_database;//数据库
QMutex m_mutex;
bool m_databaseOpenFlag = false;
QStringList listSimpleSpell; // 简拼列表
QStringList listSpell; // 拼音列表
//检查歌曲是否在总表中存在
int checkIfSongExistsInLocalMusic(const QString& filePath);
//检查歌曲是否在历史歌单中存在
int checkIfSongExistsInHistoryMusic(const QString& filePath);
//检查歌曲是否在我喜欢中存在
int checkIfSongExistsInFavorMusic(const QString& filePath);
// //检查歌单列表是否存在
// int checkPlayListExist(const QString& playListName);
// //检查歌曲是否在歌单列表中存在
// int checkIfSongExistsInPlayList(const QString& filePath, const QString& playListName);
//获取歌曲在歌曲总表中的index
int getSongIndexFromLocalMusic(const QString& filePath, int &songIndex);
//获取歌曲在歌曲某歌单表中的index
int getSongIndexFromPlayList(const QString& filePath,const QString& playListName, int &songIndex);
/**************************字符串转码接口*******************************/
QString inPutStringHandle(const QString& input);
QString outPutStringHandle(const QString& output);
// 对包含'的字符串做预处理避免获取SQL语句时语法出错
QString preHandle(const QString& input);
};
#endif // MUSICDATABASE_H

View File

@ -0,0 +1,529 @@
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
}
#include <QTimer>
#include <QAbstractButton>
#include <QDirIterator>
#include "musicfileinformation.h"
#include "UI/mainwidget.h"
#include "ukui-log4qt.h"
MusicFileInformation::MusicFileInformation(QObject *parent) : QObject(parent)
{
m_musicType << "*.voc" << "*.aiff" << "*.au" << "*.dts" << "*.flv" << "*.m4r"
<< "*.mka" << "*.mmf" << "*.mp2" << "*.mp4" << "*.mpa" << "*.wv"
<< "*.mp3" << "*.ogg" << "*.wma" << "*.amr" << "*.flac"
<< "*.wav" << "*.ape" << "*.m4a" << "*.ac3" << "*.aac";
}
QStringList MusicFileInformation::getMusicType()
{
return m_musicType;
}
void MusicFileInformation::addFile(const QStringList &addFile)
{
qDebug() << "addFile";
int count = 0;
int failCount = 0;
resList.clear();
for(auto &filepath : addFile)
{
if(filepath.isEmpty())
{
continue;
}
//过滤掉CD和远程目录
// if(filepath.startsWith("/run/user/"))
// {
// continue;
// }
//过滤U盘路径
// if(filepath.startsWith("/media/"))
// {
// continue;
// }
QFileInfo fileInfo(filepath);
if(fileInfo.isDir())
{
//适合用于大目录
QDirIterator iter(filepath,m_musicType,QDir::Files,QDirIterator::Subdirectories);
while (iter.hasNext())
{
count++;
QString strpath = iter.next();
musicdataStruct.filepath = strpath;
fileInfo.setFile(musicdataStruct.filepath);
fileType(fileInfo); //文件类型
fileSize(fileInfo); //文件大小
if(m_musicType.contains("*." + musicdataStruct.filetype))
{
fileInformation(musicdataStruct.filepath);//获取歌曲文件信息
if(musicdataStruct.time != "")
{
resList.append(musicdataStruct);
} else {
failCount++;
}
}
else
{
failCount++;
}
}
}
else if(fileInfo.isFile())
{
count++;
musicdataStruct.filepath = filepath;
fileInfo.setFile(musicdataStruct.filepath);
fileType(fileInfo); //文件类型
fileSize(fileInfo); //文件大小
if(m_musicType.contains("*." + musicdataStruct.filetype))
{
fileInformation(musicdataStruct.filepath);//获取歌曲文件信息
if(musicdataStruct.time != "")
{
resList.append(musicdataStruct);
} else {
failCount++;
}
}
else
{
failCount++;
}
}
}
musicCount = count;
m_failCount = failCount;
// resList.clear();
// if(!addFile.isEmpty())
// {
// for(int i = 0; i < addFile.size(); i++)
// {
// musicdataStruct.filepath = addFile.at(i);
// fileInfo.setFile(musicdataStruct.filepath);
// fileType(fileInfo); //文件类型
// fileSize(fileInfo); //文件大小
// if(musicType.indexOf(musicdataStruct.filetype) != -1)
// {
// QStringList list = fileInformation(musicdataStruct.filepath);//获取歌曲文件信息
// if(musicdataStruct.time == "")
// {
// m_failCount++;
// }
// else
// {
// m_successCount++;
// }
// resList.append(musicdataStruct);
// }
// else
// {
// qDebug() << "添加文件失败";
// }
// }
// }
// slotImportFinished(m_successCount, m_failCount);
}
int MusicFileInformation::getCount()
{
return musicCount;
}
int MusicFileInformation::getFailCount()
{
return m_failCount;
}
QString MusicFileInformation::filterTextCode(QString str)
{
QByteArray strdata =str.toLocal8Bit();
int len = strdata.length();
int num = 0;
int i = 0;
while (i < len) {
if ((strdata[i] & 0x80) == 0x00) {
// 0XXX_XXXX
i++;
continue;
}
else if ((num = preNum(strdata[i])) > 2) {
// 110X_XXXX 10XX_XXXX
// 1110_XXXX 10XX_XXXX 10XX_XXXX
// 1111_0XXX 10XX_XXXX 10XX_XXXX 10XX_XXXX
// 1111_10XX 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX
// 1111_110X 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX
// preNUm() 返回首个字节8个bits中首<E4B8AD>?0bit前面1bit的个数该数量也是该字符所使用的字节数
i++;
for(int j = 0; j < num - 1; j++) {
//判断后面num - 1 个字节是不是都是10开
if ((strdata[i] & 0xc0) != 0x80) {
return "";
}
i++;
}
} else {
//其他情况说明不是utf-8
return "";
}
}
return str;
}
inline int MusicFileInformation::preNum(unsigned char byte) {
unsigned char mask = 0x80;
int num = 0;
for (int i = 0; i < 8; i++) {
if ((byte & mask) == mask) {
mask = mask >> 1;
num++;
} else {
break;
}
}
return num;
}
QStringList MusicFileInformation::fileInformation(QString filepath)
{
QFileInfo fileInfo(filepath);
QStringList information;
QByteArray byteArray = filepath.toLocal8Bit();
TagLib::FileRef f(byteArray.data());
if(f.isNull())
{
musicdataStruct.time = "";
AVFormatContext *pFormatCtx = NULL;
avformat_open_input(&pFormatCtx, filepath.toStdString().c_str(), nullptr, nullptr);
if(pFormatCtx)
{
avformat_find_stream_info(pFormatCtx, nullptr);
qint64 duration = pFormatCtx->duration / 1000;
if(duration > 0)
{
duration = duration / 1000;
// QTime me(0,(duration/60000) % 60,(duration / 1000) % 60);
// QString length = me.toString("mm:ss");
int h = duration / 3600;
QString hour = QString("%1").arg(duration / 3600, 2, 10, QChar('0'));
QString minutes = QString("%1").arg(duration % 3600 / 60, 2, 10, QChar('0'));
QString seconds = QString("%1").arg(duration % 60, 2, 10, QChar('0'));
if(h > 0) {
musicdataStruct.time = QString("%1:%2:%3").arg(hour).arg(minutes).arg(seconds);
}
else {
musicdataStruct.time = QString("%1:%2").arg(minutes).arg(seconds);
}
musicdataStruct.title = fileInfo.completeBaseName();
musicdataStruct.singer = tr("Unknown singer");
musicdataStruct.album = tr("Unknown album");
information << musicdataStruct.title << musicdataStruct.singer << musicdataStruct.album << musicdataStruct.time;
return information;
}
}
else
{
QStringList str;
musicdataStruct.singer = "";
musicdataStruct.album = "";
musicdataStruct.title = "";
musicdataStruct.time = "";
str << musicdataStruct.title << musicdataStruct.singer << musicdataStruct.album << musicdataStruct.time;
return str;
}
avformat_close_input(&pFormatCtx);
avformat_free_context(pFormatCtx);
}
if (f.file() == nullptr) {
KyInfo() << "f.file == nullptr";
QStringList str;
musicdataStruct.singer = "";
musicdataStruct.album = "";
musicdataStruct.title = "";
musicdataStruct.time = "";
str << musicdataStruct.title << musicdataStruct.singer << musicdataStruct.album << musicdataStruct.time;
return str;
}
TagLib::PropertyMap propertyMap = f.file() ->properties();
QString musicName = propertyMap["TITLE"].toString().toCString(true);
if(filterTextCode(musicName).isEmpty())
musicName = fileInfo.completeBaseName();
QString musicSinger = propertyMap["ARTIST"].toString().toCString(true);
if(filterTextCode(musicSinger).isEmpty())
musicSinger = tr("Unknown singer");
QString musicAlbum = propertyMap["ALBUM"].toString().toCString(true);
if(filterTextCode(musicAlbum).isEmpty())
musicAlbum = tr("Unknown album");
TagLib::AudioProperties *properties = f.audioProperties();
if(properties == nullptr)
{
QStringList str;
musicdataStruct.singer = "";
musicdataStruct.album = "";
musicdataStruct.title = "";
musicdataStruct.time = "";
str << musicdataStruct.title << musicdataStruct.singer << musicdataStruct.album << musicdataStruct.time;
return str;
}
int h = properties->length() / 3600;
if( h <= 0)
{
musicdataStruct.time = "";
AVFormatContext *pFormatCtx = NULL;
avformat_open_input(&pFormatCtx, filepath.toStdString().c_str(), nullptr, nullptr);
if(pFormatCtx)
{
avformat_find_stream_info(pFormatCtx, nullptr);
qint64 duration = pFormatCtx->duration / 1000;
if(duration > 0)
{
duration = duration / 1000;
int h = duration / 3600;
QString hour = QString("%1").arg(duration / 3600, 2, 10, QChar('0'));
QString minutes = QString("%1").arg(duration % 3600 / 60, 2, 10, QChar('0'));
QString seconds = QString("%1").arg(duration % 60, 2, 10, QChar('0'));
if(h > 0) {
musicdataStruct.time = QString("%1:%2:%3").arg(hour).arg(minutes).arg(seconds);
}
else {
musicdataStruct.time = QString("%1:%2").arg(minutes).arg(seconds);
}
musicdataStruct.title = musicName;
musicdataStruct.singer = musicSinger;
musicdataStruct.album = musicAlbum;
information << musicdataStruct.title << musicdataStruct.singer << musicdataStruct.album << musicdataStruct.time;
return information;
}
}
else
{
QStringList str;
musicdataStruct.singer = "";
musicdataStruct.album = "";
musicdataStruct.title = "";
musicdataStruct.time = "";
str << musicdataStruct.title << musicdataStruct.singer << musicdataStruct.album << musicdataStruct.time;
return str;
}
avformat_close_input(&pFormatCtx);
avformat_free_context(pFormatCtx);
}
QString hour = QString("%1").arg(properties->length() / 3600, 2, 10, QChar('0'));
QString minutes = QString("%1").arg(properties->length() % 3600 / 60, 2, 10, QChar('0'));
QString seconds = QString("%1").arg(properties->length() % 60, 2, 10, QChar('0'));
if(h > 0) {
musicdataStruct.time = QString("%1:%2:%3").arg(hour).arg(minutes).arg(seconds);
}
else {
musicdataStruct.time = QString("%1:%2").arg(minutes).arg(seconds);
}
// int seconds = properties->length() % 60;
// int minutes = (properties->length() - seconds) / 60;
// QTime time(0,minutes,seconds);
//// QString musicTime = QString::number(minutes)+":"+QString("%1").arg(seconds, 2, 10, QChar('0'));
// QString musicTime = time.toString("mm:ss");
musicdataStruct.title = musicName;
musicdataStruct.singer = musicSinger;
musicdataStruct.album = musicAlbum;
QStringList audioFileInformation;
audioFileInformation << musicdataStruct.title << musicdataStruct.singer
<< musicdataStruct.album << musicdataStruct.time;
return audioFileInformation;
}
QPixmap MusicFileInformation::getCoverPhotoPixmap(QString filepath)
{
AVFormatContext *pFormatCtx = NULL;
avformat_open_input(&pFormatCtx, filepath.toUtf8().data(), nullptr, nullptr);
QPixmap pixmap;
QImage image;
if(pFormatCtx)
{
if(pFormatCtx->iformat != nullptr && pFormatCtx->iformat->read_header(pFormatCtx) >= 0)
{
for(unsigned int i = 0; i < pFormatCtx->nb_streams; i++)
{
if(pFormatCtx->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC)
{
AVPacket pkt = pFormatCtx->streams[i]->attached_pic;
image = QImage::fromData(static_cast<uchar *>(pkt.data), pkt.size);
break;
}
}
}
}
avformat_close_input(&pFormatCtx);
avformat_free_context(pFormatCtx);
pixmap = QPixmap::fromImage(image);
return pixmap;
}
QStringList MusicFileInformation::updateSongInfoFromLocal(QString filepath)
{
QFileInfo fileInfo(filepath);
QStringList lists;
int importFailCount = 0;
musicdataStruct.time = "";
AVFormatContext *pFormatCtx = NULL;
avformat_open_input(&pFormatCtx, filepath.toStdString().c_str(), nullptr, nullptr);
if(pFormatCtx)
{
avformat_find_stream_info(pFormatCtx, nullptr);
qint64 duration = pFormatCtx->duration / 1000;
if(duration > 0)
{
QTime me(0,(duration/60000) % 60,(duration / 1000) % 60);
QString length = me.toString("mm:ss");
musicdataStruct.time = length;
}
}
avformat_close_input(&pFormatCtx);
avformat_free_context(pFormatCtx);
if(musicdataStruct.time == "")
{
importFailCount++;
QEventLoop loop;
MMediaContent media(QUrl::fromLocalFile(filepath));
MMediaPlayer *music = new MMediaPlayer();
music->setMedia(media);
connect(music,SIGNAL(durationChanged(qint64)),this,SLOT(durationChange(qint64)));
connect(this,SIGNAL(durations()),&loop,SLOT(quit()));
QTimer::singleShot(1000,&loop,&QEventLoop::quit);
loop.exec();
if(success)
{
QStringList list;
QString name = fileInfo.completeBaseName();
QString singer = "未知歌手";
QString album = "未知专辑";
musicdataStruct.singer = singer;
musicdataStruct.album = album;
musicdataStruct.title = name;
QTime me(0,(dur/60000) % 60,(dur / 1000) % 60);
QString m_str = me.toString("mm:ss");
musicdataStruct.time = m_str;
list << musicdataStruct.title << musicdataStruct.singer << musicdataStruct.album << musicdataStruct.time;
return list;
}
else
{
QMessageBox::warning(Widget::mutual,tr("Prompt information"),tr("Add failed, no valid music file found"),QMessageBox::Ok);
QStringList str;
musicdataStruct.singer = "";
musicdataStruct.album = "";
musicdataStruct.title = "";
musicdataStruct.time = "";
str << musicdataStruct.title << musicdataStruct.singer << musicdataStruct.album << musicdataStruct.time;
return str;
}
music->deleteLater();
}
if(importFailCount <= 0)
{
QString name = fileInfo.completeBaseName();
QString singer = "未知歌手";
QString album = "未知专辑";
musicdataStruct.singer = singer;
musicdataStruct.album = album;
musicdataStruct.title = name;
lists << musicdataStruct.title << musicdataStruct.singer << musicdataStruct.album << musicdataStruct.time;
return lists;
}
}
QString MusicFileInformation::fileSize(QFileInfo fileInfo)
{
QString musicSize;
qint64 size = fileInfo.size(); //文件大小
if(size/1024)
{
if(size/1024/1024)
{
if(size/1024/1024/1024)
{
musicSize = QString::number(size/1024/1024/1024,10)+"GB";
}
else
musicSize = QString::number(size/1024/1024,10)+"MB";
}
else
musicSize = QString::number(size/1024,10)+"KB";
}
else
musicSize = QString::number(size,10)+"B";
musicdataStruct.size = musicSize;
return musicdataStruct.size;
}
bool MusicFileInformation::checkFileIsDamaged(QString filepath)
{
QProcess *ffmpegCheckProcess = new QProcess(this);
QString cmd = "/usr/bin/ffmpeg";
QStringList args;
args.append("-i");
args.append(filepath);
ffmpegCheckProcess->start(cmd, args);
ffmpegCheckProcess->waitForFinished();
ffmpegCheckProcess->waitForReadyRead();
QString results = QString::fromLocal8Bit(ffmpegCheckProcess->readAllStandardOutput());
KyInfo() << "ffmpeg info: "<< results;
return true;
}
QString MusicFileInformation::fileType(QFileInfo fileInfo)
{
QString musicType = fileInfo.suffix().toLower(); //文件类型
musicdataStruct.filetype = musicType;
return musicdataStruct.filetype;
}
void MusicFileInformation::durationChange(qint64 duration)
{
if(duration <= 0)
{
return;
}
dur = duration;
success = true;
Q_EMIT durations();
}
int MusicFileInformation::findIndexFromPlayList(QString listname,QString filepath)
{
int index = -1;
int ret;
QList<musicDataStruct> musicDateList;
ret = g_db->getSongInfoListFromDB(musicDateList,listname);
if(ret == DB_OP_SUCC) {
for(int i = 0; i < musicDateList.size(); i++) {
if(musicDateList[i].filepath == filepath) {
index = i;
break;
}
}
}
return index;
}

View File

@ -0,0 +1,84 @@
#ifndef MUSICFILEINFORMATION_H
#define MUSICFILEINFORMATION_H
#include <QDir>
#include <QFileInfo>
#include <QByteArray>
#include <QString>
#include <QSqlTableModel>
#include <QMessageBox>
#include <QDebug>
#include <QTime>
#include <QEventLoop>
#include <QProcess>
//taglib
#include <taglib/fileref.h>
#include <taglib/tpropertymap.h>
#include <taglib/tag.h>
#include <taglib/taglib.h>
//#include <taglib/tpropertymap.h>
////#include <taglib/toolkit/tpropertymap.h>
#include "musicDataBase.h"
enum SearchType {
None = 0,
TitleType,
SingerType,
AlbumType
};
class MusicFileInformation : public QObject
{
Q_OBJECT
public:
explicit MusicFileInformation(QObject *parent = nullptr);
static MusicFileInformation& getInstance()
{
static MusicFileInformation instance;
return instance;
}
QStringList getMusicType();
QList<musicDataStruct> resList;
void addFile(const QStringList &addFile);
int findIndexFromPlayList(QString listname, QString filepath);
int getCount();
int getFailCount();
QStringList m_musicType;
//获取封面图片
QPixmap getCoverPhotoPixmap(QString filepath);
public Q_SLOTS:
void durationChange(qint64 duration);
Q_SIGNALS:
void durations();
private:
QStringList updateSongInfoFromLocal(QString filepath);
private:
// QList<musicDataStruct> resList;
musicDataStruct musicdataStruct;
QStringList AllDirList;
QStringList songFiles;
QString Dir;
QStringList matchMp3Files;
// QFileInfo fileInfo;
QString MD5Str;
QStringList MD5List;
QDir matchDir;
QString fileType(QFileInfo fileInfo);
QString fileSize(QFileInfo fileInfo);
bool checkFileIsDamaged(QString filepath);
QStringList fileInformation(QString filepath);
QString filterTextCode(QString str);
int preNum(unsigned char byte);
qint64 dur;
bool success = false;
int musicCount;
int m_failCount;
};
#endif // MUSICFILEINFORMATION_H

View File

@ -0,0 +1,336 @@
#include "mmediaplayer.h"
#include <QDBusMessage>
#include <QDBusConnection>
#include <ukui-log4qt.h>
MMediaPlayer::MMediaPlayer(QObject *parent)
: QObject(parent)
{
createMvpplayer();
}
void MMediaPlayer::setPlaylist(MMediaPlaylist *playlist)
{
//异常情况:空指针
if (playlist == nullptr) {
return;
}
m_playList = playlist;
connect(this,&MMediaPlayer::playFinish,m_playList,&MMediaPlaylist::palyFinish,Qt::UniqueConnection);
connect(this,&MMediaPlayer::playError,m_playList,&MMediaPlaylist::playError,Qt::UniqueConnection);
connect(m_playList,&MMediaPlaylist::autoPlay,this,&MMediaPlayer::autoPlay,Qt::UniqueConnection);
connect(m_playList,&MMediaPlaylist::stop,this,&MMediaPlayer::stop,Qt::UniqueConnection);
connect(this,&MMediaPlayer::playErrorMsg,m_playList,&MMediaPlaylist::playErrorMsg,Qt::UniqueConnection);
}
void MMediaPlayer::truePlay(QString startTime)
{
//异常情况:入参不合法
if (startTime.isEmpty()) {
return;
}
//异常情况:播放列表空指针
if (m_playList == nullptr) {
return;
}
QString filePath = m_playList->getPlayFileName();
//异常情况:本地文件不存在
if (!QFileInfo::exists(QUrl(filePath).toLocalFile())) {
Q_EMIT playErrorMsg(NotFound);
Q_EMIT playError();
return;
}
const QByteArray c_filename = filePath.toUtf8();
//如果文件名和上次一样,且不是因为拖动进度条播放,说明上次是暂停
if (c_filename == filenameBack && m_positionChangeed == false) {
if (filenameBack != "") {
//切换播放状态为播放
pause();
}
return;
}
//重置参数
m_position = 0;
m_positionChangeed = false;
setProperty("start",startTime);
const char *args[] = {"loadfile",c_filename, NULL};
mpv_command_async(m_mpvPlayer, 0, args);
//如果不播放任何媒体,则切换状态为停止
if (c_filename == "") {
changeState(StoppedState);
return;
}
//记录到上次播放变量中
filenameBack = c_filename;
//切换播放状态为正在播放
changeState(PlayingState);
}
void MMediaPlayer::play()
{
//从开头开始播放
truePlay("0");
}
void MMediaPlayer::pause()
{
// 获得mpv播放器的"暂停"状态
QString pasued = getProperty("pause");
KyInfo() << "pauseState = " << pasued;
// 根据"暂停"状态来选择暂停还是播放
if(pasued == "no") {
KyInfo() << "set pause yes";
setProperty("pause", "yes");
changeState(PausedState);
} else if(pasued == "yes") {
KyInfo() << "set pause no";
setProperty("pause", "no");
changeState(PlayingState);
}
}
void MMediaPlayer::pauseOnly()
{
// 获得mpv播放器的"暂停"状态
QString pasued = getProperty("pause");
KyInfo() << "pauseStated = " << pasued;
// 根据"暂停"状态来选择暂停还是播放
if(pasued == "no") {
KyInfo() << "begin pause.";
setProperty("pause", "yes");
changeState(PausedState);
}
}
void MMediaPlayer::stop()
{
filenameBack = "";
setProperty("pause", "no");
const char *args[] = {"loadfile", "", NULL};
mpv_command_async(m_mpvPlayer, 0, args);
changeState(StoppedState);
}
MMediaPlayer::State MMediaPlayer::state() const
{
return m_state;
}
qint64 MMediaPlayer::position() const
{
return m_position;
}
void MMediaPlayer::setPosition(qint64 pos)
{
double sec = double(pos)/1000;
m_positionChangeed = true;
//记录拖动进度条之前播放状态是否为暂停
bool restartPlay = false;
if (m_state == PausedState) {
restartPlay = true;
}
//从拖动完成的位置开始播放
truePlay(QString::number(sec));
if (restartPlay) {
//切换播放状态为播放
pause();
}
}
void MMediaPlayer::setVolume(int vol)
{
// setProperty("volume",QString::number(vol));
// Q_EMIT signalVolume(vol);
// 设置音量此音量和系统同步不单独设置mpv音量
// delayMsecond(100);
QDBusMessage message = QDBusMessage::createSignal("/", "org.kylin.music", "sinkInputVolumeChanged");
message << "kylin-music" << vol << false;
KyInfo() << "createSignal: volume = " << vol;
QDBusConnection::sessionBus().send(message);
}
qint64 MMediaPlayer::duration() const
{
return m_duration;
}
void MMediaPlayer::setMedia(const MMediaContent &media)
{
QUrl url =media.canonicalUrl();
//防止内存泄漏
if (m_tmpPlayList != nullptr) {
m_tmpPlayList->deleteLater();
}
//创建新的播放列表并将歌曲录入
m_tmpPlayList = new MMediaPlaylist(this);
m_tmpPlayList->addMedia(url);
setPlaylist(m_tmpPlayList);
//以暂停状态从头开始播放
setProperty("pause", "yes");
play();
}
bool MMediaPlayer::isAvailable() const
{
return true;
}
void MMediaPlayer::delayMsecond(unsigned int msec)
{
QEventLoop loop;//定义一个新的事件循环
QTimer::singleShot(msec, &loop, SLOT(quit()));//创建单次定时器,槽函数为事件循环的退出函数
loop.exec();//事件循环开始执行,程序会卡在这里,直到定时时间到,本循环被退出
}
void MMediaPlayer::onMpvEvents()
{
//处理所有事件,直到事件队列为空
while (m_mpvPlayer)
{
mpv_event *event = mpv_wait_event(m_mpvPlayer, 0);
if (event->event_id == MPV_EVENT_NONE) {
break;
}
handle_mpv_event(event);
}
}
void MMediaPlayer::handle_mpv_event(mpv_event *event)
{
switch (event->event_id) {
case MPV_EVENT_PROPERTY_CHANGE: { //属性改变事件
mpv_event_property *prop = (mpv_event_property *)event->data;
//播放时,时间改变事件
if (strcmp(prop->name, "time-pos") == 0) {
if (prop->format == MPV_FORMAT_DOUBLE) {
//将播放状态设置为播放中
if (m_state == StoppedState) {
changeState(PlayingState);
}
// 获得播放时间
double time = *(double *)prop->data;
//将单位换算为毫秒
m_position = time * 1000;
Q_EMIT positionChanged(m_position);
} else if (prop->format == MPV_FORMAT_NONE) {
//当前时长距离总时长不超过500毫秒判断播放结束
if ( m_duration!=0 && (m_duration - m_position < 500)) {
m_duration = 0;
m_position = 0;
//播放结束
Q_EMIT playFinish();
} else {
//切歌
changeState(StoppedState);
}
}
}
}
break;
case MPV_EVENT_PLAYBACK_RESTART:{ //初始化完成事件
//获取总时长
m_duration = getProperty("duration").toDouble() *1000;//单位换算为毫秒
Q_EMIT durationChanged(m_duration);
}
break;
case MPV_EVENT_IDLE:{ //播放器空闲事件,只有刚启动时、播放完成时、歌曲异常时会进入此分支
QString playlist = getProperty("playlist");
if (!playlist.contains(',')) { //排除播放完成
if (playlist.length() > 2) { //排除刚启动
//歌曲播放异常
Q_EMIT playErrorMsg(Damage);
}
}
}
break;
//MPV会概率错误的发送此信号导致没播放完也跳转到下一首
// case MPV_EVENT_END_FILE:{ //播放结束事件
// if (m_position != 0) {
// //重置参数
// m_duration = 0;
// m_position = 0;
// //播放结束
// Q_EMIT playFinish();
// }
// }
// break;
default: ;
}
}
// 回调函数
static void wakeup(void *ctx)
{
// 此回调可从任何mpv线程调用但也可以从调用mpv API的线程递归地返回
// 只是需要通知要唤醒的Qt GUI线程以便它可以使用mpv_wait_event并尽快返回
MMediaPlayer *mvpPlayer = (MMediaPlayer *)ctx;
Q_EMIT mvpPlayer->mpvEvents();
}
void MMediaPlayer::createMvpplayer()
{
// 创建mpv实例
setlocale(LC_NUMERIC,"C");
m_mpvPlayer = mpv_create();
if (m_mpvPlayer == nullptr) {
qDebug()<<"创建播放模块失败!";
this->deleteLater();
return;
}
//禁用视频流
setProperty("vid", "no");
//接收事件
connect(this, &MMediaPlayer::mpvEvents, this, &MMediaPlayer::onMpvEvents, Qt::QueuedConnection);
mpv_set_wakeup_callback(m_mpvPlayer, wakeup, this);
//绑定事件
mpv_observe_property(m_mpvPlayer, 0, "time-pos", MPV_FORMAT_DOUBLE);
// 判断mpv实例是否成功初始化
if (mpv_initialize(m_mpvPlayer) < 0) {
qDebug()<<"初始化失败!";
this->deleteLater();
}
}
void MMediaPlayer::setProperty(const QString &name, const QString &value)
{
mpv_set_option_string(m_mpvPlayer, name.toLatin1().data(), value.toLatin1().data());
}
QString MMediaPlayer::getProperty(const QString &name) const
{
return (QString)mpv_get_property_string(m_mpvPlayer, name.toLatin1().data());
}
void MMediaPlayer::changeState(MMediaPlayer::State stateNow)
{
//待设置的循环模式和设置之前一致则不处理
if (m_state == stateNow ) {
return;
}
m_state = stateNow;
Q_EMIT stateChanged(m_state);
}
void MMediaPlayer::autoPlay(MMediaPlaylist::PlaybackMode playbackMode)
{
//如果是单曲循环模式
if (playbackMode == MMediaPlaylist::PlaybackMode::CurrentItemInLoop) {
//播放完毕自动切歌(借用播放点改变时间逻辑循环)
m_positionChangeed = true;
}
truePlay("0");
}

View File

@ -0,0 +1,68 @@
#ifndef MMEDIAPLAYER_H
#define MMEDIAPLAYER_H
#include <QObject>
#include <QDebug>
#include <QTimerEvent>
#include <QTimer>
#include <QEventLoop>
#include <client.h> // MPV库头文件
#include "mmediaplaylist.h"
class MMediaPlayer : public QObject
{
Q_OBJECT
public:
// 停止播放 播放中 暂停中
enum State{StoppedState=0,PlayingState,PausedState}; //播放状态枚举
enum ErrorMsg{NotFound=-1,Damage=-2}; //播放状态枚举
MMediaPlayer(QObject *parent = nullptr);
void setPlaylist(MMediaPlaylist *playlist); //设置播放列表
void pause(); //暂停或继续
void pauseOnly(); // 暂停
State state() const; //获取状态
qint64 position() const; //获取当前播放点
void setPosition(qint64 pos); //设置播放起始点
bool isAvailable() const; //暂无实际功能
void delayMsecond(unsigned int msec); // 延时函数,不阻塞线程
void setVolume(int vol); //设置音量
qint64 duration() const; //获取总时长
void setMedia(const MMediaContent &media); //设置待播放媒体
void play(); //播放
public Q_SLOTS:
void stop(); //停止
void onMpvEvents(); //接收mpv事件
private:
void truePlay(QString startTime = "0"); //实际的播放函数
void handle_mpv_event(mpv_event *event); // 处理mpv事件
void createMvpplayer(); // 创建mvpPlayer
void setProperty(const QString &name, const QString &value); // 设置mpv属性
QString getProperty(const QString &name) const; // 获得mpv属性
void changeState(State stateNow); //改变状态
MMediaPlaylist * m_playList = nullptr; //私有播放列表
MMediaPlaylist * m_tmpPlayList = nullptr; //私有临时播放列表
mpv_handle *m_mpvPlayer = nullptr;//句柄
State m_state = StoppedState;//播放状态
QByteArray filenameBack = ""; //上次播放的媒体名
bool m_positionChangeed = false; //播放进度被设置
qint64 m_position = 0; //播放进度
qint64 m_duration = 0; //总时长
private Q_SLOTS:
void autoPlay(MMediaPlaylist::PlaybackMode playbackMode); //自动播放
Q_SIGNALS:
void mpvEvents(); // 触发onMpvEvents()槽函数的信号
void stateChanged(MMediaPlayer::State); //状态改变信号
void durationChanged(qint64); //切换媒体时,总时长改变信号
void positionChanged(qint64); //播放进度改变信号
void playFinish(); //媒体播放完成信号
void playError(); //媒体播放错误信号
void playErrorMsg(ErrorMsg errorCode);//媒体播放错误信息信号
// void signalVolume(int);
};
#endif // MMEDIAPLAYER_H

View File

@ -0,0 +1,222 @@
#include "mmediaplaylist.h"
MMediaPlaylist::MMediaPlaylist(QObject *parent)
: QObject(parent)
{
}
QString MMediaPlaylist::getPlayFileName()
{
//异常情况:播放列表为空
if (m_playerList.isEmpty()) {
return "";
}
//异常情况:当前播放的媒体在列表中的位置超过列表中媒体总数量
if (m_index >= m_playerList.length()) {
m_index = m_playerList.length();
return m_playerList.last().toString();
}
return m_playerList.at(m_index).toString();
}
int MMediaPlaylist::currentIndex() const
{
return m_index;
}
bool MMediaPlaylist::addMedia(const QUrl &items)
{
m_playerList.append(items);
return true;
}
void MMediaPlaylist::next()
{
//异常情况:播放列表为空
if (m_playerList.isEmpty()) {
return;
}
//异常情况:无当前播放媒体
if (m_index < 0) {
return;
}
switch (m_playbackMode) {
case Random:
m_index=randomIndex();
break;
case Sequential:
m_index++;
if (m_index >= m_playerList.length()) {
m_index = m_playerList.length() - 1;
}
break;
default:
m_index++;
if (m_index >= m_playerList.length()) {
m_index = 0;
}
break;
}
Q_EMIT currentIndexChanged(m_index);
Q_EMIT stop();
}
void MMediaPlaylist::previous()
{
//异常情况:播放列表为空
if (m_playerList.isEmpty()) {
return;
}
switch (m_playbackMode) {
case Random:
m_index=randomIndex();
break;
case Sequential:
m_index--;
if (m_index < 0) {
m_index = 0;
}
break;
default:
m_index--;
if (m_index < 0) {
m_index = m_playerList.length() - 1;
}
break;
}
Q_EMIT currentIndexChanged(m_index);
Q_EMIT stop();
}
void MMediaPlaylist::setCurrentIndex(int index)
{
//待设置的数量和设置之前一致则不处理,默认播放第一首除外
// if (index == m_index && index != 0) {
// return;
// }
//异常情况:要设置的媒体位置超过列表总长度
if (index >= m_playerList.length()) {
qDebug()<<"指定位置超过列表元素数量";
return;
}
//统一所有非正常情况
if (index < 0) {
index = -1;
}
m_index = index;
Q_EMIT currentIndexChanged(m_index);
}
void MMediaPlaylist::setPlaybackMode(MMediaPlaylist::PlaybackMode mode)
{
//待设置的循环模式和设置之前一致则不处理
if (mode == m_playbackMode) {
return;
}
m_playbackMode = mode;
Q_EMIT playbackModeChanged(mode);
}
int MMediaPlaylist::mediaCount() const
{
return m_playerList.length();
}
MMediaContent MMediaPlaylist::media(int index) const
{
//异常情况:要设置的媒体位置在列表中不存在
if (index >= m_playerList.length() || index < 0) {
return MMediaContent(QUrl(""));
}
return MMediaContent(m_playerList.at(index));
}
bool MMediaPlaylist::clear()
{
m_playerList.clear();
return true;
}
bool MMediaPlaylist::removeMedia(int pos)
{
//异常情况:要移出的媒体位置在列表中不存在
if (pos >= m_playerList.length() || pos < 0) {
return false;
}
m_playerList.removeAt(pos);
return true;
}
void MMediaPlaylist::playError()
{
//当前仅在存在播放列表中的媒体本地文件被删除时触发
//播放异常时,轮询所有列表中的媒体文件是否存在
for (auto url : m_playerList) {
//如果发现列表中有媒体文件没被删除
if (QFileInfo::exists(url.toLocalFile())) {
//如果是单曲循环则切换下一首
if (m_playbackMode == CurrentItemInLoop) {
next();
}
//按播放完成处理
palyFinish();
return;
}
}
//列表中所有媒体的本地文件全部被删除了
Q_EMIT currentIndexChanged(-1);
}
void MMediaPlaylist::playErrorMsg(int Damage)
{
if (Damage == -2) {
//如果是列表循环则切换下一首
if (m_playbackMode == Loop) {
next();
} else if(m_playbackMode == Random) {
m_index = randomIndex();
Q_EMIT currentIndexChanged(m_index);
Q_EMIT stop();
}
Q_EMIT autoPlay(m_playbackMode);
}
}
void MMediaPlaylist::palyFinish()
{
//如果没有待播放的媒体则不处理
if (m_index < 0) {
return;
}
//如果循环模式不是单曲循环则切换下一首
if (m_playbackMode != CurrentItemInLoop) {
next();
Q_EMIT currentIndexChanged(m_index);
}
Q_EMIT autoPlay(m_playbackMode);
}
MMediaPlaylist::PlaybackMode MMediaPlaylist::playbackMode() const
{
return m_playbackMode;
}
int MMediaPlaylist::randomIndex()
{
qsrand(QDateTime::currentDateTime().toMSecsSinceEpoch());
return qrand()%(m_playerList.length());
}
MMediaContent::MMediaContent(QUrl url)
{
m_url = url;
}
QUrl MMediaContent::canonicalUrl() const
{
return m_url;
}

View File

@ -0,0 +1,57 @@
#ifndef MMediaPlaylist_H
#define MMediaPlaylist_H
#include <QObject>
#include <QDebug>
#include <QFileInfo>
#include <QUrl>
#include <QDateTime>
class MMediaContent
{
public:
MMediaContent(QUrl url);
QUrl canonicalUrl() const; //获取Qurl内容
private:
QUrl m_url; //媒体url路径
};
class MMediaPlaylist : public QObject
{
Q_OBJECT
public:
// 只播放一次 单曲循环 列表播放 列表循环 随机播放
enum PlaybackMode { CurrentItemOnce=0, CurrentItemInLoop, Sequential, Loop, Random }; //播放循环模式枚举
MMediaPlaylist(QObject *parent = nullptr);
QString getPlayFileName(); //获取待播放媒体的文件名
int currentIndex() const; //获取当前播放的歌曲在播放列表中的位置
bool addMedia(const QUrl &items); //添加媒体
void next(); //切换下一首
void previous(); //切换上一首
void setCurrentIndex(int index); //设置选中播放列表中的位置
PlaybackMode playbackMode() const; //获取播放循环模式
void setPlaybackMode(PlaybackMode mode); //设置循环播放模式
int mediaCount() const; //列表中总媒体的数量
MMediaContent media(int index) const; //获取列表中特定位置的媒体
bool clear(); //清空列表
bool removeMedia(int pos); //移出特定位置的歌曲
public Q_SLOTS:
void palyFinish(); //播放完成槽函数
void playError(); //播放异常槽函数
void playErrorMsg(int Damage); //播放错误异常
private:
int randomIndex(); //生成随机数
QList<QUrl> m_playerList; //实际的播放队列
int m_index = 0; //当前播放的歌曲位置
PlaybackMode m_playbackMode = Loop; //当前列表的循环模式
Q_SIGNALS:
void currentIndexChanged(int); //媒体切换信号
void playbackModeChanged(MMediaPlaylist::PlaybackMode mode); //播放循环模式切换信号
void autoPlay(MMediaPlaylist::PlaybackMode playbackMode); //自动播放下一首信号
void stop(); //停止播放信号
};
#endif // MMediaPlaylist_H

651
UIControl/player/player.cpp Normal file
View File

@ -0,0 +1,651 @@
#include <QDebug>
#include <QDBusConnection>
#include <ukui-log4qt.h>
#include "player.h"
#include "UIControl/base/musicDataBase.h"
#include "UIControl/base/musicfileinformation.h"
#include "UI/player/playsongarea.h"
#include "UI/base/widgetstyle.h"
bool playController::play(QString playlist, int index)
{
if (playlist.compare(m_curList)==0)
{
// if (index == m_curIndex) {
// if (m_player->state() == MMediaPlayer::State::PlayingState){
// play();
// }else {
// pause();
// }
// }
// else {
stop();
setSongIndex(index);
play();
// }
return true;
}
return false;
}
bool playController::play()
{
if (m_player == nullptr) {
return false;
}
if (m_player->isAvailable() == false) { //存疑
return false;
}
if (m_player->state() == MMediaPlayer::State::PlayingState) {
m_player->pause();
} else {
m_player->play();
Q_EMIT curIndexChanged(m_playlist->currentIndex());
}
return true;
}
bool playController::pause()
{
if (m_player == nullptr) {
return false;
}
m_player->pause();
return true;
}
bool playController::pauseOnly()
{
if (m_player == nullptr) {
return false;
}
m_player->pauseOnly();
return true;
}
bool playController::stop()
{
if (m_player == nullptr) {
return false;
}
m_player->stop();
return true;
}
void playController::setSongIndex(int index)
{
if (m_playlist == nullptr) {
qDebug() << "m_playlist is null";
return;
}
if(index < 0)
{
return;
}
if (index > m_playlist->mediaCount()) {
return;
}
m_playlist->setCurrentIndex(index);
Q_EMIT curIndexChanged(index);
}
int playController::songIndex()
{
if (m_playlist == nullptr) {
qDebug() << "m_playlist is null";
return -1;
}
return m_playlist->currentIndex();
}
int playController::playmode()
{
if (m_playlist == nullptr) {
qDebug() << "m_playlist is null";
return -1;
}
return static_cast<MMediaPlaylist::PlaybackMode>(m_playlist->playbackMode());
}
void playController::setPlaymode(int mode)
{
if (m_playlist == nullptr || m_player == nullptr) {
return;
}
if (m_playlist == nullptr) {
qDebug() << "m_playlist is null";
return;
}
// if (mode < 0 || mode > 5) {
// m_playlist->setPlaybackMode(MMediaPlaylist::PlaybackMode::CurrentItemOnce);
// } else
m_playlist->setPlaybackMode(static_cast<MMediaPlaylist::PlaybackMode>(mode));
}
void playController::curPlaylist()
{
// Print Playlist information
if (m_playlist == nullptr) {
return;
}
for (auto i = 0; i < m_playlist->mediaCount(); i++) {
MMediaContent content = m_playlist->media(i);
// qDebug() << " "
// << "media[" << i << "] is:" << content.canonicalUrl();
}
}
void playController::setCurPlaylist(QString name, QStringList songPaths)
{
if (m_curList.compare(name)==0)
{
// qDebug() << "setCurPlaylist m_curList.compare(name)==0" << m_curList << name;
// return ;
}
if (m_playlist == nullptr || m_player == nullptr) {
return;
}
disconnect(m_playlist,&MMediaPlaylist::currentIndexChanged,this,&playController::slotIndexChange);
m_curList = name;
m_playlist->clear();
for (auto path : songPaths) {
m_playlist->addMedia(QUrl::fromLocalFile(path));
}
m_player->stop();
m_player->setPlaylist(nullptr);
m_player->setPlaylist(m_playlist);
// m_playlist->setCurrentIndex(-1);
connect(m_playlist,&MMediaPlaylist::currentIndexChanged,this,&playController::slotIndexChange);
isInitialed = true;
}
void playController::addSongToCurList(QString name, QString songPath)
{
if (name.compare(m_curList) != 0) {
qDebug() << __FUNCTION__ << " the playlist to add is not Current playlist.";
return;
}
if (m_playlist != nullptr) {
m_playlist->addMedia(QUrl::fromLocalFile(songPath));
}
}
void playController::removeSongFromCurList(QString name, int index)
{
if (name.compare(m_curList) != 0)
{
// qDebug() << __FUNCTION__ << " the playlist to add is not Current playlist.";
return;
}
if (m_playlist != nullptr) {
// m_playlist->removeMedia(index);
//判断删除后 播放歌曲的index 当前只判断了删除正在播放的歌曲 还没做删除正在播放之前的歌曲和之后的歌曲
int count = m_playlist->mediaCount();
int state = m_player->state();
if(m_curIndex == index)
{
stop();
if(m_curIndex == count - 1)
{
m_curIndex = 0;
m_playlist->removeMedia(index);
if(m_playlist->mediaCount() == 0)
{
m_curIndex = -1;
}
setSongIndex(m_curIndex);
}
else
{
m_playlist->removeMedia(index);
if(m_playlist->mediaCount() == 0)
{
m_curIndex = -1;
}
// setSongIndex(m_curIndex);
setSongIndex(m_curIndex);
}
//删除当前播放歌曲不更改播放状态 2021.09.10
if (state == MMediaPlayer::State::PlayingState) {
m_player->play();
} else { //设置进度条归 0
Q_EMIT signalSetValue();
m_player->pause();
}
}
else if(m_curIndex > index)
{
// int position = 0;
// if(m_player->state()==MMediaPlayer::PlayingState)
// {
// position = m_player->position();
// }
// m_player->stop();
m_playlist->removeMedia(index);
m_curIndex = m_curIndex - 1;
//只负责高亮歌曲
setSongIndex(m_curIndex);
// m_player->setPosition(position);
//歌曲删除重新播放(跨函数调用)
// PlaySongArea::getInstance().hSlider->setValue(position);
//MPV setPosition已经设置播放不用再次设置播放
// m_player->play();
}
else if(m_curIndex < index)
{
m_playlist->removeMedia(index);
}
Q_EMIT curIndexChanged(m_curIndex);
Q_EMIT currentIndexAndCurrentList(m_curIndex,m_curList);
slotIndexChange(m_curIndex);
// auto cr_index = m_playlist->currentIndex();
// Q_EMIT curIndexChanged(cr_index);
// Q_EMIT currentIndexAndCurrentList(cr_index,m_curList);
//删除正在播放的歌曲时,正在播放的歌曲名和时长实时更新
// slotIndexChange(cr_index);
// if(name == ALLMUSIC)
// {
// }
}
}
void playController::removeSongFromLocalList(QString name, int index)
{
if (name.compare(m_curList) != 0)
{
qDebug() << __FUNCTION__ << " the playlist to add is not Current playlist.";
return;
}
if (m_playlist != nullptr)
{
int count = m_playlist->mediaCount();
int state = m_player->state();
if(m_curIndex == index)
{
stop();
if(m_curIndex == count - 1)
{
m_curIndex = 0;
m_playlist->removeMedia(index);
if(m_playlist->mediaCount() == 0)
{
m_curIndex = -1;
}
setSongIndex(m_curIndex);
}
else
{
m_playlist->removeMedia(index);
if(m_playlist->mediaCount() == 0)
{
m_curIndex = -1;
}
setSongIndex(m_curIndex);
}
//删除当前播放歌曲不更改播放状态 2021.09.10
if (state == MMediaPlayer::State::PlayingState) {
m_player->play();
} else { //设置进度条归 0
Q_EMIT signalSetValue();
m_player->pause();
}
}
else if(m_curIndex > index)
{
// int position = 0;
// if(m_player->state()==MMediaPlayer::PlayingState)
// {
// position = m_player->position();
// }
// m_player->stop();
m_playlist->removeMedia(index);
m_curIndex = m_curIndex - 1;
setSongIndex(m_curIndex);
// m_player->setPosition(position);
// m_player->play();
}
else if(m_curIndex < index)
{
m_playlist->removeMedia(index);
}
Q_EMIT curIndexChanged(m_curIndex);
Q_EMIT currentIndexAndCurrentList(m_curIndex,m_curList);
slotIndexChange(m_curIndex);
}
}
playController::PlayState playController::getState()
{
if(m_player->state() == MMediaPlayer::State::PlayingState)
return PlayState::PLAY_STATE;
else if(m_player->state() == MMediaPlayer::State::PausedState)
return PlayState::PAUSED_STATE;
else if(m_player->state() == MMediaPlayer::State::StoppedState)
return PlayState::STOP_STATE;
}
playController::playController()
: m_curList(""),m_curIndex(-1)
{
m_player = new MMediaPlayer(this);
if (m_player == nullptr) {
qDebug() << "failed to create player ";
return;
}
m_playlist = new MMediaPlaylist(m_player);
if (m_playlist == nullptr) {
qDebug() << "failed to create laylist";
return;
}
m_player->setPlaylist(m_playlist);
init();
initDbus();
m_playlist->setPlaybackMode(MMediaPlaylist::Loop);
// m_playlist->setCurrentIndex(-1);
connect(m_playlist,&MMediaPlaylist::currentIndexChanged,this,&playController::slotIndexChange);
connect(m_player,&MMediaPlayer::stateChanged,this,&playController::slotStateChanged);
connect(m_playlist,&MMediaPlaylist::playbackModeChanged,this,&playController::slotPlayModeChange);
// connect(m_player,&MMediaPlayer::playErrorMsg,this,&playController::slotPlayErrorMsg);
m_volume = volumeSetting->get("volume").toInt();
delayMsecond(100);
m_player->setVolume(m_volume);
}
void playController::init()
{
volumeSetting = new QGSettings(KYLINMUSIC);
m_volume = volumeSetting->get("volume").toInt();
delayMsecond(100);
m_player->setVolume(m_volume);
playSetting = new QGSettings(KYLINMUSIC);
m_playListName = playSetting->get("playlistname").toString();
//如果保存的歌单是 歌曲列表 或者 我喜欢(我喜欢与歌曲列表必存在不做判断),那么保存的歌曲路径不做处理
if(m_playListName == ALLMUSIC)
{
m_curList = ALLMUSIC;
}
else if(m_playListName == FAV)
{
m_curList = FAV;
}
else
{
int ret = g_db->checkPlayListExist(m_playListName);
if(ret == DB_OP_SUCC)
{
if (m_playListName == SEARCH) {
playSetting->set("playlistname", ALLMUSIC);
m_curList = ALLMUSIC;
playSetting->set("path", "");
} else {
m_curList = m_playListName;
QString pat = playSetting->get("path").toString();
int ref = g_db->checkIfSongExistsInPlayList(pat, m_curList);
if(ref != DB_OP_SUCC)
{
playSetting->set("path", "");
}
}
}
else
{
playSetting->set("playlistname", ALLMUSIC);
m_curList = ALLMUSIC;
playSetting->set("path", "");
}
}
playModeSetting = new QGSettings(KYLINMUSIC);
m_mode = static_cast<PlayMode>(playModeSetting->get("playbackmode").toInt());
}
void playController::initDbus()
{
QDBusConnection::sessionBus().connect(QString(), "/", "org.ukui.media", "sinkVolumeChanged", this, SLOT(slotVolumeChange(QString,int,bool)));
}
int playController::getVolume()
{
return m_volume;
}
void playController::delayMsecond(unsigned int msec)
{
QEventLoop loop;//定义一个新的事件循环
QTimer::singleShot(msec, &loop, SLOT(quit()));//创建单次定时器,槽函数为事件循环的退出函数
loop.exec();//事件循环开始执行,程序会卡在这里,直到定时时间到,本循环被退出
}
void playController::delayMsecondSetVolume()
{
int currentVolume = getVolume();
KyInfo() << "currentVolume = " << currentVolume
<< "playState = " << getPlayer()->state();
delayMsecond(100);
setVolume(currentVolume);
}
void playController::setVolume(int volume)
{
if(volume > 100) {
volume = 100;
}
if(volume < 0) {
volume = 0;
}
m_volume = volume;
volumeSetting->set("volume", volume);
KyInfo() << "m_receive = " << m_receive;
if (!m_receive) {
KyInfo() << "begin setVolume";
m_player->setVolume(volume);
} else {
m_receive = false;
}
}
void playController::onCurrentIndexChanged()
{
qDebug() << "onCurrentIndexChanged";
}
void playController::onPositionChanged(double value)
{
qDebug() << "onPositionChanged";
if (m_player == nullptr) {
return;
}
m_player->setPosition(m_player->duration() * value);
}
void playController::onNextSong()
{
if (m_playlist == nullptr || m_player == nullptr) {
qDebug() << "m_playlist or m_player is nullptr";
return;
}
m_playlist->next();
m_player->play();
curPlaylist();
auto index = m_playlist->currentIndex();
Q_EMIT curIndexChanged(index);
}
void playController::onPreviousSong()
{
if (m_playlist == nullptr || m_player == nullptr) {
qDebug() << "m_playlist or m_player is nullptr";
return;
}
m_playlist->previous();
m_player->play();
auto index = m_playlist->currentIndex();
Q_EMIT curIndexChanged(index);
}
void playController::setCurList(QString renameList)
{
m_curList = renameList;
}
void playController::onError()
{
qDebug() << "onError";
}
void playController::onMediaStatusChanged()
{
qDebug() << "onMediaStatusChanged";
}
playController::~playController(/* args */)
{
if (m_playlist != nullptr) {
m_playlist->deleteLater();
}
if (m_player != nullptr) {
m_player->deleteLater();
}
}
bool playController::playSingleSong(QString Path, bool isPlayNowOrNext)
{
}
void playController::slotStateChanged(MMediaPlayer::State newState)
{
if(newState == MMediaPlayer::State::PlayingState)
Q_EMIT playerStateChange(playController::PlayState::PLAY_STATE);
else if(newState == MMediaPlayer::State::PausedState)
Q_EMIT playerStateChange(playController::PlayState::PAUSED_STATE);
else if(newState == MMediaPlayer::State::StoppedState)
Q_EMIT playerStateChange(playController::PlayState::STOP_STATE);
}
void playController::slotPlayModeChange(MMediaPlaylist::PlaybackMode mode)
{
if(mode == MMediaPlaylist::PlaybackMode::CurrentItemInLoop)
Q_EMIT signalPlayMode(static_cast<MMediaPlaylist::PlaybackMode>(playController::PlayMode::CurrentItemInLoop));
else if(mode == MMediaPlaylist::PlaybackMode::Sequential)
Q_EMIT signalPlayMode(static_cast<MMediaPlaylist::PlaybackMode>(playController::PlayMode::Sequential));
else if(mode == MMediaPlaylist::PlaybackMode::Loop)
Q_EMIT signalPlayMode(static_cast<MMediaPlaylist::PlaybackMode>(playController::PlayMode::Loop));
else if(mode == MMediaPlaylist::PlaybackMode::Random)
Q_EMIT signalPlayMode(static_cast<MMediaPlaylist::PlaybackMode>(playController::PlayMode::Random));
}
void playController::slotIndexChange(int index)
{
if(index == -1)
{
Q_EMIT signalNotPlaying();
//当index == -1时会调用positionChanged导致时长显示错误
Q_EMIT singalChangePath("");
Q_EMIT currentIndexAndCurrentList(-1,m_curList);
playSetting->set("playlistname", m_curList);
playSetting->set("path", "");
return;
}
m_curIndex = index;
MMediaContent content = m_playlist->media(index);
QString path = content.canonicalUrl().toLocalFile();
QFileInfo file(path.remove("file://"));
if(file.exists())
{
x = 0;
Q_EMIT currentIndexAndCurrentList(index,m_curList);
Q_EMIT singalChangePath(path);
if(m_curList == HISTORY)
{
playSetting->set("playlistname", ALLMUSIC);
}
else
{
playSetting->set("playlistname", m_curList);
}
playSetting->set("path", path);
}
else
{
x++;
if(x > m_playlist->mediaCount())
{
x = 0;
// index = -1;
// m_playlist->setCurrentIndex(index);
return;
}
}
}
//void playController::slotPlayErrorMsg(MMediaPlayer::ErrorMsg msg)
//{
//// m_msg = msg;
// Q_EMIT playErrorMsg(msg);
//}
void playController::setPosition(int position)
{
if (qAbs(m_player->position() - position) > 99)
m_player->setPosition(position);
}
void playController::setPlayListName(QString playListName)
{
playSetting->set("playlistname", playListName);
}
QString playController::getPlayListName()
{
return playSetting->get("playlistname").toString();
}
QString playController::getPath()
{
return playSetting->get("path").toString();
}
void playController::setMode(playController::PlayMode mode)
{
m_mode = mode;
playModeSetting->set("playbackmode", m_mode);
}
playController::PlayMode playController::mode() const
{
return m_mode;
}
void playController::slotVolumeChange(QString app, int value, bool mute)
{
if (app == "kylin-music") {
if (value < 0) {
return;
}
if (value != m_volume) {
KyInfo() << "value != m_volume."
<< "value = " << value;
m_receive = true;
Q_EMIT signalVolume(value);
}
//mute = true静音 mute = false取消静音
Q_EMIT signalMute(mute);
}
}

154
UIControl/player/player.h Normal file
View File

@ -0,0 +1,154 @@
#ifndef PLAYER_H
#define PLAYER_H
#include <QObject>
#include <QGSettings>
#include <QTimerEvent>
#include <QTimer>
#include <QEventLoop>
#include "coreplayer/mmediaplayer.h"
#include "coreplayer/mmediaplaylist.h"
class playController : public QObject {
Q_OBJECT
public:
enum PlayState {
STOP_STATE = 0,
PLAY_STATE = 1,
PAUSED_STATE = 2
};
enum PlayMode {
CurrentItemInLoop = 1,
Sequential = 2,
Loop = 3,
Random = 4,
};
public:
static playController& getInstance()
{
static playController instance;
return instance;
}
private:
playController(/* args */);
playController(playController const&);
playController& operator=(playController const&);
~playController();
void init();
void initDbus();
public:
//新增接口 fyf
bool playSingleSong(QString Path, bool isPlayNowOrNext);
bool play(QString playlist, int index);
bool play();
bool pause();
bool pauseOnly();
bool stop();
int volume();
void setPlayPosition(int pos);
int playPosition();
void setSongIndex(int index);
int songIndex();
int playmode();
void setPlaymode(int mode);
void curPlaylist();
void setCurPlaylist(QString name, QStringList songPaths);
void addSongToCurList(QString name, QString songPath);
//从歌单删除
void removeSongFromCurList(QString name, int index);
//从本地删除
void removeSongFromLocalList(QString name, int index);
// void removeMedia(QString name, int index);
PlayState getState();
PlayMode mode() const;
MMediaPlayer* getPlayer()
{
return m_player;
}
MMediaPlaylist* getPlaylist()
{
return m_playlist;
}
void setPosition(int position);
//获取音量
int getVolume();
void delayMsecond(unsigned int msec); // 延时函数,不阻塞线程
void delayMsecondSetVolume();
//设置音量
void setVolume(int volume);
//获取歌单名
QString getPlayListName();
//获取歌曲路径
QString getPath();
Q_SIGNALS:
void curPositionChanged(qint64);
void curDurationChanged(qint64);
void curIndexChanged(int index);
void playerError(int error, QString errMsg);
void playerStateChange(playController::PlayState newState);
void singalChangePath(QString path);
void currentIndexAndCurrentList(int index,QString listname);
void signalPlayMode(int playModel);
void signalNotPlaying();
// void playErrorMsg(int errorCode);//媒体播放错误信息信号
//进度条归 0
void signalSetValue();
//系统音乐音量改变
void signalVolume(int value);
//系统音乐音量静音
void signalMute(bool mute);
public Q_SLOTS:
void onCurrentIndexChanged();
void onPositionChanged(double value);
void onNextSong();
void onPreviousSong();
void setCurList(QString renameList);
void setMode(playController::PlayMode mode);
void setPlayListName(QString playListName);
private Q_SLOTS:
void onError();
void onMediaStatusChanged();
//状态改变
void slotStateChanged(MMediaPlayer::State newState);
//播放模式改变
void slotPlayModeChange(MMediaPlaylist::PlaybackMode mode);
//获得当前播放的index
void slotIndexChange(int index);
//媒体播放错误信息槽函数
// void slotPlayErrorMsg(MMediaPlayer::ErrorMsg msg);
//接收系统应用音量变化
void slotVolumeChange(QString app, int value, bool mute);
private:
//当前播放列表名
QString m_curList;
//当前播放的索引
int m_curIndex;
MMediaPlayer* m_player = nullptr;
MMediaPlaylist* m_playlist = nullptr;
QGSettings *volumeSetting = nullptr;
bool isInitialed = false;
//在列表里歌曲判断本地歌曲是否存在没有播放的情况下当前函数掉了多少次要是歌曲在播放找到本地路径存在x重新计数
int x = 0;
int m_volume = 100;
QGSettings *playSetting = nullptr;
QGSettings *playModeSetting = nullptr;
QString m_playListName;
PlayMode m_mode = playController::Loop;
// int m_msg = 0;
//标记系统音乐接收状态
bool m_receive = false;
};
#endif // PLAYER_H

View File

@ -0,0 +1,169 @@
#include "musiclistmodel.h"
#include <QStandardItem>
#include <QVariant>
MusicListModel::MusicListModel(QObject* parent) : QObject(parent)
{
titleList.append(tr("Song"));
titleList.append(tr("Singer"));
titleList.append(tr("Album"));
titleList.append(tr("Time"));
m_model.setHorizontalHeaderLabels(titleList); //使用list设置水平标题标签。如有必要将列数增加到标签的大小
m_model.horizontalHeaderItem(titleList.length()-1)->setTextAlignment(Qt::AlignRight);
}
bool MusicListModel::add(musicDataStruct info)
{
QStandardItem* root = m_model.invisibleRootItem();
QStandardItem* item0 = new QStandardItem();
QStandardItem* item1 = new QStandardItem();
QStandardItem* item2 = new QStandardItem();
QStandardItem* item3 = new QStandardItem();
// QStandardItem* item4 = new QStandardItem();
// QStandardItem* item5 = new QStandardItem();
// QStandardItem* item6 = new QStandardItem();
bool ret = true;
if( (root != NULL) && (item0 != NULL) && (item1 != NULL) && (item2 != NULL) )
{
item0->setData(info.title, Qt::ToolTipRole);
item1->setData(info.singer, Qt::ToolTipRole);
item2->setData(info.album, Qt::ToolTipRole);
item3->setData(info.time, Qt::ToolTipRole);
item0->setData(info.title, Qt::DisplayRole);
item0->setTextAlignment(Qt::AlignLeft|Qt::AlignVCenter);
item1->setData(info.singer, Qt::DisplayRole);
item2->setData(info.album, Qt::DisplayRole);
item3->setData(info.time, Qt::DisplayRole);
item3->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
item0->setData(info.filepath, Qt::DecorationRole);
item1->setData(info.filetype, Qt::DecorationRole);
item2->setData(info.size, Qt::DecorationRole);
item0->setEditable(false);
item1->setEditable(false);
item2->setEditable(false);
item3->setEditable(false);
// item4->setEditable(false);
// item5->setEditable(false);
// item6->setEditable(false);
int newRow = count();
root->setChild(newRow, 0, item0);
root->setChild(newRow, 1, item1);
root->setChild(newRow, 2, item2);
root->setChild(newRow, 3, item3);
// root->setChild(newRow, 4, item4);
// root->setChild(newRow, 5, item5);
// root->setChild(newRow, 6, item6);
resList.append(info);
}
else
{
ret = false;
}
return ret;
}
bool MusicListModel::add(QList<musicDataStruct> list)
{
bool ret = true;
for(int i=0; i<list.count(); i++)
{
ret = ret && add(list[i]);
}
return ret;
}
bool MusicListModel::remove(int i)
{
bool ret = true;
if( (0 <= i) && (i < count()) )
{
m_model.removeRow(i);
}
else
{
ret = false;
}
return ret;
}
void MusicListModel::clear()
{
m_model.clear();
resList.clear();
}
musicDataStruct MusicListModel::getItem(int i)
{
musicDataStruct ret;
if( (0 <= i) && (i < count()) )
{
QModelIndex index0 = m_model.index(i, 0, QModelIndex());
QModelIndex index1 = m_model.index(i, 1, QModelIndex());
QModelIndex index2 = m_model.index(i, 2, QModelIndex());
QModelIndex index3 = m_model.index(i, 3, QModelIndex());
// QModelIndex index4 = m_model.index(i, 4, QModelIndex());
// QModelIndex index5 = m_model.index(i, 5, QModelIndex());
// QModelIndex index6 = m_model.index(i, 6, QModelIndex());
QVariant v0 = index0.data(Qt::DisplayRole);
QVariant v1 = index1.data(Qt::DisplayRole);
QVariant v2 = index2.data(Qt::DisplayRole);
QVariant v3 = index3.data(Qt::DisplayRole);
QVariant v4 = index0.data(Qt::DecorationRole);
QVariant v5 = index1.data(Qt::DecorationRole);
QVariant v6 = index2.data(Qt::DecorationRole);
ret.title = v0.toString();
ret.singer = v1.toString();
ret.album = v2.toString();
ret.time = v3.toString();
ret.filepath = v4.toString();
ret.filetype = v5.toString();
ret.size = v6.toString();
}
return ret;
}
QStringList MusicListModel::getPathList(QString listName)
{
QStringList pathList;
QList<musicDataStruct> musicInfoList;
int ret;
ret = g_db->getSongInfoListFromDB(musicInfoList,listName);
foreach (const musicDataStruct date, musicInfoList) {
pathList.append(date.filepath);
}
return pathList;
}
void MusicListModel::getMusicDateList(QList<musicDataStruct> list)
{
list = resList;
}
int MusicListModel::count()
{
return m_model.rowCount();
}
void MusicListModel::setView(QTableView& view)
{
view.setModel(&m_model);
}

View File

@ -0,0 +1,33 @@
#ifndef SCOREINFOMODEL_H
#define SCOREINFOMODEL_H
#include <QObject>
#include <QStandardItem>
#include <QTableView>
#include <QList>
#include <QDebug>
#include "UIControl/base/musicDataBase.h"
class MusicListModel : public QObject
{
Q_OBJECT
public:
explicit MusicListModel(QObject *parent = 0);
bool add(musicDataStruct info);
bool add(QList<musicDataStruct> list);
bool remove(int i);
int count();
void clear();
void setView(QTableView &view);
musicDataStruct getItem(int i);
QStringList getPathList(QString listName);
void getMusicDateList(QList<musicDataStruct> list);
QStandardItemModel m_model; // 数据模型,不能单独显示出来
QStringList titleList;
QStandardItem* item[4];
private:
QList<musicDataStruct> resList;
};
#endif // SCOREINFOMODEL_H

15
clear.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/bash
make clean
rm -rf kylin-music-plugins-simple/build/ \
kylin-music.pro.user \
debian/files \
.qmake.stash \
Makefile \
debian/.debhelper/ \
debian/debhelper-build-stamp \
debian/kylin-music.debhelper.log \
debian/kylin-music.substvars \
debian/kylin-music/ \
kylin-music

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

View File

@ -0,0 +1,47 @@
# Music Player
## Overview
Music Player is a simple to use, user-friendly, support.mp3,.ogg,.wma,.aac,.flac and other music formats music player. While playing local music, you can also group music by custom playlists according to your preferences. In addition to the regular mode, Music Player also has a small window mode to meet the different needs of users.
### Songs List
The song list page after adding the songs is shown in the Fig.below. You can select the control area for play/pause, previous track, next track and so on.
![Fig.1 Songs List-big](image/list.png)
### Right click on the song
Select the right button to add to your favorite playlist, delete songs, view song information and other operations.
![Fig.2 right-click-big](image/right.png)
### New playlist
You can create a new playlist by clicking the plus sign "+" on the right side of "My Playlist".
Note: The new playlist name cannot contain the following characters: \ / : * ? " & < > |
![Fig.3 new-playlist-big](image/create-playlist.png)
### Playlist right
You can right-click to view the editable operations of the playlist, such as play, rename, delete, etc.,
but the "I Love" playlist only has playback operations.
![Fig.4 playlist-right](image/edit-playlist.png)
### Toggle mini mode
You can switch the Mini window for better user experience.
#### Before Toggle mini mode
![Fig.5 Songs List-big](image/list.png)
#### After Toggle mini mode
![Fig.6 Mini](image/mini.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -0,0 +1,50 @@
# 音乐
## 概 述
音乐是一款简单易用,界面友好,支持.mp3、.ogg、.wma、.aac、.flac等音乐格式的音乐播放器。在播放本地音乐的同时还可以根据喜好将自定义歌单来对音乐进行分组。除了常规模式外音乐还有小窗口模式来满足用户的不同需求。
### 歌曲列表
添加完歌曲后的歌曲列表页面如下图所示。
您可以选择控制区域进行播放/暂停、上一首、下一首等操作。
![图 1 歌曲列表-big](image/list.png)
### 歌曲右键
您可以选择一首歌曲,通过鼠标右键进行添加到“我喜欢”歌单、删除、查看歌曲信息等操作。
![图 2 歌曲右键-big](image/right.png)
### 新建歌单
您可以通过“我的歌单”右侧加号“+”进行新建歌单。
注:新建歌单名不能包含以下字符:\ / : * ? " & < > |
![图 3 新建歌单-big](image/create-playlist.png)
### 歌单右键
您可以通过右键查看歌单可编辑的操作,如播放、重命名、删除等操作,但“我喜欢”歌单仅有播放操作。
![图 4 歌单右键-big](image/edit-playlist.png)
### 切换迷你模式
为了更好的体验您可以切换Mini窗口。
在Mini窗口中您可以进行上一首、播放、暂停、下一首、选择播放模式等操作。
#### 切换前
![图 5 歌曲列表-big](image/list.png)
#### 切换后
![图 6 迷你模式](image/mini.png)

View File

@ -0,0 +1,40 @@
<schemalist gettext-domain="kylin-music">
<schema id="org.kylin-music-data.settings" path="/org/kylin-music/">
<key name="light" type="s" >
<default>"1111111111"</default>
<summary>light</summary>
<description>light</description>
</key>
<key name="dark" type="s" >
<default>"2222222222"</default>
<summary>dark</summary>
<description>dark</description>
</key>
<key name="thememode" type="s" >
<default>"auto"</default>
<summary>auto</summary>
<description>auto</description>
</key>
<key name="volume" type="i" >
<default>100</default>
<summary>volume</summary>
<description>volume</description>
</key>
<key name="playlistname" type="s" >
<default>"LocalMusic"</default>
<summary>playListName</summary>
<description>playListName</description>
</key>
<key name="path" type="s" >
<default>""</default>
<summary>path</summary>
<description>path</description>
</key>
<key name="playbackmode" type="i" >
<default>3</default>
<summary>playbackmode</summary>
<description>playbackmode</description>
</key>
</schema>
</schemalist>

View File

@ -0,0 +1,39 @@
<schemalist gettext-domain="ukui-log4qt-kylin-music">
<schema id="org.ukui.ukui-log4qt-kylin-music" path="/org/ukui/ukui-log4qt-kylin-music/">
<key type="s" name="log4j-handleqtmessages">
<default>"true"</default>
<summary>hook qt messages</summary>
<description>Control if hook qt messages</description>
</key>
<key type="s" name="log4j-rootlogger">
<default>"DEBUG,console,daily"</default>
<summary>config rootLogger's level and appenders</summary>
<description>config rootLogger's level and appenders:"level,appender"</description>
</key>
<key type="s" name="log4j-appender-daily-datepattern">
<default>".yyyy-MM-dd"</default>
<summary>daily log file pattern</summary>
<description>set daily log file pattern format:one day</description>
</key>
<key type="s" name="log4j-appender-daily-layout-conversionpattern">
<default>"%d{yyyy-MM-dd HH:mm:ss,zzz}(%-4r)[%t]|%-5p| - %m%n"</default>
<summary>set log message's format</summary>
<description>set log message's format</description>
</key>
<key type="i" name="delaytime">
<default>3600</default>
<summary>set check log files delay time</summary>
<description>set check log files delay time</description>
</key>
<key type="i" name="maxfilecount">
<default>7</default>
<summary>set log files count</summary>
<description>set log files count,unit s</description>
</key>
<key type="i" name="maxfilesize">
<default>512</default>
<summary>set log files total size</summary>
<description>set log files total size, unit M</description>
</key>
</schema>
</schemalist>

BIN
image/loveblack2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 B

BIN
image/pause1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 B

BIN
image/play1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

BIN
img/clicked/add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 B

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 59 (86127) - https://sketch.com -->
<title>audio-card-symbolic-w</title>
<desc>Created with Sketch.</desc>
<g id="audio-card-symbolic-w" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="audio-card-symbolic" transform="translate(1.000000, 1.000000)">
<g id="图层_2">
<g id="编组" fill="#FFFFFF" fill-rule="nonzero">
<path d="M12,1 C12.6,1 13,1.4 13,2 L13,12 C13,12.6 12.6,13 12,13 L2,13 C1.4,13 1,12.6 1,12 L1,2 C1,1.4 1.4,1 2,1 L12,1 M12,0 L2,0 C0.9,0 0,0.9 0,2 L0,12 C0,13.1 0.9,14 2,14 L12,14 C13.1,14 14,13.1 14,12 L14,2 C14,0.9 13.1,0 12,0 L12,0 Z" id="形状"></path>
</g>
<g id="编组" transform="translate(3.000000, 2.000000)">
<path d="M2.5,8.5 L2.5,1.8 C2.5,1.3 2.8,0.9 3.3,0.8 L6.3,0.2 C6.9,0.1 7.5,0.5 7.5,1.2 L7.5,7.5" id="路径" stroke="#FFFFFF"></path>
<circle id="椭圆形" fill="#FFFFFF" fill-rule="nonzero" cx="1.5" cy="8.5" r="1.5"></circle>
<circle id="椭圆形" fill="#FFFFFF" fill-rule="nonzero" cx="6.5" cy="7.5" r="1.5"></circle>
<line x1="2.5" y1="4" x2="7.5" y2="3" id="路径" stroke="#FFFFFF"></line>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
img/clicked/backoff.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

BIN
img/clicked/close.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 B

BIN
img/clicked/delete.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

BIN
img/clicked/enlarg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

BIN
img/clicked/forward.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B

BIN
img/clicked/lastsong.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 795 B

BIN
img/clicked/listloop.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1003 B

BIN
img/clicked/love1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 548 B

Some files were not shown because too many files have changed in this diff Show More