diff --git a/Base/etc/SystemServer.ini b/Base/etc/SystemServer.ini index 0e9727be55a..2ef12ed8c3b 100644 --- a/Base/etc/SystemServer.ini +++ b/Base/etc/SystemServer.ini @@ -81,6 +81,11 @@ Priority=low KeepAlive=1 User=anon +[ClipboardHistory.MenuApplet] +Priority=low +KeepAlive=1 +User=anon + [AudioServer] Socket=/tmp/portal/audio # TODO: we may want to start it lazily, but right now WindowServer connects to it immediately on startup diff --git a/Base/res/icons/clipboard.png b/Base/res/icons/clipboard.png new file mode 100644 index 00000000000..184c93c2856 Binary files /dev/null and b/Base/res/icons/clipboard.png differ diff --git a/MenuApplets/CMakeLists.txt b/MenuApplets/CMakeLists.txt index f8b91954686..7971326fd62 100644 --- a/MenuApplets/CMakeLists.txt +++ b/MenuApplets/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(Audio) +add_subdirectory(ClipboardHistory) add_subdirectory(Clock) add_subdirectory(ResourceGraph) add_subdirectory(UserName) diff --git a/MenuApplets/ClipboardHistory/CMakeLists.txt b/MenuApplets/ClipboardHistory/CMakeLists.txt new file mode 100644 index 00000000000..7e6bb6d763e --- /dev/null +++ b/MenuApplets/ClipboardHistory/CMakeLists.txt @@ -0,0 +1,8 @@ +set(SOURCES + ClipboardHistoryModel.cpp + IconWidget.cpp + main.cpp +) + +serenity_bin(ClipboardHistory.MenuApplet) +target_link_libraries(ClipboardHistory.MenuApplet LibGUI LibCore LibGfx) diff --git a/MenuApplets/ClipboardHistory/ClipboardHistoryModel.cpp b/MenuApplets/ClipboardHistory/ClipboardHistoryModel.cpp new file mode 100644 index 00000000000..a6c0179c47d --- /dev/null +++ b/MenuApplets/ClipboardHistory/ClipboardHistoryModel.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2019-2020, Sergey Bugaev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ClipboardHistoryModel.h" + +NonnullRefPtr ClipboardHistoryModel::create() +{ + return adopt(*new ClipboardHistoryModel()); +} + +ClipboardHistoryModel::~ClipboardHistoryModel() +{ +} + +String ClipboardHistoryModel::column_name(int column) const +{ + switch (column) { + case Column::Data: + return "Data"; + case Column::Type: + return "Type"; + default: + ASSERT_NOT_REACHED(); + } +} + +GUI::Model::ColumnMetadata ClipboardHistoryModel::column_metadata(int column) const +{ + switch (column) { + case Column::Data: + return { 200 }; + case Column::Type: + return { 100 }; + default: + ASSERT_NOT_REACHED(); + } +} + +GUI::Variant ClipboardHistoryModel::data(const GUI::ModelIndex& index, Role) const +{ + auto& data_and_type = m_history_items[index.row()]; + switch (index.column()) { + case Column::Data: + if (data_and_type.type.starts_with("text/")) + return data_and_type.data; + return "<...>"; + case Column::Type: + return data_and_type.type; + default: + ASSERT_NOT_REACHED(); + } +} + +void ClipboardHistoryModel::update() +{ + did_update(); +} + +void ClipboardHistoryModel::add_item(const GUI::Clipboard::DataAndType& item) +{ + m_history_items.prepend(item); + update(); +} diff --git a/MenuApplets/ClipboardHistory/ClipboardHistoryModel.h b/MenuApplets/ClipboardHistory/ClipboardHistoryModel.h new file mode 100644 index 00000000000..5f1357563fb --- /dev/null +++ b/MenuApplets/ClipboardHistory/ClipboardHistoryModel.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019-2020, Sergey Bugaev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include +#include + +class ClipboardHistoryModel final : public GUI::Model { +public: + static NonnullRefPtr create(); + + enum Column { + Data, + Type, + __Count + }; + + virtual ~ClipboardHistoryModel() override; + + const GUI::Clipboard::DataAndType& item_at(int index) const { return m_history_items[index]; } + void add_item(const GUI::Clipboard::DataAndType& item); + +private: + virtual int row_count(const GUI::ModelIndex&) const override { return m_history_items.size(); } + virtual String column_name(int) const override; + virtual GUI::Model::ColumnMetadata column_metadata(int column) const override; + virtual int column_count(const GUI::ModelIndex&) const override { return Column::__Count; } + virtual GUI::Variant data(const GUI::ModelIndex&, Role = Role::Display) const override; + virtual void update() override; + + Vector m_history_items; +}; diff --git a/MenuApplets/ClipboardHistory/IconWidget.cpp b/MenuApplets/ClipboardHistory/IconWidget.cpp new file mode 100644 index 00000000000..bf95cf1f7d9 --- /dev/null +++ b/MenuApplets/ClipboardHistory/IconWidget.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019-2020, Sergey Bugaev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "IconWidget.h" +#include + +IconWidget::IconWidget() +{ + set_icon(Gfx::Bitmap::load_from_file("/res/icons/clipboard.png")); + set_fill_with_background_color(true); +} + +IconWidget::~IconWidget() +{ +} + +void IconWidget::mousedown_event(GUI::MouseEvent&) +{ + if (on_click) + on_click(); +} diff --git a/MenuApplets/ClipboardHistory/IconWidget.h b/MenuApplets/ClipboardHistory/IconWidget.h new file mode 100644 index 00000000000..3b96c88f3db --- /dev/null +++ b/MenuApplets/ClipboardHistory/IconWidget.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019-2020, Sergey Bugaev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include + +class IconWidget : public GUI::Label { + C_OBJECT(IconWidget) +public: + IconWidget(); + virtual ~IconWidget() override; + + Function on_click; + +private: + virtual void mousedown_event(GUI::MouseEvent&) override; +}; diff --git a/MenuApplets/ClipboardHistory/main.cpp b/MenuApplets/ClipboardHistory/main.cpp new file mode 100644 index 00000000000..39e961a3511 --- /dev/null +++ b/MenuApplets/ClipboardHistory/main.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2019-2020, Sergey Bugaev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ClipboardHistoryModel.h" +#include "IconWidget.h" +#include +#include +#include + +int main(int argc, char* argv[]) +{ + GUI::Application app(argc, argv); + + auto main_window = GUI::Window::construct(); + main_window->set_title("Clipboard history"); + main_window->set_rect(670, 65, 325, 500); + + auto& table_view = main_window->set_main_widget(); + auto model = ClipboardHistoryModel::create(); + table_view.set_model(model); + + GUI::Clipboard::the().on_change = [&](const String&) { + auto item = GUI::Clipboard::the().data_and_type(); + model->add_item(item); + }; + + table_view.on_activation = [&](const GUI::ModelIndex& index) { + auto& data_and_type = model->item_at(index.row()); + GUI::Clipboard::the().set_data(data_and_type.data, data_and_type.type); + }; + + auto applet_window = GUI::Window::construct(); + applet_window->set_title("Clipboard history"); + applet_window->set_window_type(GUI::WindowType::MenuApplet); + auto& icon = applet_window->set_main_widget(); + icon.on_click = [&main_window = *main_window] { + main_window.show(); + }; + applet_window->resize(16, 16); + applet_window->show(); + + return app.exec(); +}