diff --git a/desktop/org.kde.spectacle.appdata.xml b/desktop/org.kde.spectacle.appdata.xml index 246ee33..3b8f4fd 100644 --- a/desktop/org.kde.spectacle.appdata.xml +++ b/desktop/org.kde.spectacle.appdata.xml @@ -1,352 +1,353 @@ org.kde.spectacle.desktop CC0-1.0 GPL-2.0+ Spectacle Spectacle Spectacle Spectacle Spectacle Spectacle Spectacle Spectacle Spectacle Spectacle Spectacle Spectacle Spectacle Spectacle Spectacle Spectacle Spectacle Spectacle Spectacle Spectacle Spectacle Spectacle Spectacle Spectacle Spectacle Спектакл Spectacle Спектакл Spectacle Spectacle Spectacle Spectacle xxSpectaclexx Spectacle Spectacle Screenshot Capture Utility Utilitat per prendre captures de pantalla Utilitat per prendre captures de pantalla Nástroj na snímání obrazovky Dienstprogramm für Bildschirmfotos Εργαλείο συλληψης στιγμιοτύπων Screenshot Capture Utility Utilidad para capturar pantallas Pantaila-argazkiak atzemateko baliagarritasuna Ruutukaappaustyökalu Utilitaire de capture d'écran Utilidade para facer capturas de pantalla Utilitate de captura de instantaneo Utilitas Tangkap Cuplikanlayar Accessorio per catturare schermate 화면 캡처 유틸리티 Hulpmiddel voor het maken van een schermafdruk Verktøy for å lagra skjermbilete Narzędzie do przechwytywania ekranu Utilitário de Captura de Imagens Utilitário de captura de tela Nástroj na zachytávanie obrazovky Pripomoček za zajem zaslona Алатка за снимке екрана Alatka za snimke ekrana Алатка за снимке екрана Alatka za snimke ekrana Verktyg för att ta skärmbilder Ekran Görüntüsü Yakalama Aracı Програма для створення знімків вікон xxScreenshot Capture Utilityxx 截图抓取工具 畫面擷取工具

Spectacle is a simple application for capturing desktop screenshots. It can capture images of the entire desktop, a single monitor, the currently active window, the window currently under the mouse, or a rectangular region of the screen. The images can then be printed, sent to other applications for manipulation, or quickly be saved as-is.

L'Spectacle és una aplicació per a prendre captures de pantalla de l'escriptori. Pot capturar imatges de tot l'escriptori, un sol monitor, la finestra activa, la finestra sota el ratolí o d'una regió rectangular de la pantalla. Les imatges es poden imprimir, enviar a altres aplicacions per a la seva manipulació o desar-les com estan.

L'Spectacle és una aplicació per a prendre captures de pantalla de l'escriptori. Pot capturar imatges de tot l'escriptori, un sol monitor, la finestra activa, la finestra sota el ratolí o d'una regió rectangular de la pantalla. Les imatges es poden imprimir, enviar a altres aplicacions per a la seua manipulació o guardar-les com estan.

Spectacle ist eine einfache Anwendung für Aufnahmen des Bildschirms der Arbeitsfläche. Sie können die gesamte Arbeitsfläche, einen einzelnen Bildschirm, das zur Zeit aktive Fenster, das Fenster unter der Maus oder einen rechteckigen Bereich des Bildschirms aufnehmen. Die Aufnahmen können Sie drucken, mit anderen Anwendungen zur Bearbeitung öffnen oder direkt speichern.

Το Spectacle είναι μια απλή εφαρμογή σύλληψης στιγμιοτύπων της επιφάνειας εργασίας. Συλλαμβάνει εικόνες όλης της επιφάνειας εργασίας, μιας οθόνης, του τρέχοντος ενεργού παραθύρου, του τρέχοντος παραθύρου κάτω από το ποντίκι ή μια ορθογώνια περιοχή της οθόνης. Οι εικόνες μπορούν να εκτυπωθούν, να αποσταλλούν σε άλλες εφαρμογές για επεξεργασία, ή να αποθηκευτούν γρήγορα ως έχουν.

Spectacle is a simple application for capturing desktop screenshots. It can capture images of the entire desktop, a single monitor, the currently active window, the window currently under the mouse, or a rectangular region of the screen. The images can then be printed, sent to other applications for manipulation, or quickly be saved as-is.

Spectacle es una sencilla aplicación para realizar capturas de pantalla del escritorio. Puede capturar imágenes de todo el escritorio, de un único monitor, de la ventana activa actual, de la ventana que esté bajo el cursor o de un área rectangular de la pantalla. Las imágenes se pueden imprimir, enviar a otras aplicaciones para su procesamiento o guardar en el disco de forma inmediata.

Spectacle on lihtne ekraanipiltide tegemise rakendus. See võib pildistada tervet töölauda, konkreetset monitori, parajasti aktiivset akent, hiire all olevat akent või ekraanil valitud ristkülikukujulist osa. Tehtud pilte saab trükkida, saata töötlemiseks teistesse rakendustesse või ka lihtsalt kiiresti ja muutmata salvestada.

Spectacle mahaiganeko argazkiak atzemateko aplikazio erraz bat da. Mahaigain osoaren irudiak atzeman ditzake, monitore bakarrarena, unean aktibo dagoen leihoarena, saguaren azpiko leihoarena, edo pantailaren azalera laukizuzen batena. Irudiak inprimatu daitezke, eraldatuak izan daitezen beste aplikazioetara bidali, edo daudenean gorde.

Spectacle on yksinkertainen sovellus ruutukaappauskuvien ottamiseksi. Se voi kaapata kuvan koko työpöydältä, yksittäiseltä näytöltä, aktiivisesta ikkunasta, hiiren alla olevasta ikkunasta tai suorakulmaisesta näytön alueesta. Kuvat voi myöhemmin tulostaa, lähettää muihin sovelluksiin käsiteltäväksi tai tallentaa sellaisinaan.

Spectable est une application simple permettant la réalisation de captures d'écran. L'application permet la capture d'images du bureau complet, d'un unique moniteur, de la fenêtre se trouvant sous le pointeur, ou du région rectangulaire de l'écran. Les images peuvent être imprimées, envoyées vers d'autres applications pour y être manipulées, ou rapidement enregistrées telles-quelles.

Spectacle é un aplicativo sinxelo para capturar a pantalla do escritorio. Pode capturar imaxes de todo o escritorio, un único monitor, a xanela activa, a xanela baixo o rato, ou unha zona rectangular da pantalla. As imaxes poden imprimirse, enviarse a otros aplicativos para manipulalas, ou gardalas rapidamente tal cal.

Spectacle adalah aplikasi sederhana untuk menangkap cuplikanlayar desktop. Hal ini bisa menangkap gambar dari seluruh desktop, monitor tunggal, jendela yang sedang aktif, jendela saat ini yang sedang di bawah mouse, atau bidang persegi pada layar. Gambar kemudian bisa di-print, dikirim ke aplikasi lain untuk manipulasi, atau secara cepat disimpan sebagai apa.

Spectacle è una semplice applicazione per catturare schermate. Può acquisire immagini dell'intero desktop, di un singolo monitor, della finestra attiva, della finestra sotto il puntatore del mouse, o di una regione rettangolare dello schermo. Le immagini possono essere stampate, inviate ad altre applicazioni per essere modificate, o salvate rapidamente così come sono.

Spectacle은 데스크톱 스크린샷을 찍는 프로그램입니다. 전체 데스크톱, 단일 모니터, 활성 창, 마우스 아래 창, 화면의 사각형 영역을 찍을 수 있습니다. 사진을 인쇄하거나, 그대로 저장하거나, 다른 프로그램에서 곧바로 편집할 수 있습니다.

Spectacle is een eenvoudige toepassing voor het opnemen van schermafbeeldingen van het bureaublad. Het kan afbeeldingen van het gehele bureaublad, een enkele monitor, het nu actieve venster, het venster nu onder de muis of een rechthoekig gebied van het scherm. De afbeelding kan dan afgedrukt worden, naar een andere toepassing voor bewerking worden verzonden of snel worden opgeslagen zoals deze nu is.

Spectacle er eit enkelt program for å ta skjermbilete. Det kan ta bilete av heile skrivebordet, ein einskild skjerm, det gjeldande vindauget, vindauget under musepeikaren eller eit utsnitt av skjermflata. Bileta kan skrivast ut, sendast til andre program for vidare arbeid eller lagrast direkte.

Spectacle to prosta aplikacja do wykonywania zrzutów ekranu. Za jej pomocą można przechwycić cały pulpit, pojedynczy monitor, obecnie aktywne okno, okno obecnie pod wskaźnikiem myszy lub prostokątny obszar ekrany. Zrzuty można wydrukować, wysłać do innej aplikacji do obróbki lub szybko zapisać tak jak go wykonano.

O Spectacle é uma aplicação simples para capturar imagens do ecrã. Pode capturar imagens de todo o ecrã, de um único monitor, da janela activa no momento, da janela sob o cursor do rato ou de uma região rectangular do ecrã. As imagens poderão então ser impressas, enviadas para outras aplicações para posterior manipulação ou serem gravadas como estão.

Spectacle é um aplicativo simples para capturar imagens da tela. É capaz de capturar imagens da tela inteira, de apenas um monitor, da janela ativa, da janela que estiver sob o ponteiro do mouse ou de uma região retangular. As imagens podem ser impressas, enviadas para outros aplicativos ou salvas em diversos formatos.

Spectacle — простая программа для создания снимков экрана (скриншотов). Она позволяет делать снимки всех экранов, отдельного экрана, текущего или выбранного окна и прямоугольных областей на экране. Далее снимок можно напечатать, открыть в других приложениях или сохранить в файл нажатием одной кнопки.

Spectacle je jednoduchá aplikácia na snímanie plochy. Dokáže zachytiť obrázky celej plochy, jedného monitora, aktívneho okna, okna pod myšou alebo pravouhlej oblasti obrazovky. Obrázky sa dajú tlačiť, poslať do inej aplikácie na manipuláciu alebo rýchlo uložiť tak, ako sú.

Spectacle je preprost program za zajemanje zaslonskih slik namizja. Zajame lahko slike celotnega namizja, enega zaslona, trenutno dejavnega okna, okna pod miško ali pravokotnega območja pod miško. Te slike lahko nato natisnete, pošljete v druge programe ali pa hitro shranite.

Спектакл је једноставан програм за хватање снимака екрана. Може да сними целу површ, један монитор, тренутно активни прозор, прозор тренутно под мишем, или правоугаону зону екрана. Слике могу да се штампају, шаљу у друге програме на обраду или брзо сачувају такве какве су.

Spectacle je jednostavan program za hvatanje snimaka ekrana. Može da snimi celu površ, jedan monitor, trenutno aktivni prozor, prozor trenutno pod mišem, ili pravougaonu zonu ekrana. Slike mogu da se štampaju, šalju u druge programe na obradu ili brzo sačuvaju takve kakve su.

Спектакл је једноставан програм за хватање снимака екрана. Може да сними целу површ, један монитор, тренутно активни прозор, прозор тренутно под мишем, или правоугаону зону екрана. Слике могу да се штампају, шаљу у друге програме на обраду или брзо сачувају такве какве су.

Spectacle je jednostavan program za hvatanje snimaka ekrana. Može da snimi celu površ, jedan monitor, trenutno aktivni prozor, prozor trenutno pod mišem, ili pravougaonu zonu ekrana. Slike mogu da se štampaju, šalju u druge programe na obradu ili brzo sačuvaju takve kakve su.

Spectacle är ett enkelt program för att ta skärmbilder av skrivbordet. Det kan ta bilder av hela skrivbordet, en enda bildskärm, fönstret som för närvarande är aktivt, fönstret som för närvarande är under musen, eller ett rektangulärt skärmområde. Bilderna kan därefter skrivas ut, skickas till andra program för behandling, eller snabbt sparas som de är.

Spectacle, masaüstü ekran görüntüleri yakalamak için basit bir araçtır. Tüm masaüstü, tek bir ekran, geçerli pencere, fare altındaki pencere veya ekrandaki dikdörtgen bir bölge yakalayabilir. Resimler ardından yazdırılabilir, değiştirilmek üzere diğer uygulamalara gönderilebilir veya olduğu gibi kaydedilebilir.

Spectacle — проста програма для створення знімків екрана. Передбачено можливість захоплення знімків усієї стільниці, окремого монітора, поточного активного вікна, вікна під вказівником миші або прямокутної ділянки на екрані. Створені зображення можна надрукувати, надіслати до іншої програми для обробки або зберегти без змін.

xxSpectacle is a simple application for capturing desktop screenshots. It can capture images of the entire desktop, a single monitor, the currently active window, the window currently under the mouse, or a rectangular region of the screen. The images can then be printed, sent to other applications for manipulation, or quickly be saved as-is.xx

Spectacle 是一个用于抓取桌面截图的简单应用程序。它可以抓取整个桌面、单个显示器、当前活动窗口、鼠标所在的窗口或是屏幕上的一块方形区域的图像。这些图像稍后便可以用于打印、向其它应用程序发送以进行进一步操作或是直接保存下来。

Spectale 是一個用來擷取桌面快照的簡易應用程式。它可以擷取整個桌面、單一個顯示器、目前作用中的視窗、目前滑鼠底下的的視窗或是螢幕上的矩形區域等。其所擷取的圖片可以被列印、傳送到其他應用程式以供進一步操作或是快速儲存而不進行修改。

Features:

Característiques:

Característiques:

Vlastnosti:

Funktionen:

Χαρακτηριστικά:

Features:

Funciones:

Omadused:

Eginbideak:

Ominaisuuksia:

Fonctionnalités :

Funcionalidades:

תכונות

Characteristicas:

Fitur:

Funzionalità:

기능:

Mogelijkheden:

Funksjonar:

Możliwości:

Funcionalidades:

Recursos:

Возможности:

Funkcie:

Zmožnosti:

Могућности:

Mogućnosti:

Могућности:

Mogućnosti:

Funktioner:

Özellikler:

Можливості:

xxFeatures:xx

功能:

功能:

Spectacle after taking a screenshot L'Spectacle després de prendre una captura de pantalla L'Spectacle després de prendre una captura de pantalla Spectacle tras realizar una captura Spectacle après une capture d'écran + Spectacle dopo la cattura di una schermata Spectacle na nemen van een schermafdruk Spectacle etter å ha teke eit skjermbilete O Spectacle após capturar uma imagem O Spectacle após a captura de uma imagem Spectacle efter en skärmbild har tagits Spectacle після створення знімка xxSpectacle after taking a screenshotxx 拍下螢幕快照後開啟 Spetacle http://kde.org/images/screenshots/spectacle.png http://kde.org/applications/graphics/spectacle/ https://bugs.kde.org/enter_bug.cgi?format=guided&product=spectacle KDE spectacle
diff --git a/src/QuickEditor/EditorRoot.qml b/src/QuickEditor/EditorRoot.qml index 10560ab..361538b 100644 --- a/src/QuickEditor/EditorRoot.qml +++ b/src/QuickEditor/EditorRoot.qml @@ -1,632 +1,618 @@ /* * Copyright (C) 2016 Boudhayan Gupta * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ import QtQuick 2.5 import QtQuick.Window 2.2 import QtQuick.Layouts 1.3 import QtQuick.Controls 1.4 Item { id: editorRoot; objectName: "editorRoot"; // properties and setters property var selection: undefined; property color maskColour: Qt.rgba(0, 0, 0, 0.15); property color strokeColour: systemPalette.highlight; property color crossColour: Qt.rgba(strokeColour.r, strokeColour.g, strokeColour.b, 0.7); property color labelBackgroundColour: Qt.rgba(systemPalette.light.r, systemPalette.light.g, systemPalette.light.b, 0.85); property bool showMagnifier: false; property bool toggleMagnifier: false; property int magZoom: 5; property int magPixels: 16; property int magOffset: 32; property double largeChange: 15; property double smallChange: 1 / Screen.devicePixelRatio; + property bool resize: false; // toggle for resize versus move actions SystemPalette { id: systemPalette; } function setInitialSelection(xx, yy, ww, hh) { if (selection) { selection.destroy(); } selection = cropRectangle.createObject(parent, { "x": xx, "y": yy, "height": hh, "width": ww }); cropDisplayCanvas.requestPaint(); } function accept() { if (selection) { acceptImage(selection.x, selection.y, selection.width, selection.height); } else { acceptImage(-1, -1, -1, -1); } } // key handlers focus: true; Keys.onReturnPressed: accept() Keys.onEnterPressed: accept() Keys.onEscapePressed: { cancelImage(); } Keys.onPressed: { - var change; + const screenMaxX = cropDisplayCanvas.width; + const screenMaxY = cropDisplayCanvas.height; + const minRectHeight = 20; + const minRectWidth = 20; // shift key alone = magnifier toggle if (event.modifiers & Qt.ShiftModifier) { toggleMagnifier = true; } // nested switches for arrow keys based on modifier keys switch(event.modifiers) { case Qt.NoModifier: + resize = false; switch (event.key) { case Qt.Key_Left: - change = checkBounds(-largeChange, 0.0, "left"); - selection.x += change; + moveSizeRect(-largeChange, 0.0, "left"); break; case Qt.Key_Right: - change = checkBounds(largeChange, 0.0, "right"); - selection.x += change; + moveSizeRect(largeChange, 0.0, "right"); break; case Qt.Key_Up: - change = checkBounds(0.0, -largeChange, "up"); - selection.y += change; + moveSizeRect(0.0, -largeChange, "up"); break; case Qt.Key_Down: - change = checkBounds(0.0, largeChange, "down"); - selection.y += change; + moveSizeRect(0.0, largeChange, "down"); break; } - break; // end no modifier (just arrows) + break; // end no modifier (just arrows - large move) case Qt.ShiftModifier: + resize = false; switch (event.key) { case Qt.Key_Left: - change = checkBounds(-smallChange, 0.0, "left"); - selection.x += change; + moveSizeRect(-smallChange, 0.0, "left"); break; case Qt.Key_Right: - change = checkBounds(smallChange, 0.0, "right"); - selection.x += change; + moveSizeRect(smallChange, 0.0, "right"); break; case Qt.Key_Up: - change = checkBounds(0.0, -smallChange, "up"); - selection.y += change; + moveSizeRect(0.0, -smallChange, "up"); break; case Qt.Key_Down: - change = checkBounds(0.0, smallChange, "down"); - selection.y += change; + moveSizeRect(0.0, smallChange, "down"); break; } - break; // end Shift + arrows (large move) + break; // end Shift + arrows (small move) case Qt.AltModifier: + resize = true; switch (event.key) { case Qt.Key_Left: - change = checkBounds(-largeChange, 0.0, "left"); - if (selection.width + change <= 0.0) { - selection.width = 0.0; - } else { - selection.width += change; - } + moveSizeRect(-largeChange, 0.0, "left"); break; case Qt.Key_Right: - change = checkBounds(largeChange, 0.0, "right"); - selection.width += change; + moveSizeRect(largeChange, 0.0, "right"); break; case Qt.Key_Up: - change = checkBounds(0.0, -largeChange, "up"); - if (selection.height + change <= 0.0) { - selection.height = 0.0; - } else { - selection.height += change; - } + moveSizeRect(0.0, -largeChange, "up"); break; case Qt.Key_Down: - change = checkBounds(0.0, largeChange, "down"); - selection.height = selection.height + change; + moveSizeRect(0.0, largeChange, "down"); break; } - break; // end ALT + arrows (resize rectangle) + break; // end ALT + arrows (resize rectangle - large change) case (Qt.ShiftModifier + Qt.AltModifier): + resize = true; switch (event.key) { case Qt.Key_Left: - change = checkBounds(-smallChange, 0.0, "left"); - if (selection.width + change <= 0.0) { - selection.width = 0.0; - } else { - selection.width += change; - } + moveSizeRect(-smallChange, 0.0, "left"); break; case Qt.Key_Right: - change = checkBounds(smallChange, 0.0, "right"); - selection.width += change; + moveSizeRect(smallChange, 0.0, "right"); break; case Qt.Key_Up: - change = checkBounds(0.0, -smallChange, "up"); - if (selection.height + change <= 0.0) { - selection.height = 0.0; - } else { - selection.height += change - } + moveSizeRect(0.0, -smallChange, "up"); break; case Qt.Key_Down: - change = checkBounds(0.0, smallChange, "down"); - selection.height += change; + moveSizeRect(0.0, smallChange, "down"); break; } - break; // end Shift + ALT + arrows (large resize rectangle) + break; // end Shift + ALT + arrows (small resize rectangle) } - // all switches done; repaint on any keypress - cropDisplayCanvas.requestPaint(); - - function checkBounds(changeX, changeY, direction) { - - var leftEdge = selection.x; - var rightEdge = selection.x + selection.width; - var topEdge = selection.y; - var bottomEdge = selection.y + selection.height; - const screenMaxX = cropDisplayCanvas.width; - const screenMaxY = cropDisplayCanvas.height; + function moveSizeRect(changeX, changeY, direction) { + var action; var newX; var newY; + var newRight; + var newBottom; + + switch (resize) { + case false: // move + + switch (direction) { + case "left": + newX = selection.x += changeX; + action = (newX >= 0.0) ? selection.x = newX : selection.x = 0.0; + break; + case "right": + newRight = (selection.x + selection.width) + changeX; + action = (newRight <= screenMaxX) ? selection.x += changeX : selection.x = screenMaxX - selection.width; + break; + case "up": + newY = selection.y += changeY; + action = (newY >= 0.0) ? selection.y = newY : selection.y = 0.0; + break; + case "down": + newBottom = selection.y + selection.height + changeY; + action = (newBottom <= screenMaxY) ? selection.y = selection.y + changeY : selection.y = screenMaxY - selection.height; + break; + } - var overlap; - - newX = selection.x + changeX; - newY = selection.y + changeY; - - switch (direction) { - - case "left": - if (leftEdge + changeX > 0.0) { - return changeX; - } - - if (leftEdge + changeX < 0.0) { - return -leftEdge; - } - break; - - case "right": - newX = newX + selection.width; - if (newX < screenMaxX) { - return changeX; - } - if (newX > screenMaxX) { - overlap = newX - screenMaxX; - return changeX - overlap; - } break; - - case "up": - if (topEdge + changeY > 0.0) { - return changeY; - } else { - return -topEdge; - } - - case "down": - newY = newY + selection.height; - if (newY < screenMaxY) { - return changeY; - } - if (newY > screenMaxY) { - overlap = newY - screenMaxY; - return changeY - overlap; + // end of movement switch cases + + + case true: // resizing rectangle + + switch (direction) { + case "left": + newX = selection.width += changeX; + if (newX <= minRectWidth) { + selection.width = minRectWidth; + break; + } + action = (newX >= 0.0) ? selection.width + changeX : selection.x = 0.0; + break; + + case "right": + newX = selection.width += changeX + action = (newX <= screenMaxX) ? selection.width + changeX : selection.width = (selection.x + screenMaxX); + break; + + case "up": + newY = selection.height += changeY; + if (newY <= minRectHeight) { + selection.height = minRectHeight; + break; + } + action = (newY >= 0.0) ? selection.height = newY : selection.y = 0.0; + break; + + case "down": + newY = selection.height += changeY; + action = (newY <= screenMaxY) ? selection.height + changeY : selection.height = (selection.y + screenMaxY); + break; } - break; } } + + // all switches done; repaint on any keypress + cropDisplayCanvas.requestPaint(); + } // end Keys.onPressed Keys.onReleased: { if (toggleMagnifier && !(event.modifiers & Qt.ShiftModifier)) { toggleMagnifier = false; cropDisplayCanvas.requestPaint(); } } // signals signal acceptImage(int x, int y, int width, int height); signal cancelImage(); Image { id: imageBackground; objectName: "imageBackground"; source: "image://snapshot/rawimage"; cache: false; height: Window.height / Screen.devicePixelRatio; width: Window.width / Screen.devicePixelRatio; fillMode: Image.PreserveAspectFit; } Canvas { id: cropDisplayCanvas; objectName: "cropDisplayCanvas"; anchors.fill: imageBackground; renderTarget: Canvas.FramebufferObject; renderStrategy: Canvas.Cooperative; onPaint: { // start by getting a context on the canvas and clearing it var ctx = cropDisplayCanvas.getContext("2d"); ctx.clearRect(0, 0, cropDisplayCanvas.width, cropDisplayCanvas.height); // set up the colours ctx.strokeStyle = strokeColour; ctx.fillStyle = maskColour; // draw a sheet over the whole screen ctx.fillRect(0, 0, cropDisplayCanvas.width, cropDisplayCanvas.height); if (selection) { midHelpText.visible = false; // display bottom help text only if it does not intersect with the selection bottomHelpText.visible = (selection.y + selection.height < bottomHelpText.y) || (selection.x > bottomHelpText.x + bottomHelpText.width) || (selection.x + selection.width < bottomHelpText.x); // if we have a selection polygon, cut it out ctx.fillStyle = strokeColour; ctx.fillRect(selection.x, selection.y, selection.width, selection.height); ctx.clearRect(selection.x + 1, selection.y + 1, selection.width - 2, selection.height - 2); if ((selection.width > 20) && (selection.height > 20)) { // top-left handle ctx.beginPath(); ctx.arc(selection.x, selection.y, 8, 0, 0.5 * Math.PI); ctx.lineTo(selection.x, selection.y); ctx.fill(); // top-right handle ctx.beginPath(); ctx.arc(selection.x + selection.width, selection.y, 8, 0.5 * Math.PI, Math.PI); ctx.lineTo(selection.x + selection.width, selection.y); ctx.fill(); // bottom-left handle ctx.beginPath(); ctx.arc(selection.x + selection.width, selection.y + selection.height, 8, Math.PI, 1.5 * Math.PI); ctx.lineTo(selection.x + selection.width, selection.y + selection.height); ctx.fill(); // bottom-right handle ctx.beginPath(); ctx.arc(selection.x, selection.y + selection.height, 8, 1.5 * Math.PI, 2 * Math.PI); ctx.lineTo(selection.x, selection.y + selection.height); ctx.fill(); // top-center handle ctx.beginPath(); ctx.arc(selection.x + selection.width / 2, selection.y, 5, 0, Math.PI); ctx.fill(); // right-center handle ctx.beginPath(); ctx.arc(selection.x + selection.width, selection.y + selection.height / 2, 5, 0.5 * Math.PI, 1.5 * Math.PI); ctx.fill(); // bottom-center handle ctx.beginPath(); ctx.arc(selection.x + selection.width / 2, selection.y + selection.height, 5, Math.PI, 2 * Math.PI); ctx.fill(); // left-center handle ctx.beginPath(); ctx.arc(selection.x, selection.y + selection.height / 2, 5, 1.5 * Math.PI, 0.5 * Math.PI); ctx.fill(); } // Set the selection size and finds the most appropriate position: // - vertically centered inside the selection if the box is not covering the a large part of selection // - on top of the selection if the selection x position fits the box height plus some margin // - at the bottom otherwise // Note that text is drawn starting from the left bottom! var selectionText = Math.round(selection.width * Screen.devicePixelRatio) + "x" + Math.round(selection.height * Screen.devicePixelRatio); selectionTextMetrics.font = ctx.font; selectionTextMetrics.text = selectionText; var selectionTextRect = selectionTextMetrics.boundingRect; var selectionBoxX = Math.max(0, selection.x + (selection.width - selectionTextRect.width) / 2); var selectionBoxY; if ((selection.width > 100) && (selection.height > 100)) { // show inside the box selectionBoxY = selection.y + (selection.height + selectionTextRect.height) / 2; } else if (selection.y >= selectionTextRect.height + 8) { // show on top selectionBoxY = selection.y - 8; } else { // show at the bottom selectionBoxY = selection.y + selection.height + selectionTextRect.height + 4; } // Now do the actual box, border and text drawing ctx.fillStyle = systemPalette.window; ctx.strokeStyle = systemPalette.windowText; ctx.fillRect(selectionBoxX - 4, selectionBoxY - selectionTextRect.height - 2, selectionTextRect.width + 10, selectionTextRect.height + 8); ctx.strokeRect(selectionBoxX - 4, selectionBoxY - selectionTextRect.height - 2, selectionTextRect.width + 10, selectionTextRect.height + 8); ctx.fillStyle = systemPalette.windowText; ctx.fillText(selectionText, selectionBoxX, selectionBoxY); if (selection.zoomCenterX >= 0 && selection.zoomCenterY >= 0 && (showMagnifier ^ toggleMagnifier)) { var offsetX = magOffset; var offsetY = magOffset; var magX = selection.zoomCenterX; var magY = selection.zoomCenterY; var magWidth = crossMagnifier.width; var magHeight = crossMagnifier.height; if (magX + offsetX + magWidth >= Window.width / Screen.devicePixelRatio) { offsetX -= offsetX * 2 + magWidth; } if (magY + offsetY + magHeight >= Window.height / Screen.devicePixelRatio) { offsetY -= offsetY * 2 + magHeight; } magX += offsetX; magY += offsetY; crossMagnifier.visible = true; crossMagnifier.x = magX; crossMagnifier.y = magY; crossBackground.x = -selection.zoomCenterX * Screen.devicePixelRatio * magZoom + magPixels * magZoom; crossBackground.y = -selection.zoomCenterY * Screen.devicePixelRatio * magZoom + magPixels * magZoom; ctx.strokeRect(magX, magY, magWidth, magHeight); } else { crossMagnifier.visible = false; } } else { midHelpText.visible = true; bottomHelpText.visible = false; crossMagnifier.visible = false; } } TextMetrics { id: selectionTextMetrics } Rectangle { id: midHelpText; objectName: "midHelpText"; height: midHelpTextElement.height + 40; width: midHelpTextElement.width + 40; radius: 4; border.color: systemPalette.windowText; color: labelBackgroundColour; visible: false; anchors.centerIn: parent; - Label { + TextLabel { id: midHelpTextElement; text: i18n("Click anywhere to start drawing a selection rectangle,\n" + "or press Esc to cancel."); font.pixelSize: Qt.application.font.pixelSize * 1.2; anchors.centerIn: parent; } } Rectangle { id: bottomHelpText; objectName: "bottomHelpText"; height: bottomHelpTextElement.height + 20; width: bottomHelpTextElement.width + 20; radius: 4; border.color: systemPalette.windowText; color: labelBackgroundColour; visible: false; anchors.bottom: parent.bottom; anchors.horizontalCenter: parent.horizontalCenter; GridLayout { id: bottomHelpTextElement; columns: 2 anchors.centerIn: parent; - Label { + TextLabel { text: i18n("Enter, double-click:"); Layout.alignment: Qt.AlignRight; } - Label { text: i18n("Take screenshot"); } + TextLabel { text: i18n("Take screenshot"); } - Label { + TextLabel { text: i18n("Shift:"); - Layout.alignment: Qt.AlignRight; + Layout.alignment: Qt.AlignRight | Qt.AlignTop; } - Label { text: i18n("Hold to toggle magnifier"); } + TextLabel { text: i18n("Hold to toggle magnifier \n" + + "while dragging selection handles"); } - Label { + TextLabel { text: i18n("Arrow keys:"); Layout.alignment: Qt.AlignRight | Qt.AlignTop; } - Label { text: i18n("Move selection rectangle \n" + - "Hold Alt to resize, Shift to fine-tune"); } + TextLabel { text: i18n("Move selection rectangle \n" + + "Hold Alt to resize, Shift to fine-tune"); } - Label { + TextLabel { text: i18n("Right-click:"); Layout.alignment: Qt.AlignRight; } - Label { text: i18n("Reset selection"); } + TextLabel { text: i18n("Reset selection"); } - Label { + TextLabel { text: i18n("Esc:"); Layout.alignment: Qt.AlignRight; } - Label { text: i18n("Cancel"); } + TextLabel { text: i18n("Cancel"); } } } // Use Rectangle so that the background is white when cursor nearby edge Rectangle { id: crossMagnifier; height: (magPixels * 2 + 1) * magZoom; width: height; border.width: 0; visible: false; clip: true Image { id: crossBackground; source: "image://snapshot/rawimage"; smooth: false; height: Window.height * magZoom; width: Window.width * magZoom; } Rectangle { x: magPixels * magZoom; y: 0; width: magZoom; height: magPixels * magZoom; color: crossColour; } Rectangle { x: magPixels * magZoom; y: (magPixels + 1) * magZoom; width: magZoom; height: magPixels * magZoom; color: crossColour; } Rectangle { x: 0; y: magPixels * magZoom; width: magPixels * magZoom; height: magZoom; color: crossColour; } Rectangle { x: (magPixels + 1) * magZoom; y: magPixels * magZoom; width: magPixels * magZoom; height: magZoom; color: crossColour; } } } MouseArea { anchors.fill: imageBackground; property int startx: 0; property int starty: 0; cursorShape: Qt.CrossCursor; acceptedButtons: Qt.LeftButton | Qt.RightButton; onPressed: { if (selection) { selection.destroy(); } startx = mouse.x; starty = mouse.y; selection = cropRectangle.createObject(parent, { "x": startx, "y": starty, "height": 0, "width": 0 }); } onPositionChanged: { selection.x = Math.min(startx, mouse.x); selection.y = Math.min(starty, mouse.y); selection.width = Math.abs(startx - mouse.x) + 1; selection.height = Math.abs(starty - mouse.y) + 1; selection.zoomCenterX = mouse.x; selection.zoomCenterY = mouse.y; cropDisplayCanvas.requestPaint(); } onClicked: { if ((mouse.button == Qt.RightButton) && (selection)) { selection.destroy(); cropDisplayCanvas.requestPaint(); } } onReleased: { selection.zoomCenterX = -1; selection.zoomCenterY = -1; cropDisplayCanvas.requestPaint(); } } Component { id: cropRectangle; SelectionRectangle { drawCanvas: cropDisplayCanvas; imageElement: imageBackground; onDoubleClicked: editorRoot.accept() } } } diff --git a/src/QuickEditor/QmlResources.qrc b/src/QuickEditor/QmlResources.qrc index 48d8b6c..dd113be 100644 --- a/src/QuickEditor/QmlResources.qrc +++ b/src/QuickEditor/QmlResources.qrc @@ -1,6 +1,7 @@ EditorRoot.qml SelectionRectangle.qml + TextLabel.qml diff --git a/src/QuickEditor/TextLabel.qml b/src/QuickEditor/TextLabel.qml new file mode 100644 index 0000000..95d1232 --- /dev/null +++ b/src/QuickEditor/TextLabel.qml @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 Henrik Fehlauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +// Only Qt Quick Controls 2 supports fractional scaling of Labels, +// therefore here we use Text and set the text colour manually. + +Text { + color: systemPalette.text; +}