From f52f6e2d44bc3a08a5b2fa281459af8baac68f0d Mon Sep 17 00:00:00 2001 From: Keith Bennett Date: Sat, 22 Mar 2014 17:02:43 +0000 Subject: [PATCH] Squashed 'src/gui/qocoa/' content from commit ffe23cb git-subtree-dir: src/gui/qocoa git-subtree-split: ffe23cbb2f221bc9eacd1de2134c2947fed71c12 --- .gitignore | 2 + CMakeLists.txt | 48 +++++ LICENSE.txt | 19 ++ Qocoa.pro | 17 ++ README.md | 36 ++++ TODO.md | 13 ++ gallery.cpp | 75 +++++++ gallery.h | 14 ++ gallery.png | Bin 0 -> 42195 bytes main.cpp | 13 ++ qbutton.h | 49 +++++ qbutton_mac.mm | 229 +++++++++++++++++++++ qbutton_nonmac.cpp | 89 +++++++++ qocoa_mac.h | 63 ++++++ qprogressindicatorspinning.h | 29 +++ qprogressindicatorspinning_mac.mm | 70 +++++++ qprogressindicatorspinning_nonmac.cpp | 72 +++++++ qprogressindicatorspinning_nonmac.gif | Bin 0 -> 3208 bytes qprogressindicatorspinning_nonmac.qrc | 5 + qsearchfield.h | 48 +++++ qsearchfield_mac.mm | 262 +++++++++++++++++++++++++ qsearchfield_nonmac.cpp | 256 ++++++++++++++++++++++++ qsearchfield_nonmac.qrc | 7 + qsearchfield_nonmac_clear.png | Bin 0 -> 736 bytes qsearchfield_nonmac_magnifier.png | Bin 0 -> 300 bytes qsearchfield_nonmac_magnifier_menu.png | Bin 0 -> 439 bytes 26 files changed, 1416 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 LICENSE.txt create mode 100644 Qocoa.pro create mode 100644 README.md create mode 100644 TODO.md create mode 100644 gallery.cpp create mode 100644 gallery.h create mode 100644 gallery.png create mode 100644 main.cpp create mode 100644 qbutton.h create mode 100644 qbutton_mac.mm create mode 100644 qbutton_nonmac.cpp create mode 100644 qocoa_mac.h create mode 100644 qprogressindicatorspinning.h create mode 100644 qprogressindicatorspinning_mac.mm create mode 100644 qprogressindicatorspinning_nonmac.cpp create mode 100644 qprogressindicatorspinning_nonmac.gif create mode 100644 qprogressindicatorspinning_nonmac.qrc create mode 100644 qsearchfield.h create mode 100644 qsearchfield_mac.mm create mode 100644 qsearchfield_nonmac.cpp create mode 100644 qsearchfield_nonmac.qrc create mode 100644 qsearchfield_nonmac_clear.png create mode 100644 qsearchfield_nonmac_magnifier.png create mode 100644 qsearchfield_nonmac_magnifier_menu.png diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..4963d2730 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +cmake/ +qmake/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..513f81f7d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,48 @@ +project(Qocoa) +cmake_minimum_required(VERSION 2.8) + +find_package(Qt4 COMPONENTS QtMain QtCore QtGui REQUIRED) +include(UseQt4) + +set(SOURCES + main.cpp + gallery.cpp +) + +set(HEADERS + gallery.h + qsearchfield.h + qbutton.h + qprogressindicatorspinning.h +) + +qt4_wrap_cpp(MOC_SOURCES ${HEADERS}) + +if(APPLE) + list(APPEND SOURCES + qsearchfield_mac.mm + qbutton_mac.mm + qprogressindicatorspinning_mac.mm + ) +else() + list(APPEND SOURCES + qsearchfield_nonmac.cpp + qbutton_nonmac.cpp + qprogressindicatorspinning_nonmac.cpp + ) + set(RESOURCES + qsearchfield_nonmac.qrc + qprogressindicatorspinning_nonmac.qrc + ) + qt4_add_resources(RESOURCES_SOURCES ${RESOURCES}) +endif() + +add_executable(Qocoa + WIN32 MACOSX_BUNDLE + ${SOURCES} ${MOC_SOURCES} ${RESOURCES_SOURCES} +) +target_link_libraries(Qocoa ${QT_LIBRARIES}) + +if(APPLE) + set_target_properties(Qocoa PROPERTIES LINK_FLAGS "-framework Foundation -framework AppKit") +endif() diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 000000000..910eb6d20 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (C) 2011 by Mike McQuaid + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Qocoa.pro b/Qocoa.pro new file mode 100644 index 000000000..8b325d192 --- /dev/null +++ b/Qocoa.pro @@ -0,0 +1,17 @@ +SOURCES += main.cpp\ + gallery.cpp \ + +HEADERS += gallery.h \ + qocoa_mac.h \ + qsearchfield.h \ + qbutton.h \ + qprogressindicatorspinning.h \ + +mac { + OBJECTIVE_SOURCES += qsearchfield_mac.mm qbutton_mac.mm qprogressindicatorspinning_mac.mm + LIBS += -framework Foundation -framework Appkit + QMAKE_CFLAGS += -mmacosx-version-min=10.6 +} else { + SOURCES += qsearchfield_nonmac.cpp qbutton_nonmac.cpp qprogressindicatorspinning_nonmac.cpp + RESOURCES += qsearchfield_nonmac.qrc qprogressindicatorspinning_nonmac.qrc +} diff --git a/README.md b/README.md new file mode 100644 index 000000000..3d37b6a27 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +# Qocoa +Qocoa is a collection of Qt wrappers for OSX's Cocoa widgets. + +## Features +- basic fallback to sensible Qt types on non-OSX platforms +- shared class headers which expose no implementation details +- typical Qt signal/slot-based API +- trivial to import into projects (class header/implementation, [single shared global header](https://github.com/mikemcquaid/Qocoa/blob/master/qocoa_mac.h)) + +## Building +``` +git clone git://github.com/mikemcquaid/Qocoa.git +cd Qocoa +qmake # or cmake . +make +``` + +## Status +Qocoa classes are currently provided for NSButton, a spinning NSProgressIndicator and NSSearchField. There is a [TODO list](https://github.com/mikemcquaid/Qocoa/blob/master/TODO.md) for classes I hope to implement. + +## Usage +For each class you want to use copy the [`qocoa_mac.h`](https://github.com/mikemcquaid/Qocoa/blob/master/qocoa_mac.h), `$CLASS.h`, `$CLASS_mac.*` and `$CLASS_nonmac.*` files into your source tree and add them to your buildsystem. Examples are provided for [CMake](https://github.com/mikemcquaid/Qocoa/blob/master/CMakeLists.txt) and [QMake](https://github.com/mikemcquaid/Qocoa/blob/master/Qocoa.pro). + +## Contact +[Mike McQuaid](mailto:mike@mikemcquaid.com) + +## License +Qocoa is licensed under the [MIT License](http://en.wikipedia.org/wiki/MIT_License). +The full license text is available in [LICENSE.txt](https://github.com/mikemcquaid/Qocoa/blob/master/LICENSE.txt). + +Magnifier and EditClear icons taken from [QtCreator](http://qt-project.org/) and are licensed under the [LGPL](http://www.gnu.org/copyleft/lesser.html). + +Other icons are taken from the [Oxygen Project](http://www.oxygen-icons.org/) and are licensed under the [Creative Commons Attribution-ShareAlike 3.0 License](http://creativecommons.org/licenses/by-sa/3.0/). + +## Gallery +![Qocoa Gallery](https://github.com/mikemcquaid/Qocoa/raw/master/gallery.png) diff --git a/TODO.md b/TODO.md new file mode 100644 index 000000000..45972bafa --- /dev/null +++ b/TODO.md @@ -0,0 +1,13 @@ +Widgets I hope to implement (or at least investigate): + +- NSTokenField +- NSSegmentedControl +- NSLevelIndicator +- NSPathControl +- NSSlider (Circular) +- NSSplitView +- NSTextFinder +- NSOutlineView in an NSScrollView (Source List) +- NSDrawer +- PDFView +- WebView diff --git a/gallery.cpp b/gallery.cpp new file mode 100644 index 000000000..210821ebd --- /dev/null +++ b/gallery.cpp @@ -0,0 +1,75 @@ +#include "gallery.h" + +#include + +#include "qsearchfield.h" +#include "qbutton.h" +#include "qprogressindicatorspinning.h" + +Gallery::Gallery(QWidget *parent) : QWidget(parent) +{ + setWindowTitle("Qocoa Gallery"); + QVBoxLayout *layout = new QVBoxLayout(this); + + QSearchField *searchField = new QSearchField(this); + layout->addWidget(searchField); + + QSearchField *searchFieldPlaceholder = new QSearchField(this); + searchFieldPlaceholder->setPlaceholderText("Placeholder text"); + layout->addWidget(searchFieldPlaceholder); + + QButton *roundedButton = new QButton(this, QButton::Rounded); + roundedButton->setText("Button"); + layout->addWidget(roundedButton); + + QButton *regularSquareButton = new QButton(this, QButton::RegularSquare); + regularSquareButton->setText("Button"); + layout->addWidget(regularSquareButton); + + QButton *disclosureButton = new QButton(this, QButton::Disclosure); + layout->addWidget(disclosureButton); + + QButton *shadowlessSquareButton = new QButton(this, QButton::ShadowlessSquare); + shadowlessSquareButton->setText("Button"); + layout->addWidget(shadowlessSquareButton); + + QButton *circularButton = new QButton(this, QButton::Circular); + layout->addWidget(circularButton); + + QButton *textureSquareButton = new QButton(this, QButton::TexturedSquare); + textureSquareButton->setText("Textured Button"); + layout->addWidget(textureSquareButton); + + QButton *helpButton = new QButton(this, QButton::HelpButton); + layout->addWidget(helpButton); + + QButton *smallSquareButton = new QButton(this, QButton::SmallSquare); + smallSquareButton->setText("Gradient Button"); + layout->addWidget(smallSquareButton); + + QButton *texturedRoundedButton = new QButton(this, QButton::TexturedRounded); + texturedRoundedButton->setText("Round Textured"); + layout->addWidget(texturedRoundedButton); + + QButton *roundedRectangleButton = new QButton(this, QButton::RoundRect); + roundedRectangleButton->setText("Rounded Rect Button"); + layout->addWidget(roundedRectangleButton); + + QButton *recessedButton = new QButton(this, QButton::Recessed); + recessedButton->setText("Recessed Button"); + layout->addWidget(recessedButton); + + QButton *roundedDisclosureButton = new QButton(this, QButton::RoundedDisclosure); + layout->addWidget(roundedDisclosureButton); + +#ifdef __MAC_10_7 + QButton *inlineButton = new QButton(this, QButton::Inline); + inlineButton->setText("Inline Button"); + layout->addWidget(inlineButton); +#endif + + + QProgressIndicatorSpinning *progressIndicatorSpinning = new QProgressIndicatorSpinning(this); + progressIndicatorSpinning->animate(); + layout->addWidget(progressIndicatorSpinning); +} diff --git a/gallery.h b/gallery.h new file mode 100644 index 000000000..1e83bad94 --- /dev/null +++ b/gallery.h @@ -0,0 +1,14 @@ +#ifndef GALLERY_H +#define GALLERY_H + +#include + +class Gallery : public QWidget +{ + Q_OBJECT + +public: + explicit Gallery(QWidget *parent = 0); +}; + +#endif // WIDGET_H diff --git a/gallery.png b/gallery.png new file mode 100644 index 0000000000000000000000000000000000000000..7a2736ff572491af1fefbbface2742caceabd6e3 GIT binary patch literal 42195 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 z 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 N002ovPDHLkV1hfpIk5l$ literal 0 HcmV?d00001 diff --git a/main.cpp b/main.cpp new file mode 100644 index 000000000..835e5eb5d --- /dev/null +++ b/main.cpp @@ -0,0 +1,13 @@ +#include + +#include "gallery.h" + +int main(int argc, char *argv[]) +{ + QApplication application(argc, argv); + + Gallery gallery; + gallery.show(); + + return application.exec(); +} diff --git a/qbutton.h b/qbutton.h new file mode 100644 index 000000000..93e598f80 --- /dev/null +++ b/qbutton.h @@ -0,0 +1,49 @@ +#ifndef QBUTTON_H +#define QBUTTON_H + +#include +#include + +class QButtonPrivate; +class QButton : public QWidget +{ + Q_OBJECT +public: + // Matches NSBezelStyle + enum BezelStyle { + Rounded = 1, + RegularSquare = 2, + Disclosure = 5, + ShadowlessSquare = 6, + Circular = 7, + TexturedSquare = 8, + HelpButton = 9, + SmallSquare = 10, + TexturedRounded = 11, + RoundRect = 12, + Recessed = 13, + RoundedDisclosure = 14, +#ifdef __MAC_10_7 + Inline = 15 +#endif + }; + + explicit QButton(QWidget *parent, BezelStyle bezelStyle = Rounded); + +public slots: + void setText(const QString &text); + void setImage(const QPixmap &image); + void setChecked(bool checked); + +public: + void setCheckable(bool checkable); + bool isChecked(); + +signals: + void clicked(bool checked = false); + +private: + friend class QButtonPrivate; + QPointer pimpl; +}; +#endif // QBUTTON_H diff --git a/qbutton_mac.mm b/qbutton_mac.mm new file mode 100644 index 000000000..15490e453 --- /dev/null +++ b/qbutton_mac.mm @@ -0,0 +1,229 @@ +/* +Copyright (C) 2011 by Mike McQuaid + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "qbutton.h" + +#include "qocoa_mac.h" + +#import "Foundation/NSAutoreleasePool.h" +#import "AppKit/NSButton.h" +#import "AppKit/NSFont.h" + +class QButtonPrivate : public QObject +{ +public: + QButtonPrivate(QButton *qButton, NSButton *nsButton, QButton::BezelStyle bezelStyle) + : QObject(qButton), qButton(qButton), nsButton(nsButton) + { + switch(bezelStyle) { + case QButton::Disclosure: + case QButton::Circular: +#ifdef __MAC_10_7 + case QButton::Inline: +#endif + case QButton::RoundedDisclosure: + case QButton::HelpButton: + [nsButton setTitle:@""]; + default: + break; + } + + NSFont* font = 0; + switch(bezelStyle) { + case QButton::RoundRect: + font = [NSFont fontWithName:@"Lucida Grande" size:12]; + break; + + case QButton::Recessed: + font = [NSFont fontWithName:@"Lucida Grande Bold" size:12]; + break; + +#ifdef __MAC_10_7 + case QButton::Inline: + font = [NSFont boldSystemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]; + break; +#endif + + default: + font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]]; + break; + } + [nsButton setFont:font]; + + switch(bezelStyle) { + case QButton::Rounded: + qButton->setMinimumWidth(40); + qButton->setFixedHeight(24); + qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); + break; + case QButton::RegularSquare: + case QButton::TexturedSquare: + qButton->setMinimumSize(14, 23); + qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + break; + case QButton::ShadowlessSquare: + qButton->setMinimumSize(5, 25); + qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + break; + case QButton::SmallSquare: + qButton->setMinimumSize(4, 21); + qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + break; + case QButton::TexturedRounded: + qButton->setMinimumSize(10, 22); + qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + break; + case QButton::RoundRect: + case QButton::Recessed: + qButton->setMinimumWidth(16); + qButton->setFixedHeight(18); + qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); + break; + case QButton::Disclosure: + qButton->setMinimumWidth(13); + qButton->setFixedHeight(13); + qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); + break; + case QButton::Circular: + qButton->setMinimumSize(16, 16); + qButton->setMaximumHeight(40); + qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + break; + case QButton::HelpButton: + case QButton::RoundedDisclosure: + qButton->setMinimumWidth(22); + qButton->setFixedHeight(22); + qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); + break; +#ifdef __MAC_10_7 + case QButton::Inline: + qButton->setMinimumWidth(10); + qButton->setFixedHeight(16); + qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); + break; +#endif + } + + switch(bezelStyle) { + case QButton::Recessed: + [nsButton setButtonType:NSPushOnPushOffButton]; + case QButton::Disclosure: + [nsButton setButtonType:NSOnOffButton]; + default: + [nsButton setButtonType:NSMomentaryPushInButton]; + } + + [nsButton setBezelStyle:bezelStyle]; + } + + void clicked() + { + emit qButton->clicked(qButton->isChecked()); + } + + ~QButtonPrivate() { + [[nsButton target] release]; + [nsButton setTarget:nil]; + } + + QButton *qButton; + NSButton *nsButton; +}; + +@interface QButtonTarget : NSObject +{ +@public + QPointer pimpl; +} +-(void)clicked; +@end + +@implementation QButtonTarget +-(void)clicked { + Q_ASSERT(pimpl); + if (pimpl) + pimpl->clicked(); +} +@end + +QButton::QButton(QWidget *parent, BezelStyle bezelStyle) : QWidget(parent) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSButton *button = [[NSButton alloc] init]; + pimpl = new QButtonPrivate(this, button, bezelStyle); + + QButtonTarget *target = [[QButtonTarget alloc] init]; + target->pimpl = pimpl; + [button setTarget:target]; + + [button setAction:@selector(clicked)]; + + setupLayout(button, this); + + [button release]; + + [pool drain]; +} + +void QButton::setText(const QString &text) +{ + Q_ASSERT(pimpl); + if (!pimpl) + return; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [pimpl->nsButton setTitle:fromQString(text)]; + [pool drain]; +} + +void QButton::setImage(const QPixmap &image) +{ + Q_ASSERT(pimpl); + if (pimpl) + [pimpl->nsButton setImage:fromQPixmap(image)]; +} + +void QButton::setChecked(bool checked) +{ + Q_ASSERT(pimpl); + if (pimpl) + [pimpl->nsButton setState:checked]; +} + +void QButton::setCheckable(bool checkable) +{ + const NSInteger cellMask = checkable ? NSChangeBackgroundCellMask : NSNoCellMask; + + Q_ASSERT(pimpl); + if (pimpl) + [[pimpl->nsButton cell] setShowsStateBy:cellMask]; +} + +bool QButton::isChecked() +{ + Q_ASSERT(pimpl); + if (!pimpl) + return false; + + return [pimpl->nsButton state]; +} diff --git a/qbutton_nonmac.cpp b/qbutton_nonmac.cpp new file mode 100644 index 000000000..0a79e2baf --- /dev/null +++ b/qbutton_nonmac.cpp @@ -0,0 +1,89 @@ +/* +Copyright (C) 2011 by Mike McQuaid + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "qbutton.h" + +#include +#include +#include +#include + +class QButtonPrivate : public QObject +{ +public: + QButtonPrivate(QButton *button, QAbstractButton *abstractButton) + : QObject(button), abstractButton(abstractButton) {} + QPointer abstractButton; +}; + +QButton::QButton(QWidget *parent, BezelStyle) : QWidget(parent) +{ + QAbstractButton *button = 0; + if (qobject_cast(parent)) + button = new QToolButton(this); + else + button = new QPushButton(this); + connect(button, SIGNAL(clicked()), + this, SIGNAL(clicked())); + pimpl = new QButtonPrivate(this, button); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setMargin(0); + layout->addWidget(button); +} + +void QButton::setText(const QString &text) +{ + Q_ASSERT(pimpl); + if (pimpl) + pimpl->abstractButton->setText(text); +} + +void QButton::setImage(const QPixmap &image) +{ + Q_ASSERT(pimpl); + if (pimpl) + pimpl->abstractButton->setIcon(image); +} + +void QButton::setChecked(bool checked) +{ + Q_ASSERT(pimpl); + if (pimpl) + pimpl->abstractButton->setChecked(checked); +} + +void QButton::setCheckable(bool checkable) +{ + Q_ASSERT(pimpl); + if (pimpl) + pimpl->abstractButton->setCheckable(checkable); +} + +bool QButton::isChecked() +{ + Q_ASSERT(pimpl); + if (!pimpl) + return false; + + return pimpl->abstractButton->isChecked(); +} diff --git a/qocoa_mac.h b/qocoa_mac.h new file mode 100644 index 000000000..f8307e912 --- /dev/null +++ b/qocoa_mac.h @@ -0,0 +1,63 @@ +/* +Copyright (C) 2011 by Mike McQuaid + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include +#include +#include +#include +#include + +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) +#include +#endif + +static inline NSString* fromQString(const QString &string) +{ + const QByteArray utf8 = string.toUtf8(); + const char* cString = utf8.constData(); + return [[NSString alloc] initWithUTF8String:cString]; +} + +static inline QString toQString(NSString *string) +{ + if (!string) + return QString(); + return QString::fromUtf8([string UTF8String]); +} + +static inline NSImage* fromQPixmap(const QPixmap &pixmap) +{ +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) + CGImageRef cgImage = pixmap.toMacCGImageRef(); +#else + CGImageRef cgImage = QtMac::toCGImageRef(pixmap); +#endif + return [[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize]; +} + +static inline void setupLayout(NSView *cocoaView, QWidget *parent) +{ + parent->setAttribute(Qt::WA_NativeWindow); + QVBoxLayout *layout = new QVBoxLayout(parent); + layout->setMargin(0); + layout->addWidget(new QMacCocoaViewContainer(cocoaView, parent)); +} diff --git a/qprogressindicatorspinning.h b/qprogressindicatorspinning.h new file mode 100644 index 000000000..ae40a92a2 --- /dev/null +++ b/qprogressindicatorspinning.h @@ -0,0 +1,29 @@ +#ifndef QPROGRESSINDICATORSPINNING_H +#define QPROGRESSINDICATORSPINNING_H + +#include +#include + +class QProgressIndicatorSpinningPrivate; +class QProgressIndicatorSpinning : public QWidget +{ + Q_OBJECT +public: + // Matches NSProgressIndicatorThickness + enum Thickness { + Default = 14, + Small = 10, + Large = 18, + Aqua = 12 + }; + + explicit QProgressIndicatorSpinning(QWidget *parent, + Thickness thickness = Default); +public slots: + void animate(bool animate = true); +private: + friend class QProgressIndicatorSpinningPrivate; + QPointer pimpl; +}; + +#endif // QPROGRESSINDICATORSPINNING_H diff --git a/qprogressindicatorspinning_mac.mm b/qprogressindicatorspinning_mac.mm new file mode 100644 index 000000000..c67c7c567 --- /dev/null +++ b/qprogressindicatorspinning_mac.mm @@ -0,0 +1,70 @@ +/* +Copyright (C) 2011 by Mike McQuaid + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "qprogressindicatorspinning.h" + +#include "qocoa_mac.h" + +#import "Foundation/NSAutoreleasePool.h" +#import "AppKit/NSProgressIndicator.h" + +class QProgressIndicatorSpinningPrivate : public QObject +{ +public: + QProgressIndicatorSpinningPrivate(QProgressIndicatorSpinning *qProgressIndicatorSpinning, + NSProgressIndicator *nsProgressIndicator) + : QObject(qProgressIndicatorSpinning), nsProgressIndicator(nsProgressIndicator) {} + + NSProgressIndicator *nsProgressIndicator; +}; + +QProgressIndicatorSpinning::QProgressIndicatorSpinning(QWidget *parent, + Thickness thickness) + : QWidget(parent) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSProgressIndicator *progress = [[NSProgressIndicator alloc] init]; + [progress setStyle:NSProgressIndicatorSpinningStyle]; + + pimpl = new QProgressIndicatorSpinningPrivate(this, progress); + + setupLayout(progress, this); + + setFixedSize(thickness, thickness); + + [progress release]; + + [pool drain]; +} + +void QProgressIndicatorSpinning::animate(bool animate) +{ + Q_ASSERT(pimpl); + if (!pimpl) + return; + + if (animate) + [pimpl->nsProgressIndicator startAnimation:nil]; + else + [pimpl->nsProgressIndicator stopAnimation:nil]; +} diff --git a/qprogressindicatorspinning_nonmac.cpp b/qprogressindicatorspinning_nonmac.cpp new file mode 100644 index 000000000..6cbded6c1 --- /dev/null +++ b/qprogressindicatorspinning_nonmac.cpp @@ -0,0 +1,72 @@ +/* +Copyright (C) 2011 by Mike McQuaid + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "qprogressindicatorspinning.h" + +#include +#include +#include + +class QProgressIndicatorSpinningPrivate : public QObject +{ +public: + QProgressIndicatorSpinningPrivate(QProgressIndicatorSpinning *qProgressIndicatorSpinning, + QMovie *movie) + : QObject(qProgressIndicatorSpinning), movie(movie) {} + + QPointer movie; +}; + +QProgressIndicatorSpinning::QProgressIndicatorSpinning(QWidget *parent, + Thickness thickness) + : QWidget(parent) +{ + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setMargin(0); + + QSize size(thickness, thickness); + QMovie *movie = new QMovie(this); + movie->setFileName(":/Qocoa/qprogressindicatorspinning_nonmac.gif"); + movie->setScaledSize(size); + // Roughly match OSX speed. + movie->setSpeed(200); + pimpl = new QProgressIndicatorSpinningPrivate(this, movie); + + QLabel *label = new QLabel(this); + label->setMovie(movie); + + layout->addWidget(label); + setFixedSize(size); +} + + +void QProgressIndicatorSpinning::animate(bool animate) +{ + Q_ASSERT(pimpl && pimpl->movie); + if (!(pimpl && pimpl->movie)) + return; + + if (animate) + pimpl->movie->start(); + else + pimpl->movie->stop(); +} diff --git a/qprogressindicatorspinning_nonmac.gif b/qprogressindicatorspinning_nonmac.gif new file mode 100644 index 0000000000000000000000000000000000000000..3288d1035d70bb86517e2c233f1a904e41f06b29 GIT binary patch literal 3208 zcmc(iX;4#H9>pJdFE7h`I{IF)0|5<6L}(j=N}5%L009EB2nYfyF)E0PvIqo$u!IC; z4PgyY5|S9AEh38G)(9eq4TbH7_UHg@yWrlIJ$6smIADL7s^P;_O;ykRc9soXl`UC*LwQJXkii*0rx|*7rI2=x7WaRkx_~XZqFJ8R3c=2Kg zf@aSAv8+BJ8+^hyay>(QR@t*blbKzsf0}bscEqRc5Hd3o(-N5RyW=zWB*zQw6Zh>* z2CROCDAbu#D`)S|J_o(lL9Yn3l*+8RdiRD_>iNz$#_IAzCna&Wl5 zSF_(rRCDD!wi#i8oAm&jYtn2_@VB%2-H*G%bN#|(6R6N?wM)3u`PiGzwuX7qmTgyF zpE)h0kuoxQ9?=kW7Y!=R@DmhU9)vwT*EZWzJ zrt+=2tqFts72yIp?|gvdLhs8Hfku^Z(){gmN%Y=K#P|%fkvgUj~HfIp3CuXqCtYGtJ#me+n+-LmP( z*XNuk%!aH8bIE@_Bj46>M*dSro|7<6vZ7WUHh5YQzN$>IJFqCb|CT!wj~R2C2%=q{ zpt8rzY$aw?W?=Ustv{jo?Ow@ZRkLe<)NItY>Cyhle*wR59dTdF6(@{5^ zAQBOB*hNtc3bkY-8{Cm$nFS@elbTtSqrt7MB{h_4y+~`!mVa}?c&N>&?P}GqdMuhQ z&@TD5Czd((DcG_Su~dKKV)Pj$-qi1WHM8_vc^O4?^!oY|tmK~i!{fjd&@_1E(T~r7 z_REZy&hMT^ySJB3W7l$4YhR`M(J7S5S~+4Q&3HPa)z%zPpisOp$^ zTEe99ig2$5_qFr!$;7A6CJ}PJmRhli>w?LC}Y`#HLGy6 zMU4EhL~dKCN5Ut;U2jd*83ShBNiu zcJB0l9>1Modc?-oM<R4?}3g}UJ%@K);kriq>)e*rh%hdqM)5Q)*+O8 zXm;SEbs@koiYS!9YXIclSg+5m_s~yrW#kKMdiRszg(gCP5HPmP7L)vCf8@fxUh6qY z@Z#TmkjzAZX{rwE+q|K~F2v5{_@vt%>yT_a#fF03SFt{0RXvDAiaY~K9CgS1O>frXgAjBCS}mEd4mIWZ$=ovd5| zR?GRdU}d6+Q`+JRW)|=v7$)XNkn3yE`!nAiSCvOB1jKT zG<1aK3s<0b0m==egTD#8i(Of=1pGDTOCho0XpIOMQ&P87cVKY1W=C6kIg z9cH=@a&zbm2+`|{(_?YC9fdm?1TY~-pwlBn?>=(~1pDKbco6jloP;0-cqRiwV1A_S zEyV0Dj8Pwy!nekzaN>{)7rgZ&_QLxK{~1yRe865^yx>}+a!ECd>#MMwddow z@CU{l+Rt$xuXuf}?ga{3IAr?Raql^c@a%sI0U5m}HvJ5O1#I%_MMPt#BH>OqUZ{-k zt>4Xzz=%jT*FVW(uYkWyx}9Gw$HdN*qU?Bit#ji(Wi7p-u|_8?h^%szIS^s^fNM}b zgGy>|=cbEufpguY5_6w~&ZLv=Bo06UF9EYIY;Er-1VK)SyF&!|J{axiE1z^(hXwVq zsFS=K-#zC}CcOs^8W{KAt+kK)jYDgDYbCXv{{rwsgqtIU3<910$CJi)s?? z_t8k{>7*0~4l~LLF7$WXT5OSq5QCTbP_l!SN|{R}3D&eWA8~0ltWh1IL+ZBX4rRSt zWF6Om3WDMu4xK^1(BF`2cL}rUCzhHAB`@j5&R-yk_l*t;mPGY|u2^o|myvcOdrg0W z%=lX;f^Vkqfp?u7*4qQq%A3Mpf!xspWBSKS@O%r*TSM}?dl(@*%{0Jm_8;(h{R__M Bt + + qprogressindicatorspinning_nonmac.gif + + diff --git a/qsearchfield.h b/qsearchfield.h new file mode 100644 index 000000000..5abf4986a --- /dev/null +++ b/qsearchfield.h @@ -0,0 +1,48 @@ +#ifndef QSEARCHFIELD_H +#define QSEARCHFIELD_H + +#include +#include +#include + +class QSearchFieldPrivate; +class QSearchField : public QWidget +{ + Q_OBJECT + + Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged USER true); + Q_PROPERTY(QString placeholderText READ placeholderText WRITE setPlaceholderText); + +public: + explicit QSearchField(QWidget *parent); + + QString text() const; + QString placeholderText() const; + void setFocus(Qt::FocusReason); + void setMenu(QMenu *menu); + +public slots: + void setText(const QString &text); + void setPlaceholderText(const QString &text); + void clear(); + void selectAll(); + void setFocus(); + +signals: + void textChanged(const QString &text); + void editingFinished(); + void returnPressed(); + +private slots: + void popupMenu(); + +protected: + void changeEvent(QEvent*); + void resizeEvent(QResizeEvent*); + +private: + friend class QSearchFieldPrivate; + QPointer pimpl; +}; + +#endif // QSEARCHFIELD_H diff --git a/qsearchfield_mac.mm b/qsearchfield_mac.mm new file mode 100644 index 000000000..345ee7848 --- /dev/null +++ b/qsearchfield_mac.mm @@ -0,0 +1,262 @@ +/* +Copyright (C) 2011 by Mike McQuaid + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "qsearchfield.h" + +#include "qocoa_mac.h" + +#import "Foundation/NSAutoreleasePool.h" +#import "Foundation/NSNotification.h" +#import "AppKit/NSSearchField.h" + +#include +#include + +#define KEYCODE_A 0 +#define KEYCODE_X 7 +#define KEYCODE_C 8 +#define KEYCODE_V 9 + +class QSearchFieldPrivate : public QObject +{ +public: + QSearchFieldPrivate(QSearchField *qSearchField, NSSearchField *nsSearchField) + : QObject(qSearchField), qSearchField(qSearchField), nsSearchField(nsSearchField) {} + + void textDidChange(const QString &text) + { + if (qSearchField) + emit qSearchField->textChanged(text); + } + + void textDidEndEditing() + { + if (qSearchField) + emit qSearchField->editingFinished(); + } + + void returnPressed() + { + if (qSearchField) + emit qSearchField->returnPressed(); + } + + QPointer qSearchField; + NSSearchField *nsSearchField; +}; + +@interface QSearchFieldDelegate : NSObject +{ +@public + QPointer pimpl; +} +-(void)controlTextDidChange:(NSNotification*)notification; +-(void)controlTextDidEndEditing:(NSNotification*)notification; +@end + +@implementation QSearchFieldDelegate +-(void)controlTextDidChange:(NSNotification*)notification { + Q_ASSERT(pimpl); + if (pimpl) + pimpl->textDidChange(toQString([[notification object] stringValue])); +} + +-(void)controlTextDidEndEditing:(NSNotification*)notification { + Q_UNUSED(notification); + // No Q_ASSERT here as it is called on destruction. + if (pimpl) + pimpl->textDidEndEditing(); + + if ([[[notification userInfo] objectForKey:@"NSTextMovement"] intValue] == NSReturnTextMovement) + pimpl->returnPressed(); +} +@end + +@interface QocoaSearchField : NSSearchField +-(BOOL)performKeyEquivalent:(NSEvent*)event; +@end + +@implementation QocoaSearchField +-(BOOL)performKeyEquivalent:(NSEvent*)event { + if ([event type] == NSKeyDown && [event modifierFlags] & NSCommandKeyMask) + { + const unsigned short keyCode = [event keyCode]; + if (keyCode == KEYCODE_A) + { + [self performSelector:@selector(selectText:)]; + return YES; + } + else if (keyCode == KEYCODE_C) + { + QClipboard* clipboard = QApplication::clipboard(); + clipboard->setText(toQString([self stringValue])); + return YES; + } + else if (keyCode == KEYCODE_V) + { + QClipboard* clipboard = QApplication::clipboard(); + [self setStringValue:fromQString(clipboard->text())]; + return YES; + } + else if (keyCode == KEYCODE_X) + { + QClipboard* clipboard = QApplication::clipboard(); + clipboard->setText(toQString([self stringValue])); + [self setStringValue:@""]; + return YES; + } + } + + return NO; +} +@end + +QSearchField::QSearchField(QWidget *parent) : QWidget(parent) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSSearchField *search = [[QocoaSearchField alloc] init]; + + QSearchFieldDelegate *delegate = [[QSearchFieldDelegate alloc] init]; + pimpl = delegate->pimpl = new QSearchFieldPrivate(this, search); + [search setDelegate:delegate]; + + setupLayout(search, this); + + setFixedHeight(24); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + + [search release]; + + [pool drain]; +} + +void QSearchField::setMenu(QMenu *menu) +{ + Q_ASSERT(pimpl); + if (!pimpl) + return; + +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) + NSMenu *nsMenu = menu->macMenu(); +#else + NSMenu *nsMenu = menu->toNSMenu(); +#endif + + [[pimpl->nsSearchField cell] setSearchMenuTemplate:nsMenu]; +} + +void QSearchField::popupMenu() +{ +} + +void QSearchField::setText(const QString &text) +{ + Q_ASSERT(pimpl); + if (!pimpl) + return; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [pimpl->nsSearchField setStringValue:fromQString(text)]; + [pool drain]; +} + +void QSearchField::setPlaceholderText(const QString &text) +{ + Q_ASSERT(pimpl); + if (!pimpl) + return; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [[pimpl->nsSearchField cell] setPlaceholderString:fromQString(text)]; + [pool drain]; +} + +void QSearchField::clear() +{ + Q_ASSERT(pimpl); + if (!pimpl) + return; + + [pimpl->nsSearchField setStringValue:@""]; + emit textChanged(QString()); +} + +void QSearchField::selectAll() +{ + Q_ASSERT(pimpl); + if (!pimpl) + return; + + [pimpl->nsSearchField performSelector:@selector(selectText:)]; +} + +QString QSearchField::text() const +{ + Q_ASSERT(pimpl); + if (!pimpl) + return QString(); + + return toQString([pimpl->nsSearchField stringValue]); +} + +QString QSearchField::placeholderText() const +{ + Q_ASSERT(pimpl); + if (!pimpl) + return QString(); + + return toQString([[pimpl->nsSearchField cell] placeholderString]); +} + +void QSearchField::setFocus(Qt::FocusReason) +{ + Q_ASSERT(pimpl); + if (!pimpl) + return; + + if ([pimpl->nsSearchField acceptsFirstResponder]) + [[pimpl->nsSearchField window] makeFirstResponder: pimpl->nsSearchField]; +} + +void QSearchField::setFocus() +{ + setFocus(Qt::OtherFocusReason); +} + +void QSearchField::changeEvent(QEvent* event) +{ + if (event->type() == QEvent::EnabledChange) { + Q_ASSERT(pimpl); + if (!pimpl) + return; + + const bool enabled = isEnabled(); + [pimpl->nsSearchField setEnabled: enabled]; + } + QWidget::changeEvent(event); +} + +void QSearchField::resizeEvent(QResizeEvent *resizeEvent) +{ + QWidget::resizeEvent(resizeEvent); +} diff --git a/qsearchfield_nonmac.cpp b/qsearchfield_nonmac.cpp new file mode 100644 index 000000000..d3315b853 --- /dev/null +++ b/qsearchfield_nonmac.cpp @@ -0,0 +1,256 @@ +/* +Copyright (C) 2011 by Mike McQuaid + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "qsearchfield.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +class QSearchFieldPrivate : public QObject +{ +public: + QSearchFieldPrivate(QSearchField *searchField, QLineEdit *lineEdit, QToolButton *clearButton, QToolButton *searchButton) + : QObject(searchField), lineEdit(lineEdit), clearButton(clearButton), searchButton(searchButton) {} + + int lineEditFrameWidth() const { + return lineEdit->style()->pixelMetric(QStyle::PM_DefaultFrameWidth); + } + + int clearButtonPaddedWidth() const { + return clearButton->width() + lineEditFrameWidth() * 2; + } + + int clearButtonPaddedHeight() const { + return clearButton->height() + lineEditFrameWidth() * 2; + } + + int searchButtonPaddedWidth() const { + return searchButton->width() + lineEditFrameWidth() * 2; + } + + int searchButtonPaddedHeight() const { + return searchButton->height() + lineEditFrameWidth() * 2; + } + + QPointer lineEdit; + QPointer clearButton; + QPointer searchButton; + QPointer searchMenu; +}; + +QSearchField::QSearchField(QWidget *parent) : QWidget(parent) +{ + QLineEdit *lineEdit = new QLineEdit(this); + connect(lineEdit, SIGNAL(textChanged(QString)), + this, SIGNAL(textChanged(QString))); + connect(lineEdit, SIGNAL(editingFinished()), + this, SIGNAL(editingFinished())); + connect(lineEdit, SIGNAL(returnPressed()), + this, SIGNAL(returnPressed())); + connect(lineEdit, SIGNAL(textChanged(QString)), + this, SLOT(setText(QString))); + + int iconsize = style()->pixelMetric(QStyle::PM_SmallIconSize); + QToolButton *clearButton = new QToolButton(this); + QIcon clearIcon = QIcon::fromTheme(QLatin1String("edit-clear"), + QIcon(QLatin1String(":/Qocoa/qsearchfield_nonmac_clear.png"))); + clearButton->setIcon(clearIcon); + clearButton->setIconSize(QSize(iconsize, iconsize)); + clearButton->setFixedSize(QSize(iconsize, iconsize)); + clearButton->setStyleSheet("border: none;"); + clearButton->hide(); + connect(clearButton, SIGNAL(clicked()), this, SLOT(clear())); + + QToolButton *searchButton = new QToolButton(this); + QIcon searchIcon = QIcon(QLatin1String(":/Qocoa/qsearchfield_nonmac_magnifier.png")); + searchButton->setIcon(searchIcon); + searchButton->setIconSize(QSize(iconsize, iconsize)); + searchButton->setFixedSize(QSize(iconsize, iconsize)); + searchButton->setStyleSheet("border: none;"); + searchButton->setPopupMode(QToolButton::InstantPopup); + searchButton->setEnabled(false); + connect(searchButton, SIGNAL(clicked()), this, SLOT(popupMenu())); + + pimpl = new QSearchFieldPrivate(this, lineEdit, clearButton, searchButton); + + lineEdit->setStyleSheet(QString("QLineEdit { padding-left: %1px; padding-right: %2px; } ") + .arg(pimpl->searchButtonPaddedWidth()) + .arg(pimpl->clearButtonPaddedWidth())); + const int width = qMax(lineEdit->minimumSizeHint().width(), pimpl->clearButtonPaddedWidth() + pimpl->searchButtonPaddedWidth()); + const int height = qMax(lineEdit->minimumSizeHint().height(), + qMax(pimpl->clearButtonPaddedHeight(), + pimpl->searchButtonPaddedHeight())); + lineEdit->setMinimumSize(width, height); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setMargin(0); + layout->addWidget(lineEdit); +} + +void QSearchField::setMenu(QMenu *menu) +{ + Q_ASSERT(pimpl); + if (!pimpl) + return; + + pimpl->searchMenu = menu; + + QIcon searchIcon = menu ? QIcon(QLatin1String(":/Qocoa/qsearchfield_nonmac_magnifier_menu.png")) + : QIcon(QLatin1String(":/Qocoa/qsearchfield_nonmac_magnifier.png")); + pimpl->searchButton->setIcon(searchIcon); + pimpl->searchButton->setEnabled(isEnabled() && menu); +} + +void QSearchField::popupMenu() +{ + Q_ASSERT(pimpl); + if (!pimpl) + return; + + if (pimpl->searchMenu) { + const QRect screenRect = qApp->desktop()->availableGeometry(pimpl->searchButton); + const QSize sizeHint = pimpl->searchMenu->sizeHint(); + const QRect rect = pimpl->searchButton->rect(); + const int x = pimpl->searchButton->isRightToLeft() + ? rect.right() - sizeHint.width() + : rect.left(); + const int y = pimpl->searchButton->mapToGlobal(QPoint(0, rect.bottom())).y() + sizeHint.height() <= screenRect.height() + ? rect.bottom() + : rect.top() - sizeHint.height(); + QPoint point = pimpl->searchButton->mapToGlobal(QPoint(x, y)); + point.rx() = qMax(screenRect.left(), qMin(point.x(), screenRect.right() - sizeHint.width())); + point.ry() += 1; + + pimpl->searchMenu->popup(point); + } +} + +void QSearchField::changeEvent(QEvent* event) +{ + if (event->type() == QEvent::EnabledChange) { + Q_ASSERT(pimpl); + if (!pimpl) + return; + + const bool enabled = isEnabled(); + pimpl->searchButton->setEnabled(enabled && pimpl->searchMenu); + pimpl->lineEdit->setEnabled(enabled); + pimpl->clearButton->setEnabled(enabled); + } + QWidget::changeEvent(event); +} + +void QSearchField::setText(const QString &text) +{ + Q_ASSERT(pimpl && pimpl->clearButton && pimpl->lineEdit); + if (!(pimpl && pimpl->clearButton && pimpl->lineEdit)) + return; + + pimpl->clearButton->setVisible(!text.isEmpty()); + + if (text != this->text()) + pimpl->lineEdit->setText(text); +} + +void QSearchField::setPlaceholderText(const QString &text) +{ + Q_ASSERT(pimpl && pimpl->lineEdit); + if (!(pimpl && pimpl->lineEdit)) + return; + +#if QT_VERSION >= 0x040700 + pimpl->lineEdit->setPlaceholderText(text); +#endif +} + +void QSearchField::clear() +{ + Q_ASSERT(pimpl && pimpl->lineEdit); + if (!(pimpl && pimpl->lineEdit)) + return; + + pimpl->lineEdit->clear(); +} + +void QSearchField::selectAll() +{ + Q_ASSERT(pimpl && pimpl->lineEdit); + if (!(pimpl && pimpl->lineEdit)) + return; + + pimpl->lineEdit->selectAll(); +} + +QString QSearchField::text() const +{ + Q_ASSERT(pimpl && pimpl->lineEdit); + if (!(pimpl && pimpl->lineEdit)) + return QString(); + + return pimpl->lineEdit->text(); +} + +QString QSearchField::placeholderText() const { + Q_ASSERT(pimpl && pimpl->lineEdit); + if (!(pimpl && pimpl->lineEdit)) + return QString(); + +#if QT_VERSION >= 0x040700 + return pimpl->lineEdit->placeholderText(); +#else + return QString(); +#endif +} + +void QSearchField::setFocus(Qt::FocusReason reason) +{ + Q_ASSERT(pimpl && pimpl->lineEdit); + if (pimpl && pimpl->lineEdit) + pimpl->lineEdit->setFocus(reason); +} + +void QSearchField::setFocus() +{ + setFocus(Qt::OtherFocusReason); +} + +void QSearchField::resizeEvent(QResizeEvent *resizeEvent) +{ + Q_ASSERT(pimpl && pimpl->clearButton && pimpl->lineEdit); + if (!(pimpl && pimpl->clearButton && pimpl->lineEdit)) + return; + + QWidget::resizeEvent(resizeEvent); + const int x = width() - pimpl->clearButtonPaddedWidth(); + const int y = (height() - pimpl->clearButton->height())/2; + pimpl->clearButton->move(x, y); + + pimpl->searchButton->move(pimpl->lineEditFrameWidth() * 2, + (height() - pimpl->searchButton->height())/2); +} diff --git a/qsearchfield_nonmac.qrc b/qsearchfield_nonmac.qrc new file mode 100644 index 000000000..68b570d5b --- /dev/null +++ b/qsearchfield_nonmac.qrc @@ -0,0 +1,7 @@ + + + qsearchfield_nonmac_clear.png + qsearchfield_nonmac_magnifier_menu.png + qsearchfield_nonmac_magnifier.png + + diff --git a/qsearchfield_nonmac_clear.png b/qsearchfield_nonmac_clear.png new file mode 100644 index 0000000000000000000000000000000000000000..ec52c41bc2fbba0bcc2b30a96267d73be240dc13 GIT binary patch literal 736 zcmV<60w4W}P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igQ1 z5H}Q?5;Tqg00Ll1L_t(I%dL~KP8(SihQGOU@A%G)jYu&WzH`%nmEB~k%_)!0|LN%b|AGHm z-oG2$+uQ3>$}P|HIzosRKvh)}=iL2bvG{s(bCdlipx5iYRZ9ISrA(Dl2qAa@V2ok0 zSUehIK3`v7e|gpTKZ>>1@8dXrQ?J*FLsS(ar>K(E(Z z55w?XqtSR%uh-e%-)A2ykxBqT|~bUI}?98#7gQc7NC zTL2Qk_kDyA_`XjZ$7rp8@_S`v1>g5^&Mjw`8#w1C&N-~L#Bt1EFre9NlIJ;jp3`hL z84L!*ag4PV=N!(t$r4ai)xEVAV+`GHmo!ZokH_@;efs@ACb6=jZ2N{*lDHySr?2bF=h)KM8`M z@ne)p>7~2_ZUoUdwwqvaRgBnVYW{7Z(}7v%UkVf%q@6 SqLyO-0000Dhf?ouWA>yZ`s+BBx=){u((%TpyhhRjALHT2ckQc&d4&) z-n7Bm;H*K-pZ^kn7Mb{N&z!|jAk+T(YZimV`=g(K?qPLwkZ5DrlIwl{`;^p7iT5tI zx9yD4vv!!4s&o3#!*q*2WiQPZ0c-805^anh>)KKyITY=T68yi}@UJypmicbY)??rQ z+E&g>&)Y8jdRLLvT!xHUZR=iZbUpf-AmV!aZ=JhW=j&ZIa{LT^$CW)N?OE3SxI+54 wpr&f&y!tagmpaE@|F2cIdey48=Y>A7G=&6K*=^zp26~sl)78&qol`;+0Ic(R)c^nh literal 0 HcmV?d00001 diff --git a/qsearchfield_nonmac_magnifier_menu.png b/qsearchfield_nonmac_magnifier_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..0e652c945e4287939e4787cd02c891c50238c64a GIT binary patch literal 439 zcmV;o0Z9IdP)e+J+88IQ+ODwU{IDgdn4Yj(RG-ELPU zlgZB|=kxg)CX$;ex$!IiEsZ@$z hOGL13`%eoV{s($5(uCrFlfnQ1002ovPDHLkV1gsuzk~n) literal 0 HcmV?d00001