diff --git a/src/gui/qocoa/.gitignore b/src/gui/qocoa/.gitignore new file mode 100644 index 000000000..4963d2730 --- /dev/null +++ b/src/gui/qocoa/.gitignore @@ -0,0 +1,2 @@ +cmake/ +qmake/ \ No newline at end of file diff --git a/src/gui/qocoa/CMakeLists.txt b/src/gui/qocoa/CMakeLists.txt new file mode 100644 index 000000000..513f81f7d --- /dev/null +++ b/src/gui/qocoa/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/src/gui/qocoa/LICENSE.txt b/src/gui/qocoa/LICENSE.txt new file mode 100644 index 000000000..910eb6d20 --- /dev/null +++ b/src/gui/qocoa/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/src/gui/qocoa/Qocoa.pro b/src/gui/qocoa/Qocoa.pro new file mode 100644 index 000000000..8b325d192 --- /dev/null +++ b/src/gui/qocoa/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/src/gui/qocoa/README.md b/src/gui/qocoa/README.md new file mode 100644 index 000000000..3d37b6a27 --- /dev/null +++ b/src/gui/qocoa/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/src/gui/qocoa/TODO.md b/src/gui/qocoa/TODO.md new file mode 100644 index 000000000..45972bafa --- /dev/null +++ b/src/gui/qocoa/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/src/gui/qocoa/gallery.cpp b/src/gui/qocoa/gallery.cpp new file mode 100644 index 000000000..210821ebd --- /dev/null +++ b/src/gui/qocoa/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/src/gui/qocoa/gallery.h b/src/gui/qocoa/gallery.h new file mode 100644 index 000000000..1e83bad94 --- /dev/null +++ b/src/gui/qocoa/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/src/gui/qocoa/gallery.png b/src/gui/qocoa/gallery.png new file mode 100644 index 000000000..7a2736ff5 Binary files /dev/null and b/src/gui/qocoa/gallery.png differ diff --git a/src/gui/qocoa/main.cpp b/src/gui/qocoa/main.cpp new file mode 100644 index 000000000..835e5eb5d --- /dev/null +++ b/src/gui/qocoa/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/src/gui/qocoa/qbutton.h b/src/gui/qocoa/qbutton.h new file mode 100644 index 000000000..93e598f80 --- /dev/null +++ b/src/gui/qocoa/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/src/gui/qocoa/qbutton_mac.mm b/src/gui/qocoa/qbutton_mac.mm new file mode 100644 index 000000000..15490e453 --- /dev/null +++ b/src/gui/qocoa/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/src/gui/qocoa/qbutton_nonmac.cpp b/src/gui/qocoa/qbutton_nonmac.cpp new file mode 100644 index 000000000..0a79e2baf --- /dev/null +++ b/src/gui/qocoa/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/src/gui/qocoa/qocoa_mac.h b/src/gui/qocoa/qocoa_mac.h new file mode 100644 index 000000000..f8307e912 --- /dev/null +++ b/src/gui/qocoa/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/src/gui/qocoa/qprogressindicatorspinning.h b/src/gui/qocoa/qprogressindicatorspinning.h new file mode 100644 index 000000000..ae40a92a2 --- /dev/null +++ b/src/gui/qocoa/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/src/gui/qocoa/qprogressindicatorspinning_mac.mm b/src/gui/qocoa/qprogressindicatorspinning_mac.mm new file mode 100644 index 000000000..c67c7c567 --- /dev/null +++ b/src/gui/qocoa/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/src/gui/qocoa/qprogressindicatorspinning_nonmac.cpp b/src/gui/qocoa/qprogressindicatorspinning_nonmac.cpp new file mode 100644 index 000000000..6cbded6c1 --- /dev/null +++ b/src/gui/qocoa/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/src/gui/qocoa/qprogressindicatorspinning_nonmac.gif b/src/gui/qocoa/qprogressindicatorspinning_nonmac.gif new file mode 100644 index 000000000..3288d1035 Binary files /dev/null and b/src/gui/qocoa/qprogressindicatorspinning_nonmac.gif differ diff --git a/src/gui/qocoa/qprogressindicatorspinning_nonmac.qrc b/src/gui/qocoa/qprogressindicatorspinning_nonmac.qrc new file mode 100644 index 000000000..108c78ec1 --- /dev/null +++ b/src/gui/qocoa/qprogressindicatorspinning_nonmac.qrc @@ -0,0 +1,5 @@ + + + qprogressindicatorspinning_nonmac.gif + + diff --git a/src/gui/qocoa/qsearchfield.h b/src/gui/qocoa/qsearchfield.h new file mode 100644 index 000000000..5abf4986a --- /dev/null +++ b/src/gui/qocoa/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/src/gui/qocoa/qsearchfield_mac.mm b/src/gui/qocoa/qsearchfield_mac.mm new file mode 100644 index 000000000..345ee7848 --- /dev/null +++ b/src/gui/qocoa/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/src/gui/qocoa/qsearchfield_nonmac.cpp b/src/gui/qocoa/qsearchfield_nonmac.cpp new file mode 100644 index 000000000..d3315b853 --- /dev/null +++ b/src/gui/qocoa/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/src/gui/qocoa/qsearchfield_nonmac.qrc b/src/gui/qocoa/qsearchfield_nonmac.qrc new file mode 100644 index 000000000..68b570d5b --- /dev/null +++ b/src/gui/qocoa/qsearchfield_nonmac.qrc @@ -0,0 +1,7 @@ + + + qsearchfield_nonmac_clear.png + qsearchfield_nonmac_magnifier_menu.png + qsearchfield_nonmac_magnifier.png + + diff --git a/src/gui/qocoa/qsearchfield_nonmac_clear.png b/src/gui/qocoa/qsearchfield_nonmac_clear.png new file mode 100644 index 000000000..ec52c41bc Binary files /dev/null and b/src/gui/qocoa/qsearchfield_nonmac_clear.png differ diff --git a/src/gui/qocoa/qsearchfield_nonmac_magnifier.png b/src/gui/qocoa/qsearchfield_nonmac_magnifier.png new file mode 100644 index 000000000..ad7929d2b Binary files /dev/null and b/src/gui/qocoa/qsearchfield_nonmac_magnifier.png differ diff --git a/src/gui/qocoa/qsearchfield_nonmac_magnifier_menu.png b/src/gui/qocoa/qsearchfield_nonmac_magnifier_menu.png new file mode 100644 index 000000000..0e652c945 Binary files /dev/null and b/src/gui/qocoa/qsearchfield_nonmac_magnifier_menu.png differ